Here’s how to create your own, shiny ARM gcc cross-compile toolchain for your Mac. A cross-compile toolchain enables to compile code for a different hardware architecture than the development system. We will be using the Intel/macOS to generate ARM/Linux (Cortex-Axx CPUs) or ARM/bare-metal (Cortex-Mxx Microcontrollers) code. Since the ARM architecture is omnipresent these days in UAV work, this is kind of handy to have working. Trivial to do on Linux as a host system, but our trusty Mac needs some special treatment.

The tool to use is crosstool-ng, which is designed to compile the gcc toolchain for various architectures. The main audience for the tool is Linux, but it works fine on the Mac with a few tricks. There are other sources of information on this topic, but they deal with older versions of macOS and crosstool-ng

[1][2], so here is an update that works on macOS Sierra with the latest crosstool-ng version. Those other websites are still a good source of information, and well worth visiting in the process. Most of the workarounds listed on these pages are no longer required, but at the time of writing a small number of new hiccups need to be considered.

In this tutorial I am using places and paths that I find logical. These can be changed to any other location as desired, of course.

Step 1:

You need X-Code or the command line tools installed to provide build tools on macOS. Nothing that follows will work without it.

Step 2:

Some of the macOS build tools are not equivalent to the GNU/Linux versions. Building a beast like gcc, however, requires those extra functionalities. The package manager Homebrew can be used to install those tools quite easily. Other methods might work as well but have not been tested.

Note: Homebrew contains a formula to install crosstool-ng 1.22. This is outdated and does not work on macOS at the time of writing. So we need to build the tool from the git master for now.

So you need to install Homebrew, which is quite easy. Then install the following packages:

  • autoconf
  • automake
  • libtool
  • help2man
  • coreutils
  • binutils
  • wget
  • gnu-sed
  • gawk
  • libelf
  • make
  • grep

Some of these tools have their equivalent in macOS, so Homebrew installs them with a prefix g, so make becomes gmake and so on. Crosstool-ng is set up nicely to find these alternate versions for you during building. However in the current version (Feb. 2017) is one remaining bug that requires this knowledge.

Step 3:

gcc is a Linux tool and Linux uses case sensitive file systems by default. The Mac does not. So trying to build gcc on the standard Mac disk will inevitably fail. So we need to create a case sensitive disk somehow. Luckily, this is actually quite easy with disk utility. Check out [1] on how to do that. Basically, you want to create a sparse disk image with case sensitive file system somewhere on your disk. Be aware that disk utility actually changes the file system properties as you set the options, so make sure that it is set to case sensitive file system before creating the image.

Step 4:

Create a directory to build crosstools-ng. This can be anywhere on the Mac disk, or in the newly created disk image. Crosstool-ng does not require a case sensitive file system. The clone the git repository into this directory

cd build_dir

git clone https:// github.com/crosstool-ng/crosstool-ng.git

This creates the directory crosstool-ng, containing the source code. Enter that folder and issue

./bootstrap

to generate the configuration scripts. Then we will need to decide where we want to install the crosstool executable. I find it sensible to install it into the build disk image to have it all in one spot. To do that, issue

./configure --prefix=PATH_TO_INSTALL_DIR

make

make install

where I choose  PATH_TO_INSTALL_DIR to be /Volumes/ct-ng/ct-ng in the build disk image. This will make and install crosstool-ng in that directory. Any errors will indicate that some of the previous instructions did not succeed. Checking the output of the configuration step might show that some of the GNU/Linux tools were not recognised correctly. You’ll need to verify the Homebrew installation of those tools in this case. If all went well, there should be a working version of crosstool-ng in the INSTALL_DIR.

Step 5:

To try it out, navigate to that directory and issue

ct-ng arm-unknown-linux-gnueabi

to generate the configuration for one of the per-defined builds as a test case. Then

ct-ng menuconfig

to enter the build configuration menu. This is the same as used for the Linux kernel. In there, we need to change the default locations of the download- and output directories to point into the case sensitive disk image (the download directory doesn’t need to be there but again, it keeps things organised. Then issue

ulimit -n 4096

ct-ng build

to build the toolchain. (The ulimit command increases the number of open files allowed, otherwise the build will fail just before the end…)

This will fail immediately, but no worries, the information printed will allow us to fix the problem. As mentioned before, some of the tools installed by Homebrew have the prefix g. And this is the bug in crosstools, where in one file this is not set correctly. Everywhere else it is, so do not try to rename to tool (sed), but make a small change in one of the source files of crosstool. This might get fixed soon as there is an issue open on Github for this. But for now, we need to go into the file printed in the error message (/scripts/functions) and change the broken command (line number given in the error msg) from sed to gsed. Then save the file and try the build again. All should be working fine now. The build will take 40 minutes or so. Once done, there should be a ARM-gcc toolchain in the x-tools directory.

Update [27/02/2017]: This problem appears to be fixed, at least based on my limited testing over the past few days.

Step 6:

To use the toolchain, set the compiler path to

/Volumes/ct-ng/x-tools/arm-unknown-linux-eabi/bin

and use the gcc command

arm-unknown-linux-gnueabi-gcc

to compile the code.

This covered just the basic procedure. When it all works, the toolchain can be configured more specifically to the hardware target using the menuconfig system. This might be the topic of another article.