DEV Community

Cover image for XCode, Opam, PNPM, Node, Esy, Docker, ReactNative on 128GB Mac
Alain
Alain

Posted on • Edited on

XCode, Opam, PNPM, Node, Esy, Docker, ReactNative on 128GB Mac

image is borrowed from rietti.com

The Problem

I have hit a hard wall trying to develop with OCaml/ReasonML/Docker/Esy etc. This stack will get you fast app but the build environment is brutally disk space heavy.

I had a bunch of scripts that clean up my computer every night. The scripts deleted every React Native related file, clean the simulator out, deleted all node modules in my working directories and the ~/.esy and ~/.pnpm cache directories on my machine. I could usually get back to about 20-30GB to start my next day of coding.

This worked for a while until I tried to work on a pull request on the esy/esy. Building esy got me down to about 3GB of space which makes it super slow to work on this mac.

Solution (so far)

  1. Get a Samsung Portable SSD T5. After trying to figure out which drive would be best for this purpose, I ended up with this one, basically because @jaapfrolich said so. And if he says so, then it probably right. Luckily, that was enough justification in this case.

  2. Set environmental variables so that the programs eating up the disk space eat up external drive space instead.

You can set the default root directories to something different for all of the above programs. The first thing I did was change the name of my ssd drive to SSD because its easier to type than Samsung Portable SSD T5. I then create an enviromental variable for my external drive using the fish shell.

set -Ux SSD /Volumes/SSD
Enter fullscreen mode Exit fullscreen mode

I then set my roots:

PNPM & NPM

For pnpm, I run:

 [I] ➜ npm config set store-dir $SSD/.pnpm-store
 [I] ➜ npm config set prefix $SSD/.npm
Enter fullscreen mode Exit fullscreen mode

Then test it on a random project to check where the pnpm cache is being generated:

// run ls first to see that there is no `.pnpm-store` directory
 [I] ➜ ls
Containers/       .fnm/        .opam/
Github/           .fseventsd/ .Spotlight-V100/  .npm/        .DS_Store
 [I] ➜ bsb -init test-pnpm-store -theme basic-reason
 [I] ➜ cd test-pnpm-store 
 [I] ➜ pnpm i
 [I] ➜ cd /Volumes/SSD
 [I] ➜ ls
Containers/       .fnm/        .opam/
Github/           .fseventsd/  .pnpm-store/
.Spotlight-V100/  .npm/        .DS_Store

 [I] ➜ /Volumes/SSD
Enter fullscreen mode Exit fullscreen mode

We can see that the .pnpm-store directory was created on our external ssd drive. So that works.

ESY

For ESY__PREFIX

// set root for esy.
/Volumes/SSD
[I] ➜ set -Ux ESY__PREFIX $SSD/.esy
/Volumes/SSD
 [I] ➜ echo $ESY__PREFIX
/Volumes/SSD/.esy
Enter fullscreen mode Exit fullscreen mode

I wanted to use .esyrc because it seems cleaner but I could not get it to work.

OPAM

For OPAMROOT. There are apparently a few ways to do this per the man-pages but I could not get them to work so for now we stick with @etiennemillon's suggestion on discuss.ocaml.org. Thank you @etiennemillon.

Be sure to run opam init after you have set the root.

// set opam root
[I] ➜set -Ux OPAMROOT $SSD/.opam
~/Downloads took 2m 52s 87ms
[I] ➜ echo $OPAMROOT
/Volumes/SSD/.opam
[I] ➜ opam init
Enter fullscreen mode Exit fullscreen mode

FNM

I am using the excellent Schniz/fnm node package manager. Mostly because I was loyal to ReasonML. Now it written in Rust but the support there is still ReasonML level friendly and responsive so, fnm it is.

@galstar, who built fnm, says that I just need to change my fish.config to source the directory where I want the cache to be with

// $HOME/.config/fish/config.fish
fnm env --fnm-dir="$SSD/.fnm" | source
Enter fullscreen mode Exit fullscreen mode

DOCKER

For Docker, make a directory on your ssd for Docker to use to store images and whatever else it stores. Here I have named it Containers because that is what @frankrietta's rietta.com almost right on point blog post says. The blog doesn't use Macos Catalina but its totally worth the read anyway.

/Volumes/SSD
 [I] ➜ mkdir /Volumes/SSD/Containers
Enter fullscreen mode Exit fullscreen mode

Assuming you have already installed Docker, open the dashboard:

Alt Text

Click the settings icon to the left of the upgrade button:

Alt Text

Then the resources tab in the menu:

Alt Text

Then change the disk image location directory to the directory you created above.

Alt Text

After you click apply changes, you should be good to go.

