Cross Compilation Reference
In this section, you will find some help about cross compiling your app. The difficulty of cross-compîlation varies depending on the complexity of the app and its dependencies.
In the case of a single program written in C or C++, and not linking with third party libraries, cross compiling will be very straighforward.
In more complicated cases, this can require more work in order to correctly get the desired result.
Some of the existing build systems, such as GNU Automake and CMake, provide some cross-compilation support.
We will first present the Supported Architectures and Toolchains, which will allow finding out the tools you need to use for you app, depending on the NAS device you’re targetting.
You will then find here some help about cross compiling with automake , CMake or a simple Makefile.
Supported Architectures and Toolchains
NAS OS supports two architectures: ARMv7
and Intel x86_64
. The
toolchains for these architectures are shipped with the NAS OS SDK
development environment in /opt
CPU | Architecture | Toolchain |
---|---|---|
Marvell Armada 370 | armv7l | armv7-marvell-linux-gnueabi-hard_i686_64K_201308_2123 |
Intel Atom D2701 | x86_64 | x86_64-seagate-nasos-sdk |
Intel Celeron G1610T | x86_64 | x86_64-seagate-nasos-sdk |
Intel Silvermont | x86_64 | x86_64-seagate-nasos-sdk |
You can determine the NAS architecture with the following command:
uname -m
If the architecture is x86_64
, you can examine the content of /proc/cpuinfo
to get more information about the CPU:
grep 'model name' /proc/cpuinfo | head -n 1
This should return something like:
model name : Intel(R) Atom(TM) CPU D2701 @ 2.13GHz
Using Automake
In this section, we will create a very simple C program that will be built with
Automake. If you are just interested in what option to pass to a configure
script, you can jump straight the configure_ step. Here is the program’s source
code:
/* hello.c */ #include <stdio.h> #include <sys/utsname.h> int main(void) { struct utsname utsname; uname(&utsname); printf("Hello, from %s\n", utsname.machine); return 0; }
Autoconf is used to generate the configure
script and the makefiles are
generated with Automake. The configure.ac
is as follows:
AC_INIT([hello], [1.0], [support@mycompany.com]) AM_INIT_AUTOMAKE([-Wall -Werror]) AC_PROG_CC AC_CONFIG_FILES([Makefile]) AC_OUTPUT
The Makefile.am
contains the targets for our program:
hello_SOURCES = hello.c bin_PROGRAMS = hello
We are now ready to generate the configure
script. We need to create some
files that are required by autoreconf
:
touch NEWS README AUTHORS ChangeLog autoreconf --install
In order to cross-compile our hello program, we have to provide the prefix of
the cross-compiler to the configure
script. For instance, the prefix of the
cross-compiler for Marvell Armada 370 is arm-marvell-linux-gnueabi
. Let’s
define an environment variable for it:
export TOOLCHAIN_PREFIX=arm-marvell-linux-gnueabi
It means that the name of the tools provided by the cross-compiler start with the same identifier:
- The C compiler is
$TOOLCHAIN_PREFIX-gcc
- The C++ compiler is
$TOOLCHAIN_PREFIX-g++
- The linker is
$TOOLCHAIN_PREFIX-ld
- The assembler is
$TOOLCHAIN_PREFIX-as
These tools are located in the cross-compiler binary directory. For instance:
/opt/armv7-marvell-linux-gnueabi-hard_i686_64K_201308_2123/bin
Again, we’ll use a variable for it:
export TOOLCHAIN_DIR=/opt/armv7-marvell-linux-gnueabi-hard_i686_64K_201308_2123
The binaries in this directory need to be accessible by the configure and make
tools, which means it must be reference in the $PATH
environment variable.
export PATH=$PATH:$TOOLCHAIN_DIR/bin
The prefix should be passed as the --host
option to the configure
script:
./configure --host=$TOOLCHAIN_PREFIX make
You can check that the hello
binary is an executable for the ARM architecture
with the file
command:
file hello
Which should return something like:
hello: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), dynamically linked...
Finally, you can run hello
on the target or use qemu-arm
to emulate it:
./hello Hello, from armv7l
The configure script provides some options that you may want to change. For
instance, option --prefix
defaults to /usr/local
, but you probably want to
set it to /usr
.
The last step is to install the application with make install
. Since you
don’t want to install the application on your host machine, you should set the
destination directory to a different location:
mkdir ./export make install DESTDIR=$PWD/export
The export
directory will contain the generated binaries.
Using CMake
CMake supports cross compilation since version 2.6. Here is a minimal
CMakeLists.txt
for our hello application:
project(target-isns "C") cmake_minimum_required(VERSION 2.6) add_executable(hello hello.c) install(TARGETS hello RUNTIME DESTINATION bin)
CMake should be instructed to use a cross compiler by setting the
CMAKE_C_COMPILER
and CMAKE_CXX_COMPILER
(for C++ projects) variables.
Let’s cross-compile the hello
binary using CMake:
mkdir build cmake .. -D CMAKE_INSTALL_PREFIX=/usr -DCMAKE_C_COMPILER=$TOOLCHAIN_PREFIX-gcc -- The C compiler identification is GNU 4.6.4 -- Check for working C compiler: /opt/armv7-marvell-.../bin/arm-marvell-linux-gnueabi-gcc -- Check for working C compiler: /opt/armv7-marvell-.../bin/arm-marvell-linux-gnueabi-gcc -- works ... make file hello hello: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), dynamically linked... mkdir ./export make install DESTDIR=$PWD/export
Using Make
Sometimes, the application just uses GNU Make as its build system. The Makefiles often contain some variables that you can override for cross-compilation. You should examine the Makefile and look for some variables that you can customize. Here are some commonly used variables:
-
$CROSS_COMPILE
: if present, you can try to set it to$TOOLCHAIN_PREFIX
:export CROSS_COMPILE=$TOOLCHAIN_PREFIX
-
$CC
: ifCROSS_COMPILE
does not exist, you can try to set the value ofCC
to the cross compiler name:export CC=$TOOLCHAIN_PREFIX-gcc
-
In some cases, you may need to set the values of
LD
(linker) andCXX
(C++ compiler) as well:export LD=$TOOLCHAIN_PREFIX-ld export CSS=$TOOLCHAIN_PREFIX-g++
The variables should be passed as arguments to make
. For instance:
make CROSS_COMPILE=$TOOLCHAIN_PREFIX-