Wednesday, 7 June 2023

Alire on macOS, revisited

This note covers some of the considerations that’ll apply when running Alire on macOS.

Macs with Intel chips

If you’re using an Intel (x86_64) machine, things are fairly straightforward; the binary releases of Alire are (as of 2023-06-06) Intel-based.

Compiler, Linker paths

So that an Apple developer can use their Mac to build for the various systems supported by Apple (iPhone, iPad, Apple Watch …) as well as macOS, the normal include and library files aren’t in the places you’d exepct on a Linux system (/usr/include, /usr/lib); they’re provided in Software Development Kits (SDKs), Xcode and the Command Line Tools; the CLTs are Mac-only, and so much smaller than Xcode. We’ve built the compilers so that they will look in either place (/Applications/Xcode or /Library/Developer/CommandLineTools), allowing you to choose which to install (you must choose one of them!).

Unfortunately, this means that /usr/local/include, /usr/local/lib aren’t searched by default; you can overcome this by including these lines in your shell initialization scripts:

export C_INCLUDE_PATH=/usr/local/include
export LIBRARY_PATH=/usr/local/lib

External packages

Some Alire-supported crates (e.g. libgmp) are expected to be provided outside Alire. If it’s been told how in the crate’s manifest, Alire will use the system package manager to install the crate. For example, for libgmp,

$ alr show libgmp --external
Kind           Description                 Details                     Available
System package 5 candidate system packages Debian: libgmp-dev          True
                                           Ubuntu: libgmp-dev
                                           Msys2: mingw-w64-x86_64-gmp
                                           Arch: gmp
                                           Homebrew: gmp
                                           others: unavailable

For macOS, the two main package managers are Homebrew and Macports. Alire (the upcoming 2.0 release; pre-release binaries available here) understands Homebrew, though not many external packages have been ported. If Alire says that it needs an external package foo but doesn’t know how to install it, you should still be able to say brew install foo and proceed.

Macs with Apple chips

On a Mac with Apple (aarch64, or arm64) silicon, a process can run Intel code under the Rosetta Translation Environment. It’s all-or-nothing; that environment can’t run aarch64 code. To support this, you can’t link Apple and Intel object code, and you can’t use Apple shared libraries from an Intel program (or vice versa).

Rosetta doesn’t support gdb; you can use lldb, but it doesn’t understand Ada, so things will be a bit opaque.

Sticking with Intel

If you’re happy to use the x86_64 compilers, you’ll be able to use Alire with hardly any trouble. The only issue is with external packages; Homebrew knows it’s running on Apple silicon, and installs Apple libraries and executables. For added flavour, it installs them under /opt/homebrew rather than the /usr/local it uses on Intel silicon (supposedly this is so that you can have both versions installed; I haven’t managed it, but then I haven’t tried very hard).

Going with Apple silicon

At this point, things get a bit more complicated.

First off, you can’t download an aarch64-targeted compiler through Alire (yet). You can find a package styled after the Community packages that AdaCore used to provide (that is, including gprbuild, XML/Ada, GNATColl, libadalang) here; it installs to /opt/gcc-13.1.0-aarch64, so set your PATH to /opt/gcc-13.1.0-aarch64/bin:$PATH. After this, you can use a downloaded Intel alr; if you haven’t yet run alr toolchain --select it will probably choose the new compiler, but to make sure

$ alr toolchain --select
Welcome to the toolchain selection assistant

In this assistant you can set up the default toolchain to be used with any crate
that does not specify its own top-level dependency on a version of gnat or

If you choose "None", Alire will use whatever version is found in the

* Currently configured: gnat_native=12.2.1

Please select the gnat version for use with this configuration
  1. gnat_native=12.2.1
  2. None
  3. gnat_external=13.1.0 [Detected at /opt/gcc-13.1.0-aarch64/bin/gnat]
  4. gnat_arm_elf=12.2.1
  5. gnat_avr_elf=12.2.1
  6. gnat_riscv64_elf=12.2.1
  7. gnat_arm_elf=12.1.2
  8. gnat_avr_elf=12.1.2
  9. gnat_native=12.1.2
  0. gnat_riscv64_elf=12.1.2
  a. (See more choices...)
Enter your choice index (first is default):
> 3
* Selected tool version gnat_external=13.1.0

* Choices for the following tool are narrowed down to releases compatible with just selected gnat_external=13.1.0

* Currently configured: gprbuild=22.0.1

Please select the gprbuild version for use with this configuration
  1. gprbuild=23.0.0 [Detected at /opt/gcc-13.1.0-aarch64/bin/gprbuild]
  2. None
Enter your choice index (first is default):
> 1
* Selected tool version gprbuild=23.0.0

Compiler, Linker paths

The recommendation above to overcome limitations on these should be changed to


Using an alr compiled for Apple silicon

If you use a downloaded pre-release alr and say alr version, at the end you’ll see

distribution:              HOMEBREW
host-arch:                 X86_64
os:                        MACOS
target:                    NATIVE
toolchain:                 USER
word-size:                 BITS_64

The host-arch setting is used in alr toolchain --select to choose matching compilers from the Alire ecosystem, which are all x86_64, so if you build your own alr using the aarch64 compiler (when the host-arch will be AARCH64), the only compiler and gprbuild visible will be the external GCC 13.1.0 just downloaded.

This of course makes it hard to build for AVR or RISC-V! If you only need to build for arm-eabi, the compiler here loads on top of the gcc-13.1.0-aarch64 native compiler suite, and will be picked up when your GNAT Project calls up for Target use "arm-eabi";.

No comments:

Post a Comment