Now lets test it by running some random project that uses all these build tools. For that I'll use @davesnx's reason-in-barcelona/async. I am going to clone it to a folder not on my ssd to see how this goes.

[I] ➜ cd ~/Downloads
[I] ➜ git clone https://github.com/reason-in-barcelona/async.git reason-in-barcelona
 [I] ➜ cd reason-in-barcelona/
direnv: loading ~/Downloads/reason-in-barcelona/.envrc
direnv: export +ASYNC_PG_PORT +DATABASE_URL

Enter fullscreen mode Exit fullscreen mode

The project requires watchexec and direnv so make sure you have those installed.

Now let's run make dev from the Makefile and see if this worked.

[I] ➜ make dev
...
∗ installed core.v0.14.0
Done.
# Run eval (opam env) to update the current shell environment
opam install -y ocaml-lsp-server dune

<><> Synchronising pinned packages ><><><><><><><><><><><><><><><><><><><><>  🐫
[ocaml-lsp-server.dev] no changes from git+https://github.com/ocaml/ocaml-lsp.git#HEAD

[NOTE] Package dune is already installed (current version is 2.8.2).
[NOTE] Package ocaml-lsp-server is already installed (current version is dev).
make install
# Install the dependencies
opam install --deps-only --with-doc --with-test -y .
Nothing to do.
# Run eval (opam env) to update the current shell environment
Enter fullscreen mode Exit fullscreen mode

That looks like it worked, thankfully. Let see what happens when we try to build the local db with docker by running docker-compose -f docker-compose.dev.yml up -d.

docker-compose -f docker-compose.dev.yml up -d
reason-in-barcelona on  main is 📦 v0.1.0 via ⬢ v14.15.4 is 🐳 v20.10.2
 [I] ➜ docker-compose -f docker-compose.dev.yml up -d
Creating network "reason-in-barcelona_default" with the default driver
Creating volume "reason-in-barcelona_db-data" with default driver
Creating volume "reason-in-barcelona_pgadmin-data" with default driver
Pulling db (postgres:12.2)...
12.2: Pulling from library/postgres
54fec2fa59d0: Pull complete
30a95add0890: Pull complete
57bc798d3c84: Pull complete
a41bedb2c5de: Pull complete
589548c3abb4: Pull complete
c4c6b75d5deb: Pull complete
8f8c045a6a99: Pull complete
69f9dd86b24d: Pull complete
45bbaba740ff: Pull complete
1761ca7befa0: Pull complete
57feb34018f4: Pull complete
bede8373accc: Pull complete
6e4c69fbe63b: Pull complete
8a7949704ab2: Pull complete
Digest: sha256:d96835c9032988c8a899cb8a3c54467dae81daaa99485de70e8c9bddd5432d92
Status: Downloaded newer image for postgres:12.2
Pulling pgadmin (dpage/pgadmin4:4.18)...
4.18: Pulling from dpage/pgadmin4
89d9c30c1d48: Pull complete
910c49c00810: Pull complete
7efe415eb85a: Pull complete
7d8d53519b81: Pull complete
519124ac136c: Pull complete
fbfa5cf626f8: Pull complete
f53a64187e16: Pull complete
feae0c230730: Pull complete
87ae2307a1ad: Pull complete
0a609eb1a1ca: Pull complete
b8bb05efc354: Pull complete
bccaa4da228f: Pull complete
084101fb937a: Pull complete
774874c72d7a: Pull complete
45a1fa7f66b7: Pull complete
b19cea40abf6: Pull complete
76e3d6803955: Pull complete
Digest: sha256:1141073018353f91953c1523f170821e139dbd1c2d7808d3804962b2ba7e89e3
Status: Downloaded newer image for dpage/pgadmin4:4.18
Creating reason-in-barcelona_db_1 ... done
Creating reason-in-barcelona_pgadmin_1 ... done

reason-in-barcelona on  main is 📦 v0.1.0 via ⬢ v14.15.4 is 🐳 v20.10.2 took 1m 3s 441ms
 [I] ➜
Enter fullscreen mode Exit fullscreen mode

That also works! And my primary disk space is unaffected. Big win.

Testing Esy

I guess I should have said go get a coffee because the previous steps take so long. You have to pay for the fast and typed end product by taking the time to install your ocaml build env...

As I ran that command I realized that the project doesn't use esy so I am going run the quickstart steps from the esy.sh to test the esy setup.

Since I deleted my .fnm before I started this process I am going I need to reinstall esy.

[I] ➜ npm i -g esy@next
[I] ➜ git clone https://github.com/esy-ocaml/hello-reason.git
[I] ➜ cd hello-reason
hello-reason on  master is 📦 v0.1.0 via ⬢ v14.15.4
 [I] ➜ esy
fish: Unknown command: esy
Enter fullscreen mode Exit fullscreen mode

