Cross compiling for RaspBerry/BeagleBone on Mac OS X – Part 2/3

Now that we ware familiar with the basic terms of cross compilation, we will become specific.
What we want to do is:

  • Cross compiling
  • C/C++ projects – today the typical hallo world example
  • on a Mac-OS X device – I used OS X v10.8.4
  • for a Raspberry Pi or Beagle Bone Black as our target
  • Raspberry Pi:

  • Processor: ARM1176JZF-S (700 MHz)
  • OS: Raspbian “wheezy” – debian based GNU/Linux distribution
  • BeagleBone Black:

  • Processor: AM335x 1GHz ARM® Cortex-A8
  • OS: Ångström distribution – Linux distributaion
  • Since both, the raspberry as well as the beagle are using ARM processors and linux distribution, our choice will be clear in terms of the unix cross compiler naming convention:

    arm-none-linux-eabi //according to the unix cross compiler naming convention

    Meaning, that we want to:

  • compile for the ARM processor architecture –> arm
  • dont care about a vendor –> non
  • use the linux operating system that already runs on our target(s)
  • use the provided EABI (embedded-application binary interface) between our program and the OS
  • Installing the toolchain (the easy way)

    Of course, you can build the whole toolchain you need by your self. By doing so, you will have the most detailed overview of each of the necessary parts within your toolchain. However, there are several things to do that are not that easy. Not that easy means a little bit of effort and that’s why this should be a topic for Part 3 of this posting series.

    For now, we will download an already prepared and compiled toolchain from Carlson-Minot.
    Thanks to asmo for pointing my nose to this project!
    You could also use comparable, precompiled toolchains for the mac – one example would be the CodeSourcery-project now renamed to Mentor Graphics Sourcery Tools.

    However, now download the toolchain – it comes as a package:

    Mac OS X ARM GNU Linux G++ Lite 2013.05-24 Toolchain from 15 May 2013

    Open the package and start the setup-process. Do not forget the installation-path if you modify it, because there will be the executables, we need to use for compiling our hello world program on the mac.

    Setup the environment-variables/the path to the executables:

    First locate the directories of your previously installed toolchain.
    If you leave the default pathes, you will find the under the directory
    /usr/local/carlson-minot/crosscompilers/

    If you take a look at the directories, installed in the crosscompilers-directory, you will find something like this:

    [/usr/local/carlson-minot/crosscompilers] ls
    arm-2013.05-24-arm-none-linux-gnueabi-libc-stripper.sh
    arm-2013.05-24-arm-none-linux-gnueabi-mentor-graphics-sourcery-difference-file-map.txt
    arm-none-linux-gnueabi
    bin
    include
    lib
    libexec
    share

    change one directory further to the bin-directory and take a look at the files there:

    [~] cd /usr/local/carlson-minot/crosscompilers/bin
    rool[/usr/local/carlson-minot/crosscompilers/bin] ls
    arm-none-linux-gnueabi-addr2line  arm-none-linux-gnueabi-gcov
    arm-none-linux-gnueabi-ar         arm-none-linux-gnueabi-gdb
    arm-none-linux-gnueabi-as         arm-none-linux-gnueabi-gprof
    arm-none-linux-gnueabi-c++        arm-none-linux-gnueabi-ld
    arm-none-linux-gnueabi-c++filt    arm-none-linux-gnueabi-nm
    arm-none-linux-gnueabi-cpp        arm-none-linux-gnueabi-objcopy
    arm-none-linux-gnueabi-cs         arm-none-linux-gnueabi-objdump
    arm-none-linux-gnueabi-elfedit    arm-none-linux-gnueabi-ranlib
    arm-none-linux-gnueabi-g++        arm-none-linux-gnueabi-readelf
    arm-none-linux-gnueabi-gcc        arm-none-linux-gnueabi-size
    arm-none-linux-gnueabi-gcc-4.7.3  arm-none-linux-gnueabi-strings
    arm-none-linux-gnueabi-gcc-ar     arm-none-linux-gnueabi-strip
    arm-none-linux-gnueabi-gcc-nm     cache
    arm-none-linux-gnueabi-gcc-ranlib

    What you can see within this directory are the necessary tools to build/strip/debug/… your c/c++-program – the executables you will use for compiling your project.
    To be able to access these toolchain-executables, add the path e.g. in your .bashrc-file and source it:

    vim ~/.bashrc
     
    # Add the path of the toolchain-executables to your PATH-environment variable  
    export PATH=~/rpi/arm-cs-tools/bin:/usr/local/carlson-minot/crosscompilers/bin:$PATH:
     
    #save and close in vim
    Esc : w q
     
    #source your edited .bashrc file
    . ~/.bashrc
     
    #verify the effect in your environment
    export | grep carlson

    If you are using the zshell instead of the bash you do the same with your .zshrc-file .

    Just one remark: When you are using different toolchains (e.g. ARM, PowerPC, Intel) on your Mac, it might be a better idea to outsource the path to a shellscript, that switches the necessary settings automagically.

    Preparing the Makefile:

    Make yourself a workingdirectory (e.g. mkdir ~/dev/halloc) and change to the directory.

    A possible halloc.cpp-file woud look something like:

    #include <stdio.h>
     
    int main( void )
    {
       printf("\n=====================\nHello world!! This\n
               is your ARM Processor!\n======================\n\n");
       return 0;
    }

    and the corresponding Makefile something like:

    CC=arm-none-linux-gnueabi-g++ -g
    CFLAGS=-c -Wall --sysroot=/usr/local/carlson-minot/crosscompilers/arm-none-linux-gnueabi/libc-2013.05-24-sysroot
    LDFLAGS=--sysroot=/usr/local/carlson-minot/crosscompilers/arm-none-linux-gnueabi/libc-2013.05-24-sysroot -lstdc++
    SOURCES=halloc.cpp
    INCDIR=
    LIBS=
    OBJECTS=$(SOURCES:.cpp=.o)
    EXECUTABLE=halloc
     
     
    all: $(SOURCES) $(EXECUTABLE)
     
    $(EXECUTABLE): $(OBJECTS) $(LIBS)
    	$(CC) $(LDFLAGS) $(OBJECTS) $(LIBS)  -o $@
     
    .cpp.o:
    	$(CC) $(CFLAGS) -I=$(INCDIR) $< -o $@
     
    clean:
    	rm -rf *.o $(EXECUTABLE)

    You will notice the name of the executable of your compiler: arm-linux-gnueabihf-gcc

    When you have saved both files, just type

    [~/dev/halloc]  ll
    total 16
    -rw-r--r--  1 rool  staff   533B  4 Jul 10:24 Makefile
    -rw-r--r--  1 rool  staff   136B  4 Jul 10:23 halloc.cpp
    [~/dev/halloc] make
    arm-none-linux-gnueabi-g++ -g -c -Wall --sysroot=/usr/local/carlson-minot/crosscompilers/arm-none-linux-gnueabi/libc-2013.05-24-sysroot -I= halloc.cpp -o halloc.o
    arm-none-linux-gnueabi-g++ -g --sysroot=/usr/local/carlson-minot/crosscompilers/arm-none-linux-gnueabi/libc-2013.05-24-sysroot -lstdc++ halloc.o   -o halloc
    [~/dev/halloc] ll
    total 48
    -rw-r--r--  1 rool  staff   533B  4 Jul 10:24 Makefile
    -rwxr-xr-x  1 rool  staff    11K 30 Jul 21:13 halloc*
    -rw-r--r--  1 rool  staff   136B  4 Jul 10:23 halloc.cpp
    -rw-r--r--  1 rool  staff   2,8K 30 Jul 21:13 halloc.o
    [~/dev/halloc]

    That’s it – we have a ready made executable compiled for our linux-arm-conglomerate! Congratulations.
    Last thing todo is…

    Deploy executable to target and execute

    From your Mac OS-X, the scp command is available, so I would suggest doing the following (for the Raspberry as an example given):

    cd ~/dev/halloc
    scp halloc pi@192.168.0.101:/home/pi
    #provide user pi's password

    Where 192.168.0.101 is the ip of the taret-device within the network.
    Login to your target, and execute your fresh hallo-world application:

    ssh pi@192.168.0.101
     
    #enter password for login
     
    #execute the halloc-executable directly in the home of the pi-user 
    ./halloc
     
    =====================
    Hello world!! This 
    is your ARM Processor!
    ======================

    Have fun with further cross-compiled executables!