The Nim 2.0 release candidate is out, and includes a whole host of amazing changes and additions. I had been holding off on exploring Nim because I was waiting for ORC and multi-threading to become the default. They have been available for a long time, but defaults matter - it’s what first time and first-time-in-a-while users experience. It forms their opinion of what the language is about.
Installing Nim on Apple Silicon Macs is pretty straight forward. The official installer sets up choosenim
and a default stable release:
curl https://nim-lang.org/choosenim/init.sh -sSf | sh
However, both Nim itself and the compiler output will be amd64
(Intel) binaries. To go native, and to benefit from Nim 2 right now, more configuration is required.
Set up Nim 2 natively
We need a source build, and thankfully that’s easy:
git clone https://github.com/nim-lang/Nim
cd Nim
git checkout version-2-0
sh build_all.sh
Yep, that’s it. We don’t have to mess with our PATH
either. Instead, we can now point choosenim
at the new build:
choosenim <location>/Nim
And confirm the architecture with:
$ nim -v
Nim Compiler Version 1.9.1 [MacOSX: arm64]
Compiled at 2023-01-14
Copyright (c) 2006-2022 by Andreas Rumpf
(2.0 RC self-reports as 1.9.1 as of Jan 15 2023)
To switch back, use choosenim stable
.
Native & universal binaries
Building a project with this toolchain will produce an Intel binary. To get a full build on macOS, we have to follow Apple’s guidelines and set the correct compiler and linker targets. In your project’s nimble (nimble init
if you don’t have one yet), add a new target:
task release_clang, "Build a production release (macOS)":
--verbose
--forceBuild:on
--cc:clang
--define:release
--deepcopy:on
--cpu:arm64
--passC:"-flto -target arm64-apple-macos11"
--passL:"-flto -target arm64-apple-macos11"
--hints:off
--outdir:"."
setCommand "c", "hello.nim"
-flto
is required because clang doesn’t like Nim’s default passing of LTO parameters- note the
cpu
and-target
parameters - the rest are standard release flags
ORC and threads
are default now, so no need to enable them here anymore. It’s a good idea to pin the Nim version in the nimble file, in this case to >= 1.9.1
.
Running nimble release_clang
now gives us a nice native binary:
$ file hello
hello: Mach-O 64-bit executable arm64
If you want to build an Intel binary, add another task and change the target to x86_64-apple-macos10.12
. If you need a universal binary, build both the Intel and ARM targets first, then merge them using lipo
:
lipo -create -output universal_app x86_app arm_app
BTW: If you’re wondering what the cover image is about - “Nimm 2” (“take two”) is a popular brand of gummy candy in Germany.