This Time Self-Hosted
dark mode light mode Search

Me and a RaspberryPi: Cross-linking

You can probably guess that my target is not building packages for an embedded device on the device itself. I usually have a good luck with cross-compilation, but I usually also use very nasty hacks to get it to work. This time around I’m trying to use as few hacks as humanly possible. And linking is becoming trouble.

So first of all you need to get your cross compiler, but that’s easy:

# crossdev armv6j-hardfloat-linux-gnueabi

And everything will be taken care of for you. The whole toolchain, prefixed with armv6j-hardfloat-linux-gnueabi- will then be available, including a suitable armv6j-hardfloat-linux-gnueabi-pkg-config so that you don’t have to deal with it manually.

Now you got two options on how you want to proceed: you may only need a single configuration for all your cross-compiled targets, or you may want to customize the configuration. The former case is the easiest: a root will be set up by crossdev in /usr/armv6j-hardfloat-linux-gnueabi so you can just configure it like a chroot and just armv6j-hardfloat-linux-gnueabi-emerge --root=$path to build the packages.

But I considered that a bad hack so I wanted to do something different: I wanted to have a self-contained root and configuration. The newest GCC theoretically allows this in a very simple fashion: you just need to have already the basic components (glibc, for once) in the root, and then you can use the --with-sysroot flag to switch out of the crossdev-installed headers and libraries. Unfortunately, while the compiler behaves perfectly with this switch, the same can’t be said of the link editor.

Indeed, while even ld supports the --with-sysroot parameter, it will ignore it, making it impossible to find the libraries that are not installed in /usr/armv6j-hardfloat-linux-gnueabi. The classical solution to this is to use -L$ROOT/usr/lib -L$ROOT/lib so that the link editor is forced to search those paths as well — unfortunately this can cause problems due to the presence of .la files, and even more so due to the presence of ldscripts in /usr/lib.

You might remember a quite older post of mine that discussed the names of shared libraries. The unversioned libfoo.so name link is used by the link editor to find which library to link to when you ask for -lfoo. For most libraries this alias is provided by a symlink, but for a number of reasons (which honestly are not that clear to me) for libraries that are installed in /lib, an ldscript is created. This ldscript will provide a non-root-relative path to the shared object, so for instance $ROOT/usr/lib/libz.so will point to /lib/libz.so.1 and that’s not going to fly very well unless sysroot gets respected, but luckily for us, this does actually work.

What it seems like, is that at least the BFD link editor coming from binutils 2.23 has trouble with the implementation of --sysroot for search paths only (it works fine when expanding the paths for the ldscripts) — what about the gold link editor that should be the shiniest out there? Well, it looks like --sysroot there, while technically supported, is implemented in an even worse way: it does not use it when expanding the paths in the ldscripts, which is a 2009 fix from Gentoo on the BFD link editor side.

At the end, my current solution involves setting this in the make.conf in the root:

CFLAGS="-O2 -pipe -march=armv6j -mfpu=vfp -mfloat-abi=hard --sysroot=/home/flame/rasppy/root"
CXXFLAGS="${CFLAGS}"
LDFLAGS="-Wl,-O1,--as-needed --sysroot=/home/flame/rasppy/root -Wl,--sysroot=/home/flame/rasppy/root -L=/usr/lib"

PKG_CONFIG_SYSROOT_DIR=/home/flame/rasppy/root
PKG_CONFIG_ALLOW_SYSTEM_LIBS=1
PKG_CONFIG_LIBDIR=/home/flame/rasppy/root/usr/lib/pkgconfig
PKG_CONFIG_PATH=/home/flame/rasppy/root/usr/lib/pkgconfig:/home/flame/rasppy/root/usr/share/pkgconfig

And then use this command as emerge:

% sudo armv6j-hardfloat-linux-gnueabi-emerge --root=/home/flame/rasppy/root --config-root=/home/flame/rasppy/root

And it seems to work decently enough. Some packages, of course, fail to cross-compile at all, but that’s a story for a different time.

Comments 3
  1. I’m not really sure why we create linker scripts in /usr/lib* for shared libraries installed in /lib either, but it is all related to https://bugs.gentoo.org/sho… and gen_usr_ldscript; it isn’t a function of ld.

  2. This doesn’t work for a current Gentoo install – crossdev 20120913 overwritesPKG_CONFIG_SYSROOT_DIR and sets it to /usr/$SYSROOT. The cure is toadd “export SYSROOT=whatever” to the build script, and add $SYSROOTto the -L path.Will(Otherwise it’s magic – it builds packages with no problems at all.)

  3. Quite a lot of linking issues with cross compilation using Crossdev can be cured by running a simplemv $SYSROOT/usr/lib/*.la /somewhere/outside/lib/search/pathas libtool scripts often end up with libdir= set to your host root. In most cases the link can figure things out without libtool’s help, so this should fix more than it breaks (if anything).

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.