Multilib weirdness

13.04.2013 21:41

Multilib is a mechanism in GCC for handling multiple binary versions of a single library that have been compiled using different compiler options. This is useful for instance when compiler options affect the ABI and the linker has to choose the correct library version to link your program with. ARM architecture with its multitude of ABIs and floating point unit options is a prime example where this comes in handy.

Multilib works by mapping compiler command-line options to directories where libraries can be found. For instance, GCC compiled with my fork of summon-arm-toolchain says this about its multilib support:

$ arm-none-eabi-gcc -print-multi-lib
.;
thumb;@mthumb
fpu;@mfloat-abi=hard

What this says is that binaries compiled with -mthumb will be linked with libraries that appear under thumb/ and binaries with -mfloat-abi=hard will use libraries under fpu/ relative to the usual library search path.

However:

$ arm-none-eabi-gcc -print-multi-directory -mthumb
thumb
$ arm-none-eabi-gcc -print-multi-directory -mfloat-abi=hard
.

While thumb option seems to work as expected, the hardware-float libraries don't appear to be used. Why is that?

It turns out that multilib is somewhat smarter than what the documentation and -print-multi-lib would lead you to believe. It doesn't just check the options that you give GCC explicitly on the command line but also their default values.

It seems that -print-multi-lib assumes built-in default values for these options. It believes that fpu/ versions have been compiled using ARM, not thumb mode. But since -marm is default, it doesn't print it out explicitly.

However, this GCC has been compiled using --with-mode=thumb, which changes the default to -mthumb:

$ arm-none-eabi-gcc -v
Using built-in specs.
COLLECT_GCC=arm-none-eabi-gcc
COLLECT_LTO_WRAPPER=/home/avian/local/libexec/gcc/arm-none-eabi/4.6.3/lto-wrapper
Target: arm-none-eabi
Configured with: ../gcc-4.6.3/configure --target=arm-none-eabi
--prefix=/home/avian/local --enable-interwork --enable-multilib --with-newlib
--disable-shared --with-gnu-as --with-gnu-ld --disable-nls --disable-werror
--with-system-zlib --with-arch=armv7-m --with-mode=thumb --with-float=soft
Thread model: single
gcc version 4.6.3 (GCC)

Multilib is smart enough to know that libraries under fpu/ won't work with code compiled with -mthumb and falls back to the default directory and hopes for the best. So, to get the compiler to use libraries under fpu/, you have to explicitly set it to ARM mode:

$ arm-none-eabi-gcc -print-multi-directory -marm -mfloat-abi=hard
fpu

By the way, the combinations of options and directory names printed out by -print-multi-lib are set using MULTILIB_OPTIONS and friends in gcc/config/arm/t-arm-elf in the GCC source tree.

Posted by Tomaž | Categories: Code

Add a new comment


(No HTML tags allowed. Separate paragraphs with a blank line.)