ARM Cross Compiling with Mac OS X

The article refers mainly to cross compile on Mac OS X, but all described below can also be applied on Linux.

ARM Toolchain for Mac OS X

Let’s start first with toolchain.  So no one has to compile the toolchain again,  I have provided them as binaries:

All versions are in the Package Manager Format as Installer. After the installation, you can find the toolchains in the following directories:

  • /usr/local/linaro/arm-linux-gnueabihf  – BeagleBone Black
  • /usr/local/linaro/arm-linux-gnueabihf-raspbian  – Raspberry Pi

Now you can already start with the cross compiling:

Enter the most popular code:

Save the file, exit nano [ctrl + x] and then compile it:

Test if everything works:

If everything works fine,  you might as well go over to Eclipse. But at the moment we only have a „prebuild sysroot“. This means we can only generate code using standard C and C++. If you want to use Linux libraries, like Glib etc., you have to compile this first, to get an advanced sysroot.

Advanced Sysroot

There are a lot of Linux libraries, in the following I use the most popular or which I think they are popular. I do not explain here configuration like:

I have create a shell script which creates the extended Sysroot automatically. At the beginning,  I wanted to use only the libraries Glib, Qt embedded and OpenCV. However, they have so many dependencies, so that the Sysroot now includes the following libraries:

  • Image Libraries:
    • libjpeg – Independent JPEG Group’s JPEG runtime library
    • limping – PNG library
    • libtiff – Tag Image File Format library
    • libraw – raw image decoder library
    • liblcms2 – Little CMS 2 color management library development headers
    • imagemagick – image manipulation library
  • Audio and Video Libraries:
    • gstreamer – pipeline-based multimedia framework
    • gst-plugins-base – GStreamer libraries from the „base“ set
    • gst-plugins-good – GStreamer development files for libraries from the „good“ set
    • alsa – Advanced Linux Sound Architecture
    • liboog – Ogg bitstream library
    • libvorbis – Vorbis General Audio Compression Codec
    • libtheora – Theora Video Compression Codec
    • libvisual – Audio visualization framework
    • wavpack – Audio codec (lossy and lossless) encoder and decoder
    • lib – Open source audio and video processing tools
  • Compression Libraries:
    • zlib – Compressing File-I/O Library
    • bzip2 – High-quality block-sorting file compressor
    • liblzma – XZ-format compression library
  • Markup Language Libraries:
    • expat – XML parsing C library
    • libxml2 – GNOME XML library
  • Hardware Libraries:
    • tslib – Abstraction layer for touchscreen
    • i2c-tools – Heterogeneous set of I2C tools for Linux
    • bluez – Bluetooth protocol stack library
    • libusb – userspace USB programming library
    • wiringPi – GPIO Interface library for the Raspberry Pi (Raspberry Pi only)
  • Communication:
    • libmodbus – Library for the Modbus protocol
    • curl – Command line tool for transferring data with URL syntax
  • Mathematic and Scientific Libraries:
    • gsl – GNU Scientific Library
    • gmp – Multi precision arithmetic library developers tools
    • mpfr – Multiple precision floating-point computation developers tools
    • opencv – Open Source Computer Vision Library
      (no idea why, but can only compile on my iMac and not on my Mac Book Pro.)
  • Database:
    • sqlite – Database management system libraries
  • Framework and System Libraries:
    • Qt – Qt 4 development files and development programs for host
    • glib – GLib development library
    • dbus – Simple interprocess messaging system
    • libffi – Foreign function interface library
    • ncurses – text-based user interfaces library
    • readline – GNU readline and history libraries
    • cryptodev – Access to Linux kernel cryptographic drivers
    • openssl – Secure Sockets Layer toolkit
    • liborc – Library of Optimized Inner Loops Runtime Compiler
    • freetype – FreeType 2 font engine
    • fontconfig – Generic font configuration library
    • cairo – The Cairo 2D vector graphics library
    • liblqr – Converts plain array images into multi-size representation
    • libssh2 – SSH2 client-side library
    • libdirectfb – Direct frame buffer graphics library
    • libconfig – Configuration File Library
  • X11 Libraries:
    • libX11 – X11 client-side library
    • libXext – X11 miscellaneous extensions library
    • pixman – pixel-manipulation library for X
    • xtrans – X transport library
    • xproto
    • xextproto
    • inputproto
    • xcb-proto – X C Binding
    • libpthread-stubs – pthread stubs not provided by native libc
    • libXau – X11 authorisation library
    • libgpg-error – Library for common error values and messages in GnuPG components
    • libgcrypt – LGPL Crypto library
    • libxslt – XSLT 1.0 processing library
    • libxcb – X C Binding
    • videoproto – X11 Video extension wire protocol
    • kbproto – X11 XKB extension wire protocol
    • libXv – X11 Video extension library

