Hi! I'm ThibG, a French student and Debian user! This summer, I'll be working on Multiarch Cross-Toolchains as a Google Summer of Code student! I'll use this blog to share my progress and thoughts about the project.

Hi, It's been three weeks already since the end of the Google Summer of Code 2012, and I've been told I still haven't blogged about the state of multiarch cross-toolchains. So, here it is!

Building multiarch cross-toolchains

This section is mostly a rehash of my previous post. Cross-toolchains build properly for most architectures in Debian, with the exception of arches having clashing ld.so paths. The following instructions assume you are using Wheezy or unstable, and have applied my patches.

Adding a foreign architecture

You are going to use some packages meant for a different architecture than your native one. This means you'll have to tell dpkg about a foreign architecture, for instance, armel.

# dpkg --add-architecture armel

Then, you need to update apt's database.

# apt-get update

If one of the repository you use only supports a subset of your configured architecture (for instance, when working with an unofficial port), you will need to use arch restrictions in your sources.list (see the manpage).

Cross-binutils

Absolutely nothing has changed there, it works exactly the same way it did before the GSoC. That is, grab binutils' source package, set $TARGET to a GNU triplet or a Debian arch, and run dpkg-buildpackage.

$ apt-get source binutils
$ cd binutils-*/
$ TARGET=arm-linux-gnueabihf dpkg-buildpackage -uc -us -b

Cross-gcc

Building cross-gcc is done the same way it was before the GSoC, except it uses cross-arch dependencies instead of mangled packages for foreign packages. This means you shouldn't use dpkg-cross at all, but use multiarch instead.

If you haven't done so yet, apply my patches.

Then, building the cross-compiler is as easy as running (with $target being a Debian arch name):

$ export DEB_CROSS_NO_BIARCH=yes
$ export GCC_TARGET=$target
$ debian/rules control
$ dpkg-buildpackage -uc -us -b

Biarch/multilib and multiarch do not really play well. Using some trickery, you might be able to build multilib cross-compilers, but I would recommend building two cross-compilers instead.

You will of course need to install the required build-dependencies, some of which are packages for the target architecture, but that is no different from building any other Debian package, provided that multiarch is correctly configured.

This will produce cross-compilers packages using multiarch paths and cross-arch deps, along with some binary packages for the target architecture. Those binary packages are cross-built versions of the runtime libs. They are not needed, as they should be identical to the natively-built ones present in the archive, but using them shouldn't be a problem.

Installing the cross-toolchains

Installing cross-binutils is straightforward, installing cross-gcc itself is, but installing cross-g++ is not. Indeed there is bug #678623: g++-4.7 depends on libstdc++6-4.7-dev, which is multiarch-unaware and depends on g++-4.7. Assuming you've compiled your cross-gcc using my patches, the cross-compiled libstdc++6-4.7-dev will not have these problems, but still won't be co-installable with your native libstdc++6-4.7-dev, since it's not M-A: same. The easiest way to work around this issue is probably to download the binary package, modify its control file to include “Multi-Arch: same”, and install the modified package.

Using the cross-toolchains

Once installed, using the cross-toolchains should be as easy as running “$triplet-gcc-4.7 file.c”. Note the “-4.7” part. Indeed, the cross-compilers packages do not provide the “$triplet-gcc” symlink. This matches what is done with the native compiler pase, where the “gcc” symlink is not provided by the compiler's package, but by the “gcc” package. However, there is no “cross-gcc” package or anything like that yet, which means you have to use the full name, or provide the symlink yourself.

Another issue is pkg-config. To know where to search for libraries, pkg-config has to be told which architecture you are compiling for. Autotools does that by calling “$triplet-pkg-config” instead of “pkg-config” if it exists. The “pkg-config” binary packages comes with a wrapper you can symlink to: “/usr/share/pkg-config-crosswrapper”.

Conclusion

