CMake: Cross Build¶
Cross Build: Parameters¶
Cross build parameters “toolchain” and “sysroot”
Toolchain: usually a
$PATH
setting and a compiler name (arm-linux-gnueabihf-gcc
)Sysroot: a directory with target artifacts
For a crosstool-ng
built toolchain (unpacked to
/home/jfasch/x-tools/
), the parameters are:
Cross tools |
|
Sysroot |
|
$ /home/jfasch/x-tools/armv8-rpi4-linux-gnueabihf/bin/arm-linux-gnueabihf-gcc \
--sysroot /home/jfasch/x-tools/armv8-rpi4-linux-gnueabihf/armv8-rpi4-linux-gnueabihf \
-o hello-single hello-single.c
Core Build Instructions: Target Agnostic¶
A typical (simple) CMakeLists.txt
…
PROJECT(GreetDemo)
ADD_LIBRARY(greet hello.h hello.c hello-flexible.c)
ADD_EXECUTABLE(hello-first hello-first.c)
TARGET_LINK_LIBRARIES(hello-first greet)
ADD_EXECUTABLE(hello-second hello-second.c)
TARGET_LINK_LIBRARIES(hello-second greet)
Build instructions are target-agnostic
What goes in a library?
What goes into an executable?
What does an executable depend on?
Toolchain Files¶
CMakeLists.txt
is target-agnosticBy default: native compilation
Parameters Sysroot and Toolchain are set in per-target “toolchain files”
# the name of the target operating system
set(CMAKE_SYSTEM_NAME Linux)
# toolchain base directory (crosstool-ng toolchains bring the sysroot
# with them)
set(TOOLCHAIN_BASE_DIR /home/jfasch/x-tools/armv8-rpi4-linux-gnueabihf)
# which compilers to use for C and C++
set(CMAKE_C_COMPILER ${TOOLCHAIN_BASE_DIR}/bin/armv8-rpi4-linux-gnueabihf-gcc)
set(CMAKE_CXX_COMPILER ${TOOLCHAIN_BASE_DIR}/bin/armv8-rpi4-linux-gnueabihf-g++)
# where is the target environment located. funny enough, this doesn't
# appear to influence the --sysroot compiler setting
set(CMAKE_FIND_ROOT_PATH ${TOOLCHAIN_BASE_DIR}/armv8-rpi4-linux-gnueabihf/sysroot)
set(CMAKE_SYSROOT ${TOOLCHAIN_BASE_DIR}/armv8-rpi4-linux-gnueabihf/sysroot)
# adjust the default behavior of the FIND_XXX() commands:
# search programs in the host environment
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
# search headers and libraries in the target environment
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
Toolchain files describe toolchian parameters
⟶ stored not in the project, but rather next to the toolchain
It depends 😉
Step 1: Generate Makefile
in Build Directory¶
Sadly, cross build is a little more involved than native build - even with CMake.
In the build directory for the target architecture …
$ cd /home/jfasch/build-pi # <--- build directory
… you invoke CMake, pointing it to the toolchain file
⟶
CMAKE_TOOLCHAIN_FILE
$ cmake -DCMAKE_TOOLCHAIN_FILE=/home/jfasch/armv8-rpi4-linux-gnueabihf.cmake /home/jfasch/source -- The CXX compiler identification is GNU 11.2.1 -- Detecting CXX compiler ABI info -- Detecting CXX compiler ABI info - done -- Check for working CXX compiler: /usr/bin/c++ - skipped -- Detecting CXX compile features -- Detecting CXX compile features - done -- Configuring done -- Generating done -- Build files have been written to: /home/jfasch/build-pi
This creates a
Makefile
in the build directoryUsed as usual
Only generated ⟶ basically unreadable
Step 2: Build Using make
¶
$ pwd
/home/jfasch/build-pi
$ make
[ 14%] Building C object CMakeFiles/greet.dir/hello.c.o
[ 28%] Building C object CMakeFiles/greet.dir/hello-flexible.c.o
[ 42%] Linking C static library libgreet.a
[ 42%] Built target greet
[ 57%] Building C object CMakeFiles/hello-second.dir/hello-second.c.o
[ 71%] Linking C executable hello-second
[ 71%] Built target hello-second
[ 85%] Building C object CMakeFiles/hello-first.dir/hello-first.c.o
[100%] Linking C executable hello-first
[100%] Built target hello-first
Et voila:
$ ls -l
total 96
-rw-rw-r--. 1 jfasch jfasch 13921 Apr 22 10:58 CMakeCache.txt
drwxrwxr-x. 7 jfasch jfasch 280 Apr 22 11:02 CMakeFiles
-rw-rw-r--. 1 jfasch jfasch 1688 Apr 22 10:58 cmake_install.cmake
-rwxrwxr-x. 1 jfasch jfasch 26192 Apr 22 11:02 hello-first
-rwxrwxr-x. 1 jfasch jfasch 27920 Apr 22 11:02 hello-second
-rw-rw-r--. 1 jfasch jfasch 8102 Apr 22 11:02 libgreet.a
-rw-rw-r--. 1 jfasch jfasch 8503 Apr 22 10:58 Makefile
$ file hello-first
hello-first: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-armhf.so.3, BuildID[sha1]=5db807d9b005b19e1e0c957755fa7ca7b771edcb, for GNU/Linux 3.2.0, with debug_info, not stripped