First, the script must be downloaded from Github. I use a folder called „Development“ which is placed in my home directory. Each target has their own directory in „Development“. As this continues within the article here a short explanation:

  • The user directory  /Users/USER_NAME  has the following the acronym  $HOME.
  • The working directory for the BeagelBone Black is:  $HOME/Development/BeagleBone
  • The working directory for the Raspberry Pi is:  $HOME/Development/Raspi

The installation of the advanced sysroot for the BeagleBone Black is then as follows:

After the repository has been cloned, you have to set up the configuration file:

The following configuration file shows the default settings for the BeagleBone Black:

If all parameters are correct, you can start compiling the Sysroot:

Creating now takes some time, so you have two or three hours rest. It is useful to disable Time Machine, otherwise all source files get backed up.

If you will build the advanced sysroot for Raspberry Pi and BeagleBone Black you have to do this twice. Because the architecture of both systems are not compatible. This is also the reason why there are two compiler.

Cross Compiling with Eclipse CDT

Open Eclipse CDT. If Eclipse is not installed, install Eclipse Kepler CDT 32Bit now. First you have to specify the target. In the Menu „Window“  select → „Open Prespective“ → „Other“.

Eclipse001

 

Goto the dialog and select „Remote System Explorer“ (RSE). Confirm the dialog with OK. If you close the Welcome Screen, you will see the RSE on the left side. Right click into the RSE to open the context menu and select „New Connection“.

Eclipse002

  • Select „Linux“ and click „Next“.
  • Enter the host name or IP address and click „Next“.
  • Files: „Configuration“ choose „ssh.files“ and click „Next“.
  • Processes: „Configuration“ choose „processes.shell.linux“ and click „Next“.
  • Shells: „Configuration“ choose „ssh.shells“ and click „Next“.
  • SSH Terminals: „Configuration“ choose „ssh.terminals“ and click „Next“.

Change into the Perspective C/C++ (icon at the top right) and create a new C++ Project (e.g. hello).

Eclipse004

As Project Typ choose „Executable“ → „Empty Project“ and as Toolchain „Cross GCC“, click „Next“ to proceed. The following dialog can be skipped.

Eclipse005

In Cross GCC Command add:

  • Cross Compiler Prefix: „arm-linux-gnueabihf-„
  • Cross Compiler Path:
    • /usr/local/linaro/arm-linux-gnueabihf  – BeagleBone Black
    • /usr/local/linaro/arm-linux-gnueabihf-raspbian  – Raspberry Pi

Close the dialog with „Finish“. Create a new cpp (e.g. hello.cpp) and add the source code below:

Select the menu „Project“  → „Build Project“ oder press [cmd+b] to compile the source code. To run the program on the target, select „Run“ → „Run Configurations“, right click on „C/C++ Remote Application“ and select „New“ from the context menu. Under „Main“ add the „Remote Absolute File Path for C/C++ Application“ for example „/root/hello“. Click „Apply“ and „Run“ to execute you program on the target.

To start the Debugger select „Run“ → „Debug Configurations“. Under „Main“ add the „Remote Absolute File Path for C/C++ Application“. Goto the tab „Debugger“ and for „GDB debugger“ type „/usr/local/linaro/arm-linux-gnueabihf/bin/arm-linux-gnueabihf-gdb“ (/usr/local/linaro/arm-linux-gnueabihf-raspbian/bin/arm-linux-gnueabihf-gdb for Raspberry Pi). Click „Apply“ and „Debug“ to execute your program in debug mode on the target. Here, you can now run the program line by line (do not use step into compiled library functions).

This is now based on all standard C/C++. The effort with the Sysroot does not apply yet. To build the same source like bevor with Glib, we have to tell Eclipse where the advanced sysroot is to find. Right click on your Project and select „Properties“. Goto „C/C++ General“ → „Path and Symbols“. Under „Includes“ click the button „Add“ and add the following paths:

  • „%HOME/Development/BeagleBone/sysroot/include“
  • „%HOME/Development/BeagleBone/sysroot/include/glib-2.0“
  • „%HOME/Development/BeagleBone/sysroot/lib/glib-2.0/include“

