Jump to main content | Jump to Primary Navigation | Jump to Sub Navigation


 

Cross-compiling

Wikipedia defines a toolchain as "the set of computer programs (tools) that are used to create a product (typically another computer program or system of programs). The tools may be used in a chain, so that the output of each tool becomes the input for the next, but the term is used widely to refer to any set of linked development tools."

If the toolchain used creates binary programs for a machine architecture other than the host architecture, it is termed a cross-compiler.

Contents

  1. Sample source code (helloworld.c)
  2. Cross-compiling the source
  3. Running your program
  4. Automating the build with GNU make

Sample source code (helloworld.c)

We'll using a trivial code example to illustrate the cross-compilation process. Create a file called helloworld.c containing the following code

#include <stdio.h>

int main(int argc, char **argv)
{
    printf("Hello world!\n");
    return 0;
}

Cross-compiling the source

Now we'll cross-compile this code so that it will run on the embedded controller. To keep things neat we'll first create a variable pointing at the base directory of the toolchain (in this case we're using a Xscale toolchain in /opt/devbot. This might be different for you).

$ export CCROOT=/opt/devbot/armxscale-glibc
$ export CCNAME=arm-xscale-linux-gnu

then invoke the cross-compiler with

$ $CCROOT/bin/$CCNAME-gcc                                                   @
        -I $CCROOT/$CCNAME/include  -I $CCROOT/$CCNAME/include/glib-2.0     @
        -I $CCROOT/$CCNAME/lib/glib-2.0/include                             @
        -L $CCROOT/$CCNAME/lib      -L $CCROOT/$CCNAME/lib/devbot           @
        -pthread -lgthread-2.0 -lrt -lglib-2.0 -lbot                        @
        -o helloworld helloworld.c

The -I and -L flags tell the compiler where to look for headers and libraries respectively. You can check that this has worked by using the standard GNU/Linux file-type detection command file e.g.

$ file helloworld
helloworld: ELF 32-bit LSB executable, ARM, version 1 (ARM), dynamically linked (uses shared libs), not stripped

Obviously this command line is rather unweildy. We therefore strongly recommend using the GNU make utility to automate the process of building your projects. See Automating the build with GNU make below for more details and an example makefile.

Running your program

Since the program is cross-compiled in order to test it, you'll need to transfer it to a machine with the appropriate architecture. scp is the recommended way to transfer files

scp helloworld root@$IP_TARGET:

Automating the build with GNU make

The GNU make tool is commonly used to automate the build process. Full documentation for make can be be found at:

http://www.gnu.org/software/make/manual/make.html

To get you started here is a sample Makefile for the "helloworld" project. Note that this automatically adds support for the DevBot library and its dependencies (glib).

################################################################################
#
# Example Makefile for cross-compilation
#
################################################################################

# Insert the correct toolchain details here
CCROOT=/opt/devbot/armxscale-glibc
CCNAME=armxscale-linux-gnu


# The name of the program
PROGRAM=helloworld
# Objects used by the program (one per .c file)
OBJS=helloworld.o
# Additional libraries used by the program
LIBS=
# Additional C flags
CFLAGS=-Werror
# Drivers
DRIVER_OBJS=

################################################################################
#
# It should not be necessary to alter the following definitions
#
################################################################################

CC=$(CCROOT)/bin/$(CCNAME)-gcc
CCINC=$(CCROOT)/$(CCNAME)/include
CCLIB=$(CCROOT)/$(CCNAME)/lib

$(PROGRAM): $(OBJS)
        $(CC) $(LDFLAGS) -o helloworld $(OBJS) $(DRIVER_OBJS)

%.o:%.c
        $(CC) $(CFLAGS) -c $^

CFLAGS+=-I $(CCINC)
LDFLAGS=-L $(CCLIB)
LDFLAGS+=$(patsubst %,-l%,$(LIBS))

# Devbot libraries/drivers
LDFLAGS+=-L$(CCLIB)/devbot -lbot

# glib-2.0
LDFLAGS+=-lglib-2.0
CFLAGS+=-I$(CCINC)/glib-2.0 -I$(CCLIB)/glib-2.0/include