Is it possible to build a "universal binary" of erlang on macOS (ARM/Intel)?

I could not find a configure option, for this. Basically I would like to build erlang as a Universal Binary on macOS. Is it currently supported by the build-system?

Background: We are currently upgrading our Mac-Application to support Apple M1 (ARM) native, as part of the application we have a part running in erlang, which basically launches erlang as a process.

4 Likes

There is no direct support for it, but after briefly looking at the link you provided it should be possible (though not trivial) to build the arm and x86 releases separately and then merge them using lipo. That is something like this:

./configure CFLAGS="-g -O2 -target x86_64-apple-macos10.12" LDFLAGS="-target x86_64-apple-macos10.12"
make
make release RELEASE_ROOT=`pwd`/x86_release
git clean -Xfdq
./configure CFLAGS="-g -O2 -target arm64-apple-macos11" LDFLAGS="-target arm64-apple-macos11"
make
make release RELEASE_ROOT=`pwd`/arm_release

and then run lipo -create -output universal_app for each native binary found in the respective releases. Not sure what has to be done about dynamic libraries.

8 Likes

@wojtekmach was looking into univeral builds for livebook with their most recent release, though not (yet) successfully: macOS app launches with Rosetta · Issue #890 · livebook-dev/livebook · GitHub

3 Likes

Yeah, libraries are the problem. I have an open PR about cross-compiling from x86_64 to aarch64 xcomp: Add aarch64-darwin by wojtekmach · Pull Request #5458 · erlang/otp · GitHub and I’m stuck on correctly linking openssl. wx will be problematic too.

3 Likes

Sorry for the long delay, but I just wanted to note that the lipo-version works for us. Strangely we had to disable the jit for the intel-build, if enabled starting erl results in

felix@fizfaz-air Resources % ./at_servr_release/erts-12.2.1/bin/erl
beam/jit/x86/beam_asm.cpp:168:pick_allocator(): Internal error: jit: Cannot allocate executable memory. Use the interpreter instead.

which works fine for the normal build. But this is maybe due to some security restriction in macOS :thinking: , and is not a problem for us. We don’t need wxWidgets or other shared libraries, which made it simpler for us. Thanks for the help!

2 Likes

Not really that strange, their arch does x86-aarch64m1 recompilation via a JIT on M1 machines, which doesn’t play well with post-runtime code injection like inbuilt JIT’s do unless they are aware of it and make proper adjustments. I.E. the M1 translates code on load, which if you are generating machine code at runtime means that it can’t do that without talking to the translator directly to tell it of any updates, so they prevent dynamic executable mapping to prevent something screwing it up (which will be everything to start).

1 Like

the error above is while running the universal-binary on an Intel mac (same error if running using Rosetta on a M1-machine)

2 Likes

Yep exactly, that’s what I was saying, it’s unable to dynamically mmap executable memory so it’s unable to JIT, they kept the same restriction on Intel macs as well for feature parity with M1’s as they don’t want something to work on an Intel but not work on the M1 to help encourage people to migrate, even if it is an artificial limitation on the Intel side.

2 Likes

ah ok. I wondered because the non-universal version uses the jit just fine on intel. But hey its apple after all … :smile:

2 Likes