Cross Compiling in C++
Cross compilation happens when we are compiling the program on a system different to what the program will be running on.
It is used widely in embedded development, because many embedded devices lack the capacity for some serious compiling work. Hence, we would compile these programs on a powerful host machine and then ship them to the target machine (i.e. the embedded system).
Compile for ARMv7 under x64 Linux
Using CMake + GCC Toolchain
A more conventional way to do so is to use the GCC toolchain, i.e. the gcc
/g++
compilers, the ld
linker, and the libstdc++
libraries.
The toolchain should be included in most of the GNU/Linux systems. However, for cross compiling, we need to separately install the compilers and libraries for that specific architecture.
Here is a list of packages that worked for me under Ubuntu 18.04:
gcc-7-arm-linux-gnueabihf
gcc-7-multilib-arm-linux-gnueabihf
g++-7-arm-linux-gnueabihf
g++-7-multilib-arm-linux-gnueabihf
binutils-arm-linux-gnueabihf
libgcc1-armhf-cross
libstdc++-7-dev-armhf-cross
To do the actual compiling, you should include the following lines in the CMake file, which specifically tells it to use the gcc cross compiler for armhf and to compile for that architecture. Tweak the -march
and -mcpu
flag according to your platform and then you should be able to compile it as usual.
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR arm)
set(CMAKE_C_COMPILER arm-linux-gnueabihf-gcc-7)
set(CMAKE_CXX_COMPILER arm-linux-gnueabihf-g++-7)
# Some websites also adds "-mfloat-abi=hard" which produces error in my environment (gcc v7.5)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -march=armv7-a -mcpu=cortex-a9")
If there are still errors produced at the linking stage, check if the linked libraries are also compiled in the wanted architecture (i.e. armhf). You may also need to cross-compile them from source.
References
- cmake-toolchains(7)
- Cross-Compiling from x86_64 to ARM - How To Cross-Compile Clang/LLVM using Clang/LLVM
Using CMake + LLVM Toolchain
Clang in the LLVM Toolchain is inherently a cross compiler, so it should theoretically be easier to work (while in reality...I gave up while compiling on a Ubuntu 18.04)
In LLVM, we use clang
as compiler, lld
as linker, and libc++
as libraries.
TODO: figure out how to get this to work.
You should set the target triplet based on the architecture you wan to compile to. Then, you should be able to compile as usual.
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_PROCESSOR arm)
set(triple arm-linux-gnueabihf)
set(CMAKE_C_COMPILER clang)
set(CMAKE_C_COMPILER_TARGET ${triple})
set(CMAKE_CXX_COMPILER clang++)
set(CMAKE_CXX_COMPILER_TARGET ${triple})