About · Blog · Projects · Papers · Contact

I said I'd never blog

DeforaOS, NetBSD, reverse-engineering and stuff
Cross-compiling Debian packages for hackable:1
Blog post by khorben
on Friday, April 17 2009, 02:00

Member of

I was finally able to create my first cross-compiled Debian package this evening. This wasn't without a lot of pain, and some issues remain. Still, it's worth mentioning how to reproduce it, along with the problems that I have more or less solved along the way.

Requirements

It's somewhat easier to start from hackable:1's cross-compiling environment. In fact there are still a few glitches to get it truly working, as always just create tickets if you get stuck (or solve something yourself).

pkg-config 0.23

In contrast with the current autoconf/automake/libtool's nightmare, pkg-config has managed to make life easier. This is particularly true since its 0.23 release and fix for the PKG_CONFIG_SYSROOT_DIR and PKG_CONFIG_LIBDIR environment variables. In our case, they are set as follows:

export PKG_CONFIG_LIBDIR="/usr/arm-linux-gnueabi/usr/lib/pkgconfig:/usr/arm-linux-gnueabi/usr/share/pkgconfig"
export PKG_CONFIG_SYSROOT_DIR="/usr/arm-linux-gnueabi"
This does two important things:
  • prefix the relevant CFLAGS and LDFLAGS flags with the path to the cross-compiled include and library files;
  • forces pkg-config to only look at the definition files for packages installed in the cross-compilation environment.
Unfortunately, Debian does not include pkg-config 0.23 yet. I have explained how to install it from source, but even better I have packaged the patched 0.23 release in hackable:1. It will appear from the upcoming build bot soon.

libmokoui2

Unlike jbl2024 with neod, I have settled on libmokoui2. Here's a summary of the issues I ran into.

$ dpkg-buildpackage -rfakeroot -us -uc -aarmel
[...]
checking for C compiler default output file name... 
configure: error: C compiler cannot create executables
See `config.log' for more details.
make: *** [config.status] Error 77
dpkg-buildpackage: failure: debian/rules build gave error exit status 2
Here's what said in config.log:

configure:2950: arm-linux-gnueabi-gcc -g -O2  -Wl,-z,defs -lX11 conftest.c  >&5
/usr/lib/gcc/arm-linux-gnueabi/4.3.2/../../../../arm-linux-gnueabi/bin/ld: skipping incompatible /usr/arm-linux-gnueabi/bin/../../lib/libX11.so when searching for -lX11
/usr/lib/gcc/arm-linux-gnueabi/4.3.2/../../../../arm-linux-gnueabi/bin/ld: skipping incompatible /usr/arm-linux-gnueabi/bin/../../lib/libX11.a when searching for -lX11
/usr/lib/gcc/arm-linux-gnueabi/4.3.2/../../../../arm-linux-gnueabi/bin/ld: cannot find -lX11
collect2: ld returned 1 exit status
The solution here is to force the LDFLAGS, as follows:

ifneq ($(DEB_HOST_GNU_TYPE),$(DEB_BUILD_GNU_TYPE))
CROSS= --build $(DEB_BUILD_GNU_TYPE) --host $(DEB_HOST_GNU_TYPE)
LDFLAGS=-L/usr/$(DEB_HOST_GNU_TYPE)/lib -L/usr/$(DEB_HOST_GNU_TYPE)/usr/lib
else
[...]
./configure $(CROSS) --prefix=/usr --mandir=\$${prefix}/share/man --infodir=\$${prefix}/share/info CFLAGS="$(CFLAGS)" LDFLAGS="-Wl,-z,defs $(LDFLAGS)"
This works much better. We even got rid of -lX11, which should not be necessary: it is already required by the other libraries which will be used.

libtool nightmare

This is what drove me nuts again. I am not the only one:

« You might play with compiler and linker flags, try to hack and understand the libtool shell script (best of luck if you can decipher it), and end up cursing the ancestors of those who ever came up with such a dumb system. »

...and so I read it, and cursed endlessly. Thousands of lines of shell stress-testing code. To put it shortly, libtool is re-generated everytime you run ./configure, which appends ltmain.sh to some configuration variables.

At this point, depending on which LDFLAGS you're using, libtool will have a life of its own, sometimes replacing -lname by /usr/lib/libname.so, sometimes not (and ignoring most other flags). This got wrong in our case; in fact, libtool was correct in picking up *.la files (libtool's own library description format) in /usr/arm-linux-gnueabi/usr/lib, but it was blindly trusting them as they mention the libraries are stored in /usr/lib instead.

The solution should have been as "simple" as using -inst-prefix-dir (which I did not know about, and found by reading the code). Unfortunately it wasn't and I had to patch ltmain.sh to obtain what I feel is the correct fix:

test -f "$inst_prefix_dir$add" && add="$inst_prefix_dir$add"
This checks if the library is in the staging directory, which takes then precedence over the normal path.

dh_strip and dh_shlibdeps

I was totally expecting them to break: dh_strip hardcodes strip as the executable to run (instead of $(DEB_HOST_GNU_TYPE)-strip). Likewise, dh_shlibdeps will have to be modified to support cross-compilation. So I temporarily disabled them both.

And the winner is...

It feels good when it works:

dpkg-deb: building package `libmokoui2-dev' in `../libmokoui2-dev_0.3+svn4878-1_armel.deb'.
dpkg-deb: building package `libmokoui2' in `../libmokoui2_0.3+svn4878-1_armel.deb'.
dpkg-genchanges  >../libmokoui2_0.3+svn4878-1_armel.changes
dpkg-genchanges: including full source code in upload
dpkg-buildpackage: full upload (original source is included)
It's not so bad, I learned some :)

Come back...

Creative Commons License RSS