Spoonfeeding machine architecture to OCaml toolchain on Apple Silicon§
Written by Jayesh Bhoot Published on
Problem§
OCaml compiler failed to build on my M1 Macbook with Apple's Silicon architecture.
$ opam switch create . 4.14.1 -y --deps-only
<><> Installing new switch packages <><><><><><><><><><><><><><><><><><><><> π«
Switch invariant: ["ocaml-base-compiler" {= "4.14.1"} | "ocaml-system" {= "4.14.1"}]
[NOTE] External dependency handling not supported for OS family 'macos'.
You can disable this check using 'opam option --global depext=false'
<><> Processing actions <><><><><><><><><><><><><><><><><><><><><><><><><><> π«
β installed base-bigarray.base
β installed base-threads.base
β installed base-unix.base
β installed ocaml-options-vanilla.1
β¬ retrieved ocaml-base-compiler.4.14.1 (cached)
[ERROR] The compilation of ocaml-base-compiler.4.14.1 failed at
"make -j7".
#=== ERROR while compiling ocaml-base-compiler.4.14.1 ===========#
# context 2.1.5 | macos/arm64 | | https://opam.ocaml.org#bc52affc
# path ~/projects/aoc-2023/ocaml/_opam/.opam-switch/build/ocaml-base-compiler.4.14.1
# command ~/.opam/opam-init/hooks/sandbox.sh build make -j7
# exit-code 2
# env-file ~/.opam/log/ocaml-base-compiler-11985-7b627b.env
# output-file ~/.opam/log/ocaml-base-compiler-11985-7b627b.out
### output ###
# [...]
# signals_nat.c:221:5: error: no member named '__pc' in 'struct __darwin_x86_thread_state64'
# CONTEXT_PC = (context_reg) &caml_stack_overflow;
# ^~~~~~~~~~
# ./signals_osdep.h:182:37: note: expanded from macro 'CONTEXT_PC'
# #define CONTEXT_PC (CONTEXT_STATE.__pc)
# ~~~~~~~~~~~~~ ^
# 4 errors generated.
# make[3]: *** [signals_nat.n.o] Error 1
# make[3]: *** Waiting for unfinished jobs....
# make[2]: *** [makeruntimeopt] Error 2
# make[1]: *** [opt.opt] Error 2
# make: *** [world.opt] Error 2
<><> Error report <><><><><><><><><><><><><><><><><><><><><><> π«
ββ The following actions failed
β Ξ» build ocaml-base-compiler 4.14.1
ββ
ββ The following changes have been performed (the rest was aborted)
β β install base-bigarray base
β β install base-threads base
β β install base-unix base
β β install ocaml-options-vanilla 1
ββ
<><> ocaml-base-compiler.4.14.1 troubleshooting <><><><><><><> π«
=> A failure in the middle of the build may be caused by build
parallelism
(enabled by default).
Please file a bug report at
https://github.com/ocaml/opam-repository/issues
=> You can try installing again including --jobs=1
to force a sequential build instead.
Switch initialisation failed: clean up? ('n' will leave the
switch partially installed) [Y/n] y
Hacky solution§
If you have the same issue, then try specifying the architecture explicitly.
$ arch -arm64 opam switch create . 4.14.1 -y --deps-only
Apply the same approach to install packages too.
$ arch -arm64 opam install dune
There has to be a better way though.
P.S.: Even dune does not work without it!
$ arch -arm64 dune exec bin/main.exe
Update () : Better solution§
JM from OCaml discord helped me to discover the underlying issue - my Terminal.app was running in Rosetta mode. I had configured it to run on Rosetta during the initial Silicon-Rosetta churn, but forgotten all about it.
So, opam, which uses uname -a
to find the
underlying architecture, always got x86_64
.
Once I unchecked the Open using Rosetta option, arch -arm64
was no longer needed.
From what I understand, if any tool or binary across a
toolchain is configured to run through Rosetta - be it the Terminal.app, or the shell, or a helper binary like uname
- then the program using this toolchain could end up using the wrong architecture.