Fixing -rpath-link issues with cross-compilers

If you are using a cross-compiler to build a non-trivial Linux app (e.g. including QT libraries), you may encounter errors like this when linking your binary:

ld.exe: warning: libfontconfig.so.1, needed by .../libQtGui.so, not found (try using -rpath or -rpath-link)
ld.exe: warning: libaudio.so.2, needed by .../libQtGui.so, not found (try using -rpath or -rpath-link)
ld.exe: warning: libglib-2.0.so.0, needed by .../libQtGui.so, not found (try using -rpath or -rpath-link)
ld.exe: warning: libpng12.so.0, needed by .../libQtGui.so, not found (try using -rpath or -rpath-link)
ld.exe: warning: libz.so.1, needed by .../libQtGui.so, not found (try using -rpath or -rpath-link)

The output is usually followed by a long list of undefined reference to `xxx’ errors.

This happens if you a library referenced in your makefile needs some other library that is not explicitly listed in your makefile. E.g. if you were building a QT project and referenced libQtGui (-lQtGui), but did not reference libz (-lz) that is needed by it, you may get this error.

One obvious fix would be to explicitly list all libraries referenced by the ones that are explicitly mentioned in your project (repeating this iteration several times as newly added libraries may also reference some other ones). Another fix would be to add a GCC command-line option similar to the following one:

-Wl,-rpath-link,C:/Cross-compiler/arm-linux-gnueabihf/sysroot/usr/lib/arm-linux-gnueabihf

However, there is a better universal fix.

The root cause:

The problem actually happens when LD invoked by GCC starts resolving library dependencies. Both GCC and LD are aware of the sysroot containing libraries, however LD may be missing one critical component: the /etc/ld.so.conf file. Here’s an example ld.so.conf file from a Raspberry PI system:

include /etc/ld.so.conf.d/*.conf

The /etc/ld.so.conf.d directory contains the following files:

00-vmcs.conf:

/opt/vc/lib

arm-linux-gnueabihf.conf:

# Multiarch support
/lib/arm-linux-gnueabihf
/usr/lib/arm-linux-gnueabihf

libc.conf:

# libc default configuration
/usr/local/lib

The universal solution

 

The problem can be easily solved by copying the LD configuration files to a location where the cross-toolchain’s LD can find them. There’s one pitfall however: if your cross-toolchain was built with MinGW (most are), it probably did not have access to the glob() function so it won’t be able to parse a wildcard-enabled include statement like *.conf. The workaround here is to just manually combine the contents of all .conf files from /etc/ld.so.conf.d and paste them into <your toolchain sysroot directory>\etc\ld.so.conf.

Here.s an example of a merged ld.so.conf file for our Raspberry PI toolchain:

/opt/vc/lib

/lib/arm-linux-gnueabihf
/usr/lib/arm-linux-gnueabihf

/usr/local/lib

Once you create the ld.so.conf file in the correct folder, your toolchain will be able to resolve all shared library references automatically and you won’t see that error message again!