Setting up Opam and MirageOS on MacOS Ventura, on Apple Silicon

Aryan Godara
4 min readJul 16, 2023

--

The OCaml logo in png format with transparent background.
OCaml: Functional Programming Language

Setting up Ocaml and fixing the dependency install error using SymLinks, on MacOS M1/M2

1. Install Opam

To install Opam, you can use your system package manager (Homebrew, MacPort, etc.) or download the binary from the Source.

# With Homebrew:
$ brew install opam
# With MacPort:
$ port install opam

And if you’re feeling brave, and don’t trust your package manager to serve you the latest version, use the direct binary distribution link ;)

$ bash -c "sh <(curl -fsSL https://raw.githubusercontent.com/ocaml/opam/master/shell/install.sh)"

2. Initialize Opam

$ opam init # Takes some time
$ eval $(opam env)

This is an important step, so pay attention.

opam init initializes the opam state (stored in ~/.opam ). It also initializes the default switch (conveniently called default).
A switch is similar to a Python environment (one you create using virtualenv); it’s an independent OCaml environment with its own OCaml compiler and a unique set of libraries and binaries.
This is important as you might not want to create a mess in your global environment, or in some cases, the dependency versions supported by different applications are in conflict.

I suffered with the same issue during my time at Outreachy, when mirageOS supported v4.x.x of OCaml, but the latest available stable version was v5.0.0
So my advice is to always “create new switches when starting big projects”

If you install Ocaml using homebrew, etc., the default switch will be set up to use this compiler (it is called a “system switch”). Otherwise it will build one from source, usually taking the most recent version of OCaml.

eval $(opam env) modifies a few environment variables to make your shell (zsh or bash) aware of the switch you are using; it’ll add what is needed to the PATH variable.

Now, check the installation using opam --version .

2. Creating a new opam switch

$ opam switch create v4.14.0.  # Just the version
OR
$ opam switch create cardioproj ocaml.5.0.0 # Specify name and version
$ eval $(opam env)

Now, opam init already sets up a default switch for you to work in. But if you want an independent environment, or to use a different version of ocaml, you can create your own custom switch, and preferably, even give it a name.
To check if the installation was successful, try this

$ which ocaml
/Users/aryan/.opam/cardioproj/bin/ocaml
$ ocaml --version
The OCaml toplevel, version 5.0.0

Learn more about toplevel/utop here.

Installing dependencies

Now this is the tricky part if you are using macOS with the latest Apple Silicon chips, the M1 and the M2.

I had an issue due to the default save locations of homebrew which were different for intel and apple chips; and the default expected locations of dependencies, or even install location were different for the apple chips compared to their intel counterparts even when using unix based systems.

How I lost 2 days of my time trying to fix these errors.

But good news I found a fix. And if you want to delve into this issue further, here are the links for the resources I used to find the fix :-

  1. https://stackoverflow.com/questions/71129114/unable-to-install-ocaml-on-macos-mac-m1
  2. https://github.com/rakyll/portmidi/issues/13
  3. https://sourceforge.net/p/portmedia/wiki/Installing_portmidi_on_Linux/
  4. https://stackoverflow.com/questions/35337601/why-is-there-a-usr-local-opt-directory-created-by-homebrew-and-should-i-use-it
  5. https://apple.stackexchange.com/questions/410825/apple-silicon-port-all-homebrew-packages-under-usr-local-opt-to-opt-homebrew

But in short, the issue has to do with the storage location of Homebrew packages; and to fix this, you just need to create SysLinks between the directories identified by traditional Unix software and the directories created on the new apple silicon chip using architectures (wow, that’s a mouthful).

$ sudo ln -s /opt/homebrew/include/ /usr/local/include
$ sudo ln -s /opt/homebrew/lib /usr/local/lib

And this is it, now you can freely install dependcies on using Opam.

As a challenge, let’s see if can follow the steps to run Cardio Crumble, using the instructions in the README.

Running Hello World in MirageOS

The MirageOS logo in png format with transparent background.
MirageOS: Unikernel written in OCaml

Now, the best way to test our progress is to see if we can get mirageOS to run on our system; this will prove that OCaml is working just fine, and installation of dependencies using Opam is not an issue anymore :)

Just follow this guide to run hello world on Mirage, to confirm that your installation now works properly.

--

--

Aryan Godara

Hi, I'm a student at IIT D, India. My passions include all things tech-related, pc gaming cuz Indian parents don't like gaming consoles :( and playing guitar :3