Building a GCC cross compile tool chain for Linux ARM on OS X Mountain Lion


If you have a Beagleboard, Pandaboard, Raspberry Pi, or other ARM hardware running Linux, and you want to compile and debug C/C++ applications from your Windows or Linux desktop, it's relatively straightforward: download a pre-built tool chain from Mentor Graphics (formerly Code Sourcery). No such luck for OS X users. You have to build it yourself, and it's pretty painful. Hopefully, the info below will make it less painful for you. If you don't care to build the tools yourself, I posted the binaries on SourceForge.

Here's what I had to do to build all the cross compile binaries:

  • Install the latest Command Line Tools for XCode.
  • Install Homebrew (Homebrew is awesome, by the way):

    ruby -e "$(curl -fsSkL raw.github.com/mxcl/homebrew/go)"
    
  • Use Homebrew to install crosstool-ng, mpfr, and gmp:

    brew install crosstool-ng mpfr gmp
    
  • Install Homebrew dupes:

    brew tap homebrew/dupes
    
  • Use Homebrew to Install grep. You already have BSD grep on your Mac, but crosstool-ng scripts use functionality that assumes you have GNU grep, which is why you need it from Homebrew dupes:

    brew install grep
    
  • You need a case-sensitive file system to work with. Fortunately, you can create one in Apple's Disk Utility and mount it. Create one that's at least 5 GB to start. You can increase the size later if needed.

That was the easy part. Now we configure and build the tool chain.

  • Change the working directory to your mounted case-sensitive volume:

    cd /Volumes/{whatever you named it in Disk Utility}
    
  • Then load crosstool-ng with the ARM Linux preset. The way you call crosstool-ng is via ct-ng (it took me a few minutes to figure that out):

    ct-ng arm-unknown-linux-gnueabi
    

If things were easy (e.g., if you were doing this on a Linux desktop), you could probably just run ct-ng build at this point and walk away for about 30 minutes and a shiny new cross compile tool chain would be waiting for you when you returned. Most of the remaining steps account for errors that are probably symptomatic of using OS X to run a utility that wasn't written to run on OS X.

  • Update the paths that crosstool-ng uses to the case-sensitive location:

    ct-ng menuconfig
    

    This brings up a configuration tool that you can use to set all sorts of things. Start with changing paths. Rename the "local tarballs directory", "working directory", and "prefix directory" to /Volumes/{whatever you named it in Disk Utility}/{somethingunique}. While you're in there, turn off the build of Java and Fortran compilers, since you don't need them and they'll just cause more problems.

If you get an error, be sure to run ct-ng clean before you try to build again. Below are errors I ran into and what I did to get past them.

Static linking impossible on the host system 'x86_64-build_apple-darwin11.2.0'

Easy workaround: Open the hidden file named .config (this was automatically created in your working directory when you first called ct-ng) and update the line that includes CT_WANTS_STATIC_LINK=y to CT_WANTS_STATIC_LINK=n. Keep in mind that if you go back into menuconfig and save new changes, that will overwrite your change to .config and you'll have to make your edits again.

unknown parameter -Bstatic

This problem has to do with functionality differences between OS X ld and GNU ld. Building GNU ld for OS X isn't possible AFAIK. To fix this one, either remove or comment out this line in your .config file: CT_CC_STATIC_LIBSTDCXX=y

Again, keep in mind that if you go back into menuconfig and save new changes, that will overwrite your change to .config and you'll have to make your edits again.

automatic de-ANSI-fication support has been removed

Change the version of MPFR to a later version that doesn't result in this error. I used 3.0.1 and it worked.

Then, if you're lucky, you can just run

ct-ng build

and you'll end up with a working cross compile tool chain. If you've gotten this far, I recommend downloading Eclipse+CDT and configuring it to use your newly-built toolchain.

I got debugging working, too. I had problems with connecting to a 32-bit gdbserver from my 64-bit gdb client. The error looked something like this in the console when trying to start debugging:

readchar: Got EOF

I fixed this by building a later version of GDB. Here are the changes I made to .config:

# CT_GDB_V_6_8a=y
CT_GDB_7_0_or_later=y
# CT_GDB_VERSION="6.8a"
CT_GDB_VERSION="7.5"

All of this took me a lot of trial and error, so it's likely I've included some extraneous steps, but I left them in just in case they're needed. Several errors were remedied by just changing to a more recent version of the tools configured in ct-ng menuconfig. Here's the set that worked for me:

  • Linux kernel: 3.2.32
  • binutils: 2.19.1a
  • gcc: 4.6.3
  • glibc: 2.10.1
  • dmalloc: disabled
  • GMP 5.0.2
  • MPFR 3.0.1
  • PPL 0.11.2
  • CLooG/ppl 0.15.11
  • MPC 0.9
  • libelf: 0.8.13

Handy resources/tips:

  • Using crosstool-NG on MacOS-X [crosstool-ng.org] -- He says you need MacPorts, but you don't. Homebrew and MacPorts don't always play nice. I installed crosstool-ng via Homebrew, so I avoided MacPorts.
  • If your build fails, find the error in build.log and search the web with the error string. If you find a response from Yann E. Morin or Titus von Boxberg, read it.