Despite a few shortcomings (bug #678623, missing symlinks, multilib issues and clashing ld.so paths), multiarch cross-toolchains are already usable on Wheezy. There is still quite a lot of work left (like fixing #678623, splitting gcc-4.7 in two, or changing wanna-build, britney etc. to handle cross-arch deps) but hopefully this will be done for Jessie.

Posted Wed Sep 12 18:00:37 2012

Hi! As you may know, I'm working on multiarch cross-toolchains as part of the Google summer of Code (see my previous post for details), and although there is still a lot to do, the project is doing fairly well, and a cross-gcc is already installable and working. I'll proceed with detailed instructions on how to install the cross-compiler, along with some explanations on multiarch itself, and how to build cross-toolchains from source.

Prerequisites

First, you need specific versions apt (>= 0.9.6) and dpkg (>= 1.16.5).
This is because the cross-toolchains packages I'm working on depend on specific cross-arch dependencies, such as libc6:armhf. Support for such dependencies has been added in the aforementioned versions of apt and dpkg. This means you should be running unstable, or at least use dpkg from unstable.

Adding a foreign architecture

Adding a foreign architecture is straightforward, but I've seen users do overcomplicated, or just plain wrong things. So, let's do this step by step (well, there are only two of them), with some explanations.

  1. Tell dpkg to handle an additional architecture by typing dpkg --add-architecture armhf. There isn't much to say. It will only add an architecture to the list of architectures dpkg would accept to handle.

  2. Update APT's database. You need to run apt-get update after adding or removing an architecture to get package lists for all wanted architectures and rebuild APT's database, including the implicit cross-arch dependencies/conflicts brought by multiarch.

And that's it for the common case. Now, a word on architecture restrictions: a common misconception about multiarch seems to be that you have to tell APT which architectures you want from the mirrors by modifying your sources.list file(s). This is not true, as, by default, APT gets the list of accepted architectures from dpkg, and gets the correct package lists from the mirrors configured in the sources.list. You only need to use arch restrictions (“deb [arch=arch1,arch2,...] ...”) when you want to get packages from a mirror only for a subset of your accepted architectures. This is very unlikely, and in the general you do not need to modify your sources.list, at all.

Getting the cross-compilers from my repository

I provide compiled versions of gcc-4.7-arm-linux-gnueabihf for i386 and amd64 in my repository. If you have followed the previous paragraphs, nothing should be easier than adding a “deb http://emdebian.org/~thibg/repo/ sid main” line to your sources.list and doing the following:

# apt-get update
[...]
# apt-get --no-install-recommends install gcc-4.7-arm-linux-gnueabihf
Reading package lists... Done
Building dependency tree       
Reading state information... Done
The following extra packages will be installed:
  binutils-arm-linux-gnueabihf cpp-4.7-arm-linux-gnueabihf gcc-4.7-arm-linux-gnueabihf-base gcc-4.7-base:armhf libc6:armhf libgcc1:armhf
  libgmp10 libgomp1:armhf libmpc2 libmpfr4
Suggested packages:
  binutils-doc gcc-4.7-locales libmudflap0-4.7-dev:armhf gcc-4.7-doc libgcc1-dbg:armhf libgomp1-dbg:armhf libitm1-dbg:armhf
  libquadmath-dbg:armhf libmudflap0-dbg:armhf binutils-gold glibc-doc:armhf locales:armhf
Recommended packages:
  libc6-dev:armhf
The following NEW packages will be installed:
  binutils-arm-linux-gnueabihf cpp-4.7-arm-linux-gnueabihf gcc-4.7-arm-linux-gnueabihf gcc-4.7-arm-linux-gnueabihf-base gcc-4.7-base:armhf
  libc6:armhf libgcc1:armhf libgmp10 libgomp1:armhf libmpc2 libmpfr4
0 upgraded, 11 newly installed, 0 to remove and 0 not upgraded.
Need to get 23.5 MB of archives.
After this operation, 57.2 MB of additional disk space will be used.
Do you want to continue [Y/n]? 

I've disabled the recommends since, libc6-dev:armhf would recommend gcc:armhf itself, which is not co-installable with your native gcc if you have it installed.

Building the cross-toolchain yourselves

If you don't trust the repository above, or simply want to rebuild the toolchain yourself, it is rather simple: get my gcc-4.7 patches and:

$ apt-get source binutils
$ cd binutils-*/
$ TARGET=arm-linux-gnueabihf dpkg-buildpackage -uc -us -b
$ cd ../
# dpkg -i binutils*arm-linux-gnueabihf*.deb
$ apt-get source gcc-4.7
$ cd gcc-4.7/
$ for patch in path/to/the/patches/*.patch; do patch -p1 < $patch ; done
$ GCC_TARGET=armhf debian/rules control
$ GCC_TARGET=armhf dpkg-buildpackage -uc -us -b

Using the cross-compiler

It's easy, but there is a trick, and dpkg-buildpackage -aarmhf won't work out of the box yet, as gcc-4.7-arm-linux-gnueabihf provides the “arm-linux-gnueabihf-gcc-4.7” executable, but no “arm-linux-gnueabihf-gcc” symlink.

So, for the moment:

$ cat > test.c << __EOF__
#include <stdio.h>
int main(void)
{
  printf("Hello world\\n");
  return 0;
}
__EOF__
$ arm-linux-gnueabihf-gcc-4.7 test.c
$ qemu-arm ./a.out 
Hello world

Conclusion

The toolchain is not complete yet (there is some more work to do on binutils and libstdc++, and equivalents to the “gcc”, “cpp”, and “build-essential” packages to provide), but it should still be useful to cross-compile C programs. Multi-arch cross-toolchains for wheezy can definitely be hosted at emdebian, and I hope to clean up the build process so that it could get included in the archive for wheezy+1.

Posted Mon Jul 2 16:55:02 2012

Hi! I have been selected to work on multiarch cross-toolchains as part of the Google summer of Code. Although coding officially started last week, I have been busy with exams and other uni stuff at the time.

Anyway, let's talk about the project itself, that is, multiarch cross-toolchains.

What is multiarch?

In order to understand what the project is about, one need to know what multiarch is. I'll quickly describe it, and I invite anyone interested to read the spec (really, it's interesting, and not that long). Basically, multiarch lets you install binary packages for multiple architectures on one system, and let package managers resolve dependencies as one would expect.

This works by identifying four sets of packages:

  • Packages that don't need to be aware of multi-arch. Such packages can only be installed for one architecture at a time, and can only be used to resolve dependencies of packages having the same architecture.

    Those packages are “Multi-Arch: none” or “multiarch-unaware” packages.

  • Packages that can be installed for multiple architectures at a time, and can only be used to resolve dependencies of packages having the same architecture.

    Those packages are “Multi-Arch: same” packages. They typically are libs.

  • Packages that can only be installed for one architecture at a time but can satisfy dependencies of any package regardless of its architecture.

    Those packages are “Multi-Arch: foreign” packages. They typically are tools working with architecture-independent interfaces. (for instance, gpg, zenity or tar).

  • Packages that can only be installed for one architecture at a time but can satisfy any dependency annotated with “:any”, regardless of the architecture.

    Those packages are “Multi-Arch: allowed” packages. They are packages providing both arch-dependent and arch-independent interfaces. They are typically things like python, which can be used to interpret arch-indep files, but providing arch-dependent interfaces for C extensions.

Anyway, multiarch is an amazing thing that may be of use in various cases, such as running i386-only software on an amd64 system, running armel software on an armhf system, running i386 software on an armhf system using qemu-user-static and binfmt, cross-grading (switching, for instance, from i386 to amd64 on a running system), and, in our case, easing cross-compilation.

State of cross-toolchains in Debian

There aren't really cross-toolchains available in Debian (although some can be built from source packages), but they are available in emdebian's repositories.

However, those packages predate multiarch, and don't make use of it. Instead, they depend on special packages converted using dpkg-cross. Such packages are merely arch: all versions of foreign packages, with files moved to arch-qualified paths to prevent conflicts with “normal” packages.

Such packages thus have to be generated from real packages, either manually or using some sort of automation. In addition, this additional step brings several issues, like keeping in sync converted packages with real packages from the archive.

With multiarch, such packages are rendered useless, and may in fact bring additional problems, since “converted” and multiarch packages may share the same files, and thus may not be co-installable.

Switching from dpkg-cross to cross-arch deps

Cross-toolchains packages currently depend on a few packages converted using dpkg-cross (ex: libc6-$ARCH-cross and libc6-dev-$ARCH-cross for some packages). They need to depend on the “real” package with the right arch (ex: libc6:$ARCH, libc6-dev:$ARCH).

The obvious way to do so is by annotating the dependency with a specific arch qualifier (ex: “Depends: libc6:armhf”). This is, however, not covered by the multiarch spec.

Note that some “lib*-$ARCH-cross” packages will remain (for instance, libgcc1-armhf-cross). Indeed, those packages are different from the packages mentioned above in that they are of the architecture of the build system and actually part of the toolchain itself.
The above isn't actually true. Indeed, those packages are runtime library cross-built during gcc's build.

Likewise, cross-toolchains may build-depend on foreign packages (ex: libc6-dev). Thus, specific arch qualifiers must be handled in the “Build-Depends” source package field too.

Changing dpkg and apt to support that should be fairly straightforward. In fact, I already have a few patches, but I need to refresh them, maybe clean them up a little, and push them a little harder to get them accepted!

Posted Mon May 28 16:24:18 2012