Running esy does not work. Apparently, my environment does not know that it is there. Anyone know what is going on here? I have posted this in the discussion for esy@next here. I will get back to you all when I figure this out.

Update:

I used my trusty go to debugging method, just trying stuff, which got us esy working. At the very beginning, I got cute and ran npm config set prefix $SSD/.npm which resulted in out $HOME/.npmrc file looking like this:

store-dir=/Volumes/SSD/.pnpm-store
prefix=/Volumes/SSD/.npm
Enter fullscreen mode Exit fullscreen mode

When I read the output from npm i -g @esy@next I saw a bunch of symlinks. I have learned the hard way over the years that symlinks are not always your friend. I removed prefix=/Volumes/SSD/.npm from .npmrc, ran npm i -g esy@next again, then running esy in the hello-reason directory worked.

hello-reason on  master is 📦 v0.1.0 via ⬢ v14.15.4
 [I] ➜ cat package.json | jq '.scripts'
{
  "test": "esy x Hello",
  "format": "esy dune build @fmt --auto-promote",
  "doc": "esy dune build @doc"
}

hello-reason on  master is 📦 v0.1.0 via ⬢ v14.15.4
 [I] ➜ esy test
Running Test Program:
Hello, World!
Enter fullscreen mode Exit fullscreen mode

If your run ls in your external volume, you will see that that esy is using it to cache files.

/Volumes/SSD
 [I] ➜ ls
Containers/  .Spotlight-V100/  .fnm/        .npm/   .pnpm-store/
Github/      .esy/             .fseventsd/  .opam/  .DS_Store

Enter fullscreen mode Exit fullscreen mode

I should probably delete the .npm dir.

Let see if there are any other issues. I find that there is usually some quirk that show up later on so I am sure I will be back.

XCode

XCode is the master of all disk space hoarders. Dealing with XCode and Esy/OCaml's disk space was the point of this excersize and when I went to use this set up, I realized I had forgotten about Xcode.

This is what I did to get this going.

First, read this stackoverflow issue -> https://stackoverflow.com/questions/59159232/can-i-install-xcode-on-an-external-hard-drive-along-with-the-iphone-simulator-ap/65683543#comment116453766_65683543

There are a bunch of good bits in there though the author says he doesnt vouch for it with XCode 12.

Here is how I did it for XCode 12.

Go to https://developer.apple.com/download/more/?q=xcode, sign in if you have to and select the version of XCode you want. I selected the latest stable version which was XCode12.3.

Alt Text

If you have space issue, which is why you are reading this, you will want to download this to your ssd. I set my browser download location to my SSD drive and double clicked on XCode12.3.zip. This takes a while as you know.

I then deleted the old XCode with CleanMyMac. You can do without it from the terminal with:

rm -rf ~/Library/Developer/Xcode
rm -fr /Applications/Xcode.app
Enter fullscreen mode Exit fullscreen mode

Then you want to symlink Xcode from your ssd to your ~/Applications directory.

ln -s /Volumes/SSD/Applications/Xcode.app /Applications/Xcode.app
Enter fullscreen mode Exit fullscreen mode

Set up the simulator by

Important! Double Click XCode to open it so that it prompts you accept the license. If you dont do this, when you have symlinked the simulator it will just silently shutdown.

After you have accepted the license you can close Xcode which will have opened.

Tell XCode which XCode to use:

 [I] ➜ sudo xcode-select --switch /Volumes/SSD/Applications/Xcode.app
Enter fullscreen mode Exit fullscreen mode

Tell XCode which xcode-select to use:

sudo xcode-select -s /Volumes/SSD/Applications/Xcode.app/Contents/Developer
Enter fullscreen mode Exit fullscreen mode

Set up the simulator by aliasing the simulator on your ssd into your applications. I am only using the IPhone simulator so I did the following. Go to the Simulator on your ssd which should be at /Volumes/SSD/Applications/Xcode.app/Contents/Developer/Applications/Simulator.app. Right click it and select Make Alias:
Alt Text

Copy/Drag that to ~/Applications.
Alt Text

Now if you go into some project and run react-native run-ios it should be good to go.

I hope this help you all with limited disk space trying to do too much with your limited tools like I am.

You can also set a custom path for Library/Developer/Xcode/DerivedData and Library/Developer/Xcode/Archives via Xcode -> Preferences -> Locations.

Alt Text

Now download the version you might need via Xcode -> Preferences -> Components or via the Xcode app:

Alt Text

Hopefully these are now being installed in our custom directory on our external SSD.

This also seems to work: https://www.simpleswiftguide.com/how-to-add-missing-iphone-se-simulator-in-xcode-11-with-ios-13-sdks/

Stay tuned.

Other Tips

Top comments (0)