Cross Development¶
Native Compilation¶
Compiler runs on a machine, say
x86_64
Produces code for that machine
Uses header files and libraries from that machine
Default paths for headers and libraries
/usr/include
: e.g.#include <stdio.h>
is found as/usr/include/stdio.h
/usr/lib
,/lib64
, …: e.g.-lpthread
(“linker, please go find me thepthread
library”) is resolved to/lib64/libpthread.so
Cross?¶
Compiler runs on host machine (e.g.
x86_64
)Produces code for the target machine (e.g.
armv7l
)
Simple? ⟶ No
Code must be built against target situation
Header files and libraries
⟶ must be available on host
⟶
sysroot
Must match the target situation ⟶ binary compatibility
Statically linked cross build generally ok
But: shared libraries are a continuous source of pain
Challenges
Cross compiler: finding or building one that works
Trial and error, mostly
Building one: crosstool-ng
Using a metadistribution like Yocto: gives you a cross toolchain as by-product of creating the target rootfilesystem
sysroot
Target root filesystem, in principle
Ideally stripped down to a miniumum
Don’t need target executables on the host, for example (they won’t run)
Ideally a by-product of root filesystem creation
Example: Cross Toolchain And sysroot
Built With crosstool-ng¶
By default, ct-ng
installs the toolchain/sysroot combo in
~/x-tools/
$ ls -l ~/x-tools/
...
dr-xr-xr-x. 1 jfasch jfasch 128 Apr 17 2023 armv8-rpi4-linux-gnueabihf
...
Structure is a bit confusing,
$ ls -l ~/x-tools/armv8-rpi4-linux-gnueabihf
total 1660
dr-xr-xr-x. 1 jfasch jfasch 60 Apr 17 2023 armv8-rpi4-linux-gnueabihf
dr-xr-xr-x. 1 jfasch jfasch 2364 Apr 17 2023 bin
-r--r--r--. 1 jfasch jfasch 1697265 Apr 17 2023 build.log.bz2
dr-xr-xr-x. 1 jfasch jfasch 0 Apr 17 2023 include
dr-xr-xr-x. 1 jfasch jfasch 98 Apr 17 2023 lib
dr-xr-xr-x. 1 jfasch jfasch 6 Apr 17 2023 libexec
dr-xr-xr-x. 1 jfasch jfasch 42 Apr 17 2023 share
Toolchain in bin/
¶
$ ls -l ~/x-tools/armv8-rpi4-linux-gnueabihf/bin/
...
-r-xr-xr-x. 2 jfasch jfasch 1078248 Apr 17 2023 armv8-rpi4-linux-gnueabihf-ar
-r-xr-xr-x. 2 jfasch jfasch 1260352 Apr 17 2023 armv8-rpi4-linux-gnueabihf-g++
-r-xr-xr-x. 2 jfasch jfasch 1256256 Apr 17 2023 armv8-rpi4-linux-gnueabihf-gcc
-r-xr-xr-x. 1 jfasch jfasch 143 Apr 17 2023 armv8-rpi4-linux-gnueabihf-ld
...
Runs on the PC,
$ file ~/x-tools/armv8-rpi4-linux-gnueabihf/bin/armv8-rpi4-linux-gnueabihf-gcc
/home/jfasch/x-tools/armv8-rpi4-linux-gnueabihf/bin/armv8-rpi4-linux-gnueabihf-gcc: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=a5540938c2c36ad2bb371ccfdeaee5e7dbc8d512, stripped
Produces output for the Raspberry Pi (armv8
),
$ ~/x-tools/armv8-rpi4-linux-gnueabihf/bin/armv8-rpi4-linux-gnueabihf-gcc --verbose
...
Target: armv8-rpi4-linux-gnueabihf
...
sysroot
in armv8-rpi4-linux-gnueabihf/sysroot/
¶
$ ls -l ~/x-tools/armv8-rpi4-linux-gnueabihf/armv8-rpi4-linux-gnueabihf/sysroot/
total 0
dr-xr-xr-x. 1 jfasch jfasch 6 Apr 17 2023 etc
dr-xr-xr-x. 1 jfasch jfasch 1654 Apr 17 2023 lib
dr-xr-xr-x. 1 jfasch jfasch 22 Apr 17 2023 sbin
dr-xr-xr-x. 1 jfasch jfasch 58 Apr 17 2023 usr
dr-xr-xr-x. 1 jfasch jfasch 4 Apr 17 2023 var
The situation on the target, made available on the host
Usually a single tree, containing a subset of the target’s root filesystem
Cross Build¶
#include <stdio.h>
int main(void)
{
printf("Hello World\n");
return 0;
}
$ ~/x-tools/armv8-rpi4-linux-gnueabihf/bin/armv8-rpi4-linux-gnueabihf-gcc \
--sysroot ~/x-tools/armv8-rpi4-linux-gnueabihf/armv8-rpi4-linux-gnueabihf/sysroot \
-o hello \
hello.c
Produces a target executable,
$ file hello
/tmp/hello: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-armhf.so.3, for GNU/Linux 6.0.2, with debug_info, not stripped
Does not run on a PC (QEMU?),
$ ./hello
qemu-arm-static: Could not open '/lib/ld-linux-armhf.so.3': No such file or directory
Which shared libraries is it linked against?
$ ldd hello
not a dynamic executable
Ah, wrong ldd
: use the cross ldd
to view dependencies,
$ ~/x-tools/armv8-rpi4-linux-gnueabihf/bin/armv8-rpi4-linux-gnueabihf-ldd --root ~/x-tools/armv8-rpi4-linux-gnueabihf/armv8-rpi4-linux-gnueabihf/sysroot hello
libc.so.6 => /lib/libc.so.6 (0xdeadbeef)
ld-linux-armhf.so.3 => /lib/ld-linux-armhf.so.3 (0xdeadbeef)
Copy to the target, and execute,
$ scp hello my.target.com:
$ ssh my.target.com ./hello
Hello World