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 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. You need X-Code or the command line tools installed to provide build tools on macOS. Nothing that follows will work without it. 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: 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. 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. 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 This creates the directory crosstool-ng, containing the source code. Enter that folder and issue 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 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. To try it out, navigate to that directory and issue to generate the configuration for one of the per-defined builds as a test case. Then 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 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. To use the toolchain, set the compiler path to and use the gcc command 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. Step 1:
Step 2:
Step 3:
Step 4:
cd build_dir
git clone https:// github.com/crosstool-ng/crosstool-ng.git
./bootstrap
./configure --prefix=PATH_TO_INSTALL_DIR
make
make install
Step 5:
ct-ng arm-unknown-linux-gnueabi
ct-ng menuconfig
ulimit -n 4096
ct-ng build
Step 6:
/Volumes/ct-ng/x-tools/arm-unknown-linux-eabi/bin
arm-unknown-linux-gnueabi-gcc
Hello Kai. Great tutorial! If it is possible keep posting about pixhawk as well. You made a great contribution for the px4 community!
Thank you very much for the tutorial; I am unable to run neither the bootstrap script as I got a lot of errors; I am running MacOs Sierra 10.12.6; I get the following errors running bootstrap; what could be happening ?
Thank you very much. Regards.
Marco Bisio
./bootstrap: line 20: declare: -A: invalid option
declare: usage: declare [-afFirtx] [-p] [name[=value] …]
INFO :: *** Generating package version descriptions
./bootstrap: line 548: local: -A: invalid option
local: usage: local name[=value] …
./bootstrap: line 433: local: -A: invalid option
local: usage: local name[=value] …
./bootstrap: line 439: @{pkg_name}-@{version}-linux-x86_64: syntax error: operand expected (error token is “@{pkg_name}-@{version}-linux-x86_64”)
INFO :: *** Generating menu/choice selections
INFO :: Generating arch.in
./bootstrap: line 238: ${v^^}: bad substitution
./bootstrap: line 650: Target Architecture: syntax error in expression (error token is “Architecture”)
INFO :: Generating kernel.in
./bootstrap: line 238: ${v^^}: bad substitution
./bootstrap: line 650: Target OS: syntax error in expression (error token is “OS”)
INFO :: Generating cc.in
./bootstrap: line 238: ${v^^}: bad substitution
ERROR :: Iterator over ‘choice’ is already set up
You might want to ask the developers directly. I cannot help with these issues, since I don’t see them during my setup.
I’m looking a solution for step four seems to be no command for cd build_dir really I’m just confused
I have the directory but theres just empty folders named git and clone no actual git
You might want to look up a guide on how to use git before proceeding here. And ‘build_dir’ is just a placeholder for wherever you want to build. Good luck.
I just went through the build process following your guide. If somebody wants to take a shortcut I uploaded the resulting binaries to my Google Drive:
https://drive.google.com/file/d/1MH6r0uv9nPJYx2eXmnUSRru8ctdvfW_6