#### CrossCompiling for Arm on Debian

##### Compile for ARM Hard Float from the comfort of your debian laptop
C tech embedded gcc cross-compiler IOT M2M

# CrossCompiling for Arm on Debian

## ARM boards

Arm processors are everywhere, and will soon land on the desktop as well. So far, they provide quite nice functionalities for embedded application. Chances are, you will have some ARM board lying around. You probably also have a way to install a compiler on top of your board, and compile directly on it.

But if you are either doing something more professional, or you want for example introduce some CI tool, you don’t want to compile on the board, and you are going to need a cross-compiling setup.

This used to be more complex that it is now, and I’d encourage anyone to setup a build chain in order to be able to compile code for an architecture different from the one you are running on.

## The code

Let’s say you are trying to compile some C fragment that goes like this:

#include <stdio.h>

int main(int argc, char *argv[]){
printf("whatever\n");
return 0;
}


The command that will bring a cross-compiler to life for yourself is the following:

apt-get install gcc-arm-linux-gnueabihf


Needless to say, you need to be root in order to install packages, or you can use sudo if you want. Now that you have installed the cross tools, you will see that you will have available some variation of the following commands:

arm-linux-gnueabihf-addr2line
arm-linux-gnueabihf-ar
arm-linux-gnueabihf-as
arm-linux-gnueabihf-c++filt
arm-linux-gnueabihf-cpp
arm-linux-gnueabihf-cpp-6
arm-linux-gnueabihf-dwp
arm-linux-gnueabihf-elfedit
arm-linux-gnueabihf-gcc
arm-linux-gnueabihf-gcc-6
arm-linux-gnueabihf-gcc-ar
arm-linux-gnueabihf-gcc-ar-6
arm-linux-gnueabihf-gcc-nm
arm-linux-gnueabihf-gcc-nm-6
arm-linux-gnueabihf-gcc-ranlib
arm-linux-gnueabihf-gcc-ranlib-6
arm-linux-gnueabihf-gcov
arm-linux-gnueabihf-gcov-6
arm-linux-gnueabihf-gcov-dump
arm-linux-gnueabihf-gcov-dump-6
arm-linux-gnueabihf-gcov-tool
arm-linux-gnueabihf-gcov-tool-6
arm-linux-gnueabihf-gprof
arm-linux-gnueabihf-ld
arm-linux-gnueabihf-ld.bfd
arm-linux-gnueabihf-ld.gold
arm-linux-gnueabihf-nm
arm-linux-gnueabihf-objcopy
arm-linux-gnueabihf-objdump
arm-linux-gnueabihf-ranlib
arm-linux-gnueabihf-size
arm-linux-gnueabihf-strings
arm-linux-gnueabihf-strip


Probably, in order to compile your dummy code sample, the following would be enough:

arm-linux-gnueabihf-gcc whatever.c -o whatever


But I’d not recommend it, because if you’re serious about writing code, you’ll probably find yourself repeating the same commands a thousand times, then maybe you want to run it on your current architecture, and then you want to use the linker… if you don’t see the point by now: it will quickly start to explode in tiny micro-issues that need to be handled by hand.

You might have different preferences when it comes to build systems, but I think the old Make is still a good tool for the trade. If it isn’t for yourself, you’d probably won’t have a hard time to adapt the following ideas to your favourite shiny build tool.

As a practical example, let’s say you have a file with a main: whatever.c and a file with function definitions blink.c. You’ll normally compile them with a Makefile like that:

all: whatever

whatever.o: whatever.c
cc -c whatever.c

clean:  whatever
rm *.o; rm whatever



The hint is to replace explicit calls to compiler with variables, and not just the compiler, but also linker and other binutils. To put it simply, you can just prefix your Makefile with:

CC=${CROSS_COMPILE}gcc CXX=${CROSS_COMPILE}g++
RANLIB=${CROSS_COMPILE}ranlib LD=${CROSS_COMPILE}ld
LDXX=${CROSS_COMPILE}g++ AR=${CROSS_COMPILE}ar


Now that you’re in the game, I’d recommend trowing in also the flags:

CFLAGS= -g -Wall
LDFLAGS= -g -Wall


that are just so damn useful when you’re putting together some meaningful piece of code.

So, to recap, if your code is the following:

//blink.c
#include <stdio.h>
}



and:

//blink.h

#endif


the main file:

//whatever.c
#include <stdio.h>

int main(int argc, char *argv[]){
printf("whatever\n");
return 0;
}



You can have the following makefile:

CC=${CROSS_COMPILE}gcc CXX=${CROSS_COMPILE}g++
RANLIB=${CROSS_COMPILE}ranlib LD=${CROSS_COMPILE}ld
LDXX=${CROSS_COMPILE}g++ AR=${CROSS_COMPILE}ar

all: whatever

whatever.o: whatever.c
${CC} -c whatever.c blink.o: blink.c blink.h${CC} -c blink.c

${CC} whatever.o blink.o -o whatever clean: whatever rm *.o; rm whatever  This is supposed to work like this, for your native architecture, just issue the command: make  and you’ll be able to compile. The following, in order to clean the builÃds: $ make clean
rm *.o; rm whatever

gcc -c whatever.c


Now you can exploit the use of variables, and issue the command:

make CROSS_COMPILE=arm-linux-gnueabihf-


You will see the result will be that the cross-compiler is used, instead of the one for your running architecture:

arm-linux-gnueabihf-gcc -c whatever.c


Your whatever binary is now compiled for ARM hard float, and you can check it like that:

\$ file whatever
whatever: ELF 32-bit LSB shared object, ARM, EABI5 version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-armhf.so.3, for GNU/Linux 3.2.0, BuildID[sha1]=5673161126e8511971a0b8111868d2ac9a723057, not stripped


You will probably throw the command itself in a script, like:

cat build.sh
#! /bin/bash -x

make CROSS_COMPILE=arm-linux-gnueabihf-