Click „Add to all Languages“ and „OK“. Goto „Library Path“ (repeat it for each path).

Select the path to the Sysroot Libraries:

  • „%HOME/Development/BeagleBone/sysroot/lib“

Goto „Libraries“ and add them (without -l and without lib):

  • glib-2.0
  • pthread

Close the Properties dialog and replace the source code with the code below:

For the example the effort does not make sense, this effect is only relevant for large projects.

Cross Compiling with Qt Creator

Fierst we need to install Qt Creator. Even the Qt in the sysroot is in version 4.8.6, we can use the actual Qt Creator 3.2.1 for Mac. After the installation, goto „Qt Creator“ → „Properties“.

So my problem now is, Max OS X is a comfortable and ergonomic Operation System and Qt Creator try to follow them. Means everything is in German. I’m trying to translate the dialogues and commands, but it may be that they are different in the English version.

Select „Devices“ in the left menu and push the button „Add…“ on top right.

qt001

Select „Generic Linux Device“ and press „Start Wizard“:

qt002

Add the Connection setup for your target click „Continue“:

qt003

Confirm the following dialog with „Finish“ and start the test procedure.  After the test is completed successfully click on „Close“.

qt004

Click „Apply“ (bottom left) to save your changes. Goto „Build & Run“ and select the tab „Compilers“. Push the button „Add“ and chose „GCC“:

  • Name:  You can assign a name of your choice.
  • Compiler Pfad:
    • /usr/local/linaro/arm-linux-gnueabihf/bin/arm-linux-gnueabihf-g++  – BeagleBone Black
    • /usr/local/linaro/arm-linux-gnueabihf-raspbian/bin/arm-linux-gnueabihf-g++  – Raspberry Pi

Click „Apply“ (bottom left) to save your changes. Select the tab „Qt Versions“ and push the „Add“ button:

  • Path ([cmd+shift+h] shows hidden files):
    • /usr/local/Trolltech/Qt-4.8.6-beaglebone/bin/qmake  – BeagleBone
    • /usr/local/Trolltech/Qt-4.8.6-raspi/bin/qmake  – Raspberry Pi

Select the tab „Debugger“ and push the „Add“ button:

  • Name:  You can assign a name of your choice.
  • Path ([cmd+shift+h] shows hidden files):
    • /usr/local/linaro/arm-linux-gnueabihf/bin/arm-linux-gnueabihf-gdb  – BeagleBone
    • /usr/local/linaro/arm-linux-gnueabihf-raspbian/bin/arm-linux-gnueabihf-gdb  – Raspberry Pi

Finally select the tab „Kits“ and push the „Add“ button, to set the parameters previously taken, as shown below using the example of an BeagleBone Black.

qt005

Before we can create a program and run it on the target, we still need to be made some modifications of the target.

Preparation of the target for Qt

In order to understand, the Qt version that we have compiled is embedded Qt version with its own frame buffer. The Qt version in the Debian/Raspbian repositories requires a window manager. This means you can not install Qt from the package source, you have to copy the compiled libraries to the target. In the following the example of the BeagleBone Black (Raspberry Pi is placed in Qt-4.8.6-raspi):

To find the libraries we have to add the path in the environment variable:

Extend in the file, the row 5 and 7, the path with „/usr/local/Trolltech/Qt-4.8.6-beaglebone/lib“.

 

I was not able to configure libffi 5 on Mac OS X, so libffi was installed in version 6. So we have to copy these libraries too:

As on a freshly installed BeagleBone Black und and Raspberry Pi has already a window manager running, it must be removed.

The target is now ready for use.

Test Qt on the Target

Now a new project can be created. Open „File“ → „New File or Project“, select „Application“ → „Qt Widgets Application“ and press „Choose“. Create a subfolder with the same name as your project and save the project into it. A nice feature on Qt Creator is, you can create one and the same project for different targets and also for the host PC and change within this. Continue to the next screen.

qt007

Give the Class a name and press continue to the next screen. It now appears our main window where you already have a windows application. By pressing the hammer, this can be compiled.

qt008

If this works, the program can be transferred and executed, by pressing the green arrow, on the target. But before you have to setup the project file, in order like this:

In addition, a command line argument has to be passed. Click the icon „Projects“, goto „Build & Run“ and click „Run“ below the Target. Go to the section „Run“ and pass „-qws“ in the „Arguments“ field.

