-
Notifications
You must be signed in to change notification settings - Fork 9
cross compile
cross-compilation == software is compiled on machine (architecture) A for running on machine architecture B.
- A is called the build host which is typically a Linux x86 or amd64 machine, and
- B the target which is here the RasPi, having an armv7-a architecture.
Cross-compilation is by no means restricted to Yocto Project, but we focus here on it.
Yocto Project installed and already successfully bitbaked something, e.g. an image. A 64-bit Linux build host is assumed, otherwise the paths are slightly different.
The ${BUILDDIR}/tmp/sysroots/x86_64-linux
folder contains tools for cross-compilation like the compiler
${BUILDDIR}/tmp/sysroots/x86_64-linux/usr/bin/arm-poky-linux-gnueabi/arm-poky-linux-gnueabi-gcc
which
you may start with the -v option to see its configuration:
frank@FrankBuntuSSD:~/rpi/build$ ${BUILDDIR}/tmp/sysroots/x86_64-linux/usr/bin/arm-poky-linux-gnueabi/arm-poky-linux-gnueabi-gcc -v
In the (lengthy) output look for strings like Target: arm-poky-linux-gnueabi
and --build=x86_64-linux --host=x86_64-linux --target=arm-poky-linux-gnueabi
.
Although the compiler could be used directly, we prefer using it form a devshell. This is the typical Yocto Project workflow which not only provides the compiler but a cross-compilation environment.
Note for advanced users: It is possible to extract a complete cross-compilation environment (called SDK) for use on a different build host. Those SDKs can be integrated into an Eclipse or Qt Creator IDE, and, if properly installed, support automatic deployment to the target, cross-debugging, and so on.
There is a hello-single
example in ${BUILDDIR}/../recipes/poky/documentation/ref-manual/examples/
.
Create a new folder recipes-examples
in the ${BUILDDIR}/../recipes/meta-raspberrypi/
folder.
From a bitbake shell copy the whole hello-single
folder structure to the meta-raspberrypi
layer like this:
frank@FrankBuntuSSD:~/rpi/build$ cp -r ${BUILDDIR}/../recipes/poky/documentation/ref-manual/examples/hello-single ${BUILDDIR}/../recipes/meta-raspberrypi/recipes-examples
frank@FrankBuntuSSD:~/rpi/build$ tree ${BUILDDIR}/../recipes/meta-raspberrypi/recipes-examples
/home/frank/rpi/build/../recipes/meta-raspberrypi/recipes-examples
└── hello-single
├── files
│ └── helloworld.c
└── hello.bb
Note: In general, it is not recommended to copy files into someone else's layer. Before doing so, you should fork that layer, create a working branch, or create your own layer. We do it here for simplicity.
The recipe needs a little fix: the compile command should be:
do_compile() {
${CC} helloworld.c -o helloworld ${LDFLAGS}
}
Do not bitbake hello, because this would create to much files for starting. If you really want to test the recipe, make a dry-run: bitbake -n hello
.
On the build host open a bitbake shell and, from there, a devshell for hello:
frank@FrankBuntuSSD:~/rpi/build$ bitbake -c devshell hello
A new window opens, execute the tree command in it to look around:
root@FrankBuntuSSD:~/rpi/build/tmp/work/cortexa7hf-neon-vfpv4-poky-linux-gnueabi/hello/1.0-r0# tree
.
├── helloworld.c
├── patches
├── pseudo
│ ├── files.db
│ ├── logs.db
│ ├── pseudo.lock
│ ├── pseudo.log
│ ├── pseudo.pid
│ └── pseudo.socket
└── temp
├── log.do_devshell -> log.do_devshell.30728
├── log.do_devshell.30728
├── log.do_fetch -> log.do_fetch.30721
├── log.do_fetch.30721
├── log.do_patch -> log.do_patch.30726
├── log.do_patch.30726
├── log.do_unpack -> log.do_unpack.30722
├── log.do_unpack.30722
├── log.task_order
├── run.base_do_fetch.30721
├── run.base_do_unpack.30722
├── run.do_devshell -> run.do_devshell.30728
├── run.do_devshell.30728
├── run.do_fetch -> run.do_fetch.30721
├── run.do_fetch.30721
├── run.do_patch -> run.do_patch.30726
├── run.do_patch.30726
├── run.do_qa_unpack.30722
├── run.do_terminal.30728
├── run.do_unpack -> run.do_unpack.30722
├── run.do_unpack.30722
└── run.patch_do_patch.30726
You see the source code and some auxiliary files, mostly scripts and logfiles for the bitbake phases executed to open that devshell. The cross compiler can be used to build the result. The file
command is used to check that we have built an ARM executable:
root@FrankBuntuSSD:~/rpi/build/tmp/work/cortexa7hf-neon-vfpv4-poky-linux-gnueabi/hello/1.0-r0# arm-poky-linux-gnueabi-gcc -march=armv7ve -marm -mfpu=neon-vfpv4 -mfloat-abi=hard -mcpu=cortex-a7 -Wl,-O1 -Wl,--hash-style=gnu -Wl,--as-needed --sysroot=/home/frank/rpi/build/tmp/sysroots/raspberrypi3 helloworld.c -o helloworld
root@FrankBuntuSSD:~/rpi/build/tmp/work/cortexa7hf-neon-vfpv4-poky-linux-gnueabi/hello/1.0-r0# file helloworld
helloworld: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux-armhf.so.3, for GNU/Linux 3.2.0, BuildID[sha1]=c5fd3620b555c21de821324d19bfdd9b8b079649, not stripped
Note that quite a few options are necessary to make the cross compiler happy. We could have achieved the same result much simpler from a bitbake shell by executing:
frank@FrankBuntuSSD:~/rpi/build$ bitbake -c compile hello
Note: compile is not the last phase of bitbake. A complete bitbake hello
will also build a package and put it in the deployment folder for the package server.
Note: hello would not be included in any image unless specifically included in the image recipe or required by some other recipe in the image.
Makefiles are popular to build larger software projects by a simple make
, but a Makefile contains architecture specific flags and commands. There are several preprocessing steps which are better suited for cross compilation.
- Autotools Mythbuster https://autotools.io/index.html
- Specifying target triplets (autoconf) https://www.gnu.org/software/autoconf/manual/autoconf-2.65/html_node/Specifying-Target-Triplets.html