Cross Compiling With pkg-config
This document summarises the proposal for adding cross compilation support to pkg-config. Some people currently cross compile with pkg-config, but it requires knowledge of extra pkg-config specific environment variables.
Related to cross compiling, it would also be nice if pkg-config supported bi-arch and multi-arch systems better.
Current Support
The pkg-config tool works with a collection of .pc files that describe available packages for linking. These files are located using the following rules:
- searching directories listed in
$PKG_CONFIG_PATH - when
$PKG_CONFIG_LIBDIRis specified, it will override the compiled in default directory (e.g./usr/lib/pkgconfig) and the PKG_CONFIG_PATH.
Note that when specifying PKG_CONFIG_LIBDIR, pkg-config will completely ignore the content in PKG_CONFIG_PATH, even if the documentation states different things.
In a cross compile situation, some .pc files on the system will be for the build machine and some will be for the target machine. In order to make sure that the build machine's .pc files are not found, both the $PKG_CONFIG_PATH and $PKG_CONFIG_PATH environment variables must be set to directories containing only target machine `.pc files.
The same is true in a bi-arch/multi-arch setup.
Proposed Changes
The following changes are based on discussions with Wolfgang Wieser (most of the ideas are originally his).
A new --host option
In order for pkg-config to be smart about picking what .pc files to use, it needs to know the what it is targetting. The proposed solution to this is to add a --host option to the program with the following behaviour:
- takes a string representation of the target machine as an argument
defaults to a compiled in default determined when
pkg-configwas built. ThePKG_PROG_PKG_CONFIGautoconf macro would be modified to pass this argument topkg-config. The code would be something like this:AC_REQUIRE([AC_CANONICAL_HOST]) ... find pkg-config ... PKG_CHECK_EXISTS([pkg-config >= 0.XXX], [pkgconfig_supports_host=true], [pkgconfig_supports_host=false]) if $pkgconfig_supports_host; then PKG_CONFIG="$PKG_CONFIG --host $host" fi(where0.XXXis the first version that supports the--hostoption).
Host Strings
The $host string produced by autoconf comes from one of two places:
- the result of
config.guess - if the user passes
--hosttoconfigure, then that string is passed throughconfig.subto canonicalise it These strings are of the formCPU-VENDOR-OSwhereOSis eitherSYSTEMorKERNEL-SYSTEM.
Not all of the information in this string is relevant, so we will need to do some canonicalisation too:
- On a i686 Linux system,
config.guessoutputsi686-pc-linux-gnu. On an i586, we geti586-pc-linux-gnueven if the two systems have an identical set of libraries installed. Some vendors might insert their name into the host string of some executables they produce. For instance
config.guessoutputsx86_64-unknown-linux-gnuon AMD64 machines, yet some programs on Fedora are configured asx86_64-redhat-linux-gnu. So the canonicalisation would need to be some combination of:canonicalise compatible architectures
- drop vendor
- drop
SYSTEMwhenKERNELis given?
Identifying Host Type for .pc Files
Two possible ways of identifying what host type a particular .pc file is for are:
- place
.pcfiles in host type specific subdirectories.pkg-configthen searches these host-specific subdirectories before the base directories when processing the search path. - add a
Host:header to.pcfiles giving the host type they are for. I favour the first solution.
This leaves the question of what to do with .pc files for which we can't determine the architecture. There are a few things to consider here:
- Treat them as belonging to the default host type. This is almost definitely the right choice for things in the default search path. Would break current cross-compile practices to do this for stuff in
$PKG_CONFIG_PATH(this might be acceptable). - Files in
/usr/share/pkgconfig. Newer versions ofpkg-configadd this directory to the default search path. For the multi-arch case, these files should be used in all cases. For cross-compile, perhaps these should be ignored. The most compatible solution seems to be to always include files in the base dirs of$PKG_CONFIG_PATH, but use different default search paths for different host types.
Default Search Path
A lot of multi-arch and cross-compile problems can be avoided by being a bit smarter about the default search path. With the help of the --host option, it should finally be possible to do this. For instance, on an AMD64 bi-arch box, the following would be the appropriate:
* <table class="mointable">
<tr>
<td><strong>host type</strong> </td>
<td><strong>default path</strong> </td>
</tr>
<tr>
<td><code>x86_64-linux</code> </td>
<td><code>/usr/lib64/pkgconfig</code>, <code>/usr/share/pkgconfig</code> </td>
</tr>
<tr>
<td><code>i386-linux</code> </td>
<td><code>/usr/lib/pkgconfig</code>, <code>/usr/share/pkgconfig</code> </td>
</tr>
<tr>
<td><em>other</em> </td>
<td><em>nothing</em> </td>
</tr>
This would generally do the right thing when configuring packages for the two architectures the machine supports, and when cross compiling to another system the default search path would not interfere.
This could either be configured as a table compiled into the pkg-config executable, or as an external config file (given pkg-config doesn't have a config file currently, it might be better to compile it in).
Package Changes
For the most part, packages that only search for installed pkg-config packages would not need any major modifications -- they would just need to regenerate their configure script with the updated macros so that --host gets passed through to pkg-config.
For packages that want to install .pc files, they will need to be modified in order to install the .pc files in the right host-specific subdirectory. It should be possible to wrap the logic for determining the subdirectory inside an autoconf macro (it would probably need to ask pkg-config what the canonical form of the host string is).
References
- LSB multi-arch ideas (not standardised)
- Debian multi-arch status