qt009

If you now press „Run“, the application should be appears on the screen of the target, if you have one.

Conclusion

I work with this setup for several months. Since then, I have not started my virtual Linux machine. The last time that I have used Linux (private, as an embedded developer I use it everyday), was to check if the advanced sysroot works also on Linux.

Comments

  • Hi, Thanks for the tutorial and the toolchain!!!!

    You think there is a chance that we get gcc 5.x?

    Mike8. März 2016
  • The more I dive into your package the more I can see how great it is. By far!!!! the best toolchain for Raspi + Mac. You should build a separate website for this and ask for Donation – I would pay. The whole thing looks a bit outdated but it isn’t.

    To all the other visitors:
    – GH-Sysroot: https://github.com/Illuminux/arm-cross-sysroot
    – GH crosstools-ng Linaror Mac: https://github.com/Illuminux/ct-ng-linaro-mac

    PS: It’s still not clear why you use gcc 4.9 and not 5.x – I’m sure there is a reason for this but I don’t get it – can you explain?

     

    Mike8. März 2016
  • I get a series of errors and need to run ./sysroot with a lot of the libraries removed from the ’setting.cfg‘. Wasn’t concerned until I got the error on wiringPi which is the one i really wanted.

    wiringPi Build script
    =====================

    fgrep: /proc/cpuinfo: No such file or directory

    WiringPi Library
    ./build.sh: line 128: uninstall: command not found
    wiringPi Build script
    =====================

    fgrep: /proc/cpuinfo: No such file or directory

    WiringPi Library
    ./build.sh: line 128: uninstall: command not found

    Any help would much appreciated, I’m fairly new at this.

    Rowan1. April 2016
  • Hi Mike,
    I use gcc 4.9 because it is also used on my target.
    The default Raspbian is based on Debian Jessie, so I try to use all program and libraries in the sysroot with the same versions as Jessie does.

    Knut2. April 2016
  • This tutorial is amazing, thanks a lot for sharing it.

    I am facing a problem while trying to build sysroot. The lirary libxslt is failing on a final ld step:

    (…) arm-linux-gnueabihf/bin/ld: cannot find -licucore

    Is there a way to make libicucore easily available on the toolchain to solve this missing dependency ?

    Thanks for any help.

    Cristiano28. April 2016
  • Hi All,

    Did someone find how to fix the missing „icucore“ library issue: „arm-linux-gnueabihf/bin/ld: cannot find -licucore“

    icucore is a Mac OS X library and is located in /usr/lib, once Xcode is installed.

    I’m not sure which version of this library is missing(macosx, or ARM)

    Thanks

     

     

     

     

    dsarr23. Mai 2016
  • Hello,

    this tutorial is really interesting. I have a raspberry pi3 with installed Raspbian Jessie and I’d like to cross compile using an Max osx with installed Snow Leopard 10.6.8.

    The binaries that you provied can be used with this Raspian and raspberry pi3 version?

    Thanks!

    Cypre25. Mai 2016
  • Hello,

    I’ve been trying out your toolchain and have found a couple of issues:

    The first one was fairly simple – it doesn’t recognize the MacPorts install of gettext.  The fix was to install a second copy via Homebrew.  It’s not that big a deal to have the extra install, but if there’s a way with -rpath to have it try both library locations, that would be handy for those of us who prefer MacPorts (with libraries in /opt/local/lib by default).

    Having got past that, a really simple test program compiled, linked, and ran without errors.  But it got more complicated once I tried a program that uses clock_gettime().  That function is troublesome since it was originally part of the „real-time“ package, and only later was promoted to a full standard feature.

    Without „-lrt“ the build succeeds, but the resulting executable doesn’t run on the BBB, since it needs GLIBC_2.17, which isn’t available in the stock Debian (Wheezy) install.  Note that using different libraries for building versus running creates this sort of inconsistency.

    With „-lrt“, the link fails because librt needs libpthread, which isn’t in any of the places the linker is looking.  After locating it manually, I was able to get the link (and subsequent execution) to work by adding the following option:

    -Wl,-rpath-link,/usr/local/linaro/arm-linux-gnueabihf/arm-linux-gnueabihf/libc/lib/arm-linux-gnueabihf

    However, this obviously wasn’t a „proper“ fix, and wouldn’t necessarily work for all libraries.  So I investigated further by comparing the –verbose output between the broken cross-link and the working native link.  It turned out to be a difference in the default linker script:
    6c6
    < SEARCH_DIR(„=/usr/local/lib“); SEARCH_DIR(„=/lib“); SEARCH_DIR(„=/usr/lib“);

    SEARCH_DIR(„=/usr/local/lib/arm-linux-gnueabihf“); SEARCH_DIR(„=/usr/local/lib“); SEARCH_DIR(„=/lib/arm-linux-gnueabihf“); SEARCH_DIR(„=/lib“); SEARCH_DIR(„=/usr/lib/arm-linux-gnueabihf“); SEARCH_DIR(„=/usr/lib“);

    So the native linker precedes each of the three library paths with an architecture-specific version, and that is missing from the crosstool linker scripts.
    I’ve modified all the relevant script files accordingly, but that of course doesn’t change the compiled-in script, so to take advantage of the fix I need to add:
    -Wl,-dT,/usr/local/linaro/arm-linux-gnueabihf/arm-linux-gnueabihf/lib/ldscripts/armelf_linux_eabi.xc
    There may need to be more than just cosmetic reasons to avoid that approach, however, especially if linker options can change the script selection.  So it would be desirable to incorporate the script fixes into the build.
    There are other script differences as well, but I don’t know which (if any) of them should also be incorporated.

    BTW, I also started setting up an „advanced sysroot“ (and can pass along a couple of issues I encountered), but then decided to take a different approach.  Instead of building all the libraries from source, I just copied the libraries and includes over from the BBB with rsync.  The only issue I’ve found so far with this approach is that many of the libraries are absolute symlinks which are invalid when transplanted.  To fix that, I wrote a small Python program to replace all the absolute symlinks with equivalent relative symlinks, which are valid in either environment.  There are also absolute paths in „libraries“ which are really linker scripts, but the linker documentation claims that it handles sysroot issues with those properly, and I haven’t yet seen anything to refute that.
    Thanks.

    Fred Wright9. August 2016
  • Hi,

    many thanks to the beaglebone toolchain. Will there be a aarch64 toolchain aswell for the new 64 bit arm processor platforms like raspberry pi 3 or odroid c2?

    I would realy much appreciate.

    Best regards,

    Constantin

    Constantin11. August 2016
  • Hi

    Thanks for the great post, I am having difficulty at compiling the Sysroot. I get the following error;

    Mounting Source Image… donne

    mounted to /Users/MacMini/Documents/Development/BeagleBone/arm-cross-sysroot/src

    Build zlib: already installed (1.2.8)

    Build bzip2: already installed (1.0.6)

    Build xz: already installed (5.1.4beta)

    Build libffi: already installed (3.0.13)

    Build expat: already installed (2.1.0)

    Build tslib: already installed (0.0.2)

    Build glib: already installed (2.40.0)

    Build dbus: already installed (1.8.0)

    Build gsl: already installed (1.15)

    Build ncurses: already installed (5.9.20110404)

    Build gmp: already installed (5.0.5)

    Build mpfr: already installed (3.1.2)

    Build readline: already installed (6.0)

    Build sqlite-autoconf: already installed (3.8.7)

    Build cryptodev-linux: already installed

    Build openssl: already installed (1.0.1j)

    Build libgpg-error:

    Download libgpg-error-1.10.tar.bz2…

    curl: (9) Server denied you to change to the given directory

    faild

    HTTP Status 550:

    Can not download: ftp://ftp.gnupg.org/GnuPG/libgpg-error//libgpg-error-1.10.tar.bz2

    *** Error in libgpg-error ***

    Cleanup build directory:

    Unmount source image… done

    Renove source image… done

     

    Any help with this will be greatly appreciated.

    regards

    Nicholas1. September 2016
  • Hi,

    for the icucore problem what I did:

    find the cross-sysroot-downloads/libxslt-1.1.27.tar.gz

    tar -xvzf libxslt-1.1.27.tar.gz

    echo „find . -exec sed -i -e ’s/-licucore//g‘ \{\} \;“ >> libxslt-1.1.27/configure

    tar -cvzf libxslt-1.1.27.tar.gz libxslt-1.1.27
    shasum libxslt-1.1.27.tar.gz
    and change the shasum into arm-cross-sysroot/formula/libxslt.sh

    Nicolas Zin20. September 2016
  • Many thanks for sharing. Works perfectly on OSX 10.11 with eclipse mars2.

    Cheers!

    Kai

    kai23. September 2016