Sunday, March 13, 2005

pkg-config: A quick introduction

If you have ever tried to check for the presence of a library from a configuration script, you know this is not an easy task. Getting the right compiler (CFLAGS) and linker (LIBS) flags can be very difficult, if not impossible, without manual help from the user.

To detect some libraries, you have to create a little test program and link it against the library you are looking for. If the build is successful, the library is available, and possibly ready to be used. In fact, this is what GNU Autoconf's AC_CHECK_LIB macro does. However, this is not necessarily true, as the detected library may be older than you expected, or may need some extra flags that you didn't think of.

To overcome this difficulty, the *-config scripts were born. These scripts, specific to a library, print the required compiler and linker flags to the standard output, so that the configuration script can get them. For example, consider the glib 1.x library. It includes the glib-config script, which produces the following output:

[dawn jmmv] $ glib-config --cflags
-I/usr/pkg/include/glib/glib-1.2 -I/usr/pkg/lib/glib/include
[dawn jmmv] $ glib-config --libs
-L/usr/pkg/lib -Wl,-R/usr/pkg/lib -lglib

This is certainly nicer than manual detection of libraries, but has a problem: each library has to provide its own script, which may be syntactically incompatible with all other ones (e.g., accepting an -ldflags flag rather than --libs).

And here is where pkg-config comes into play: it generalizes the *-config scripts concept and provides a consistent framework to access library information.

In the pkg-config world, each library installs a special metadata file in a centralized directory (typically, lib/pkgconfig relative to the installation prefix). These files specify the version of the installed library, the compiler and linker flags needed to link to it as well as some other extra information. Then, the pkg-config utility can be used to consistently query this information.

The above glib example becomes the following:

[dawn jmmv] $ pkg-config --cflags glib
-I/usr/pkg/include/glib/glib-1.2 -I/usr/pkg/lib/glib/include
[dawn jmmv] $ pkg-config --libs glib
-Wl,-R/usr/pkg/lib -L/usr/pkg/lib -lglib

We can also ensure that a given version is present:

[dawn jmmv] $ pkg-config --print-errors glib-2.0 ">=" 2.6.0
[dawn jmmv] $ pkg-config --print-errors glib-2.0 ">=" 2.10.0
Requested 'glib-2.0 >= 2.10.0' but version of GLib is 2.6.2

Furthermore, this integrates nicely with configuration scripts generated by GNU Autoconf, as pkg-config provides a macro (PKG_CHECK_MODULES) to trivially query package information.

Unfortunately, not all libraries provide pkg-config metadata files (yet?), so you still need to fallback to the previous mechanisms if available. Furthermore, some people don't like pkg-config, but I can't see why. To me, it's a very neat concept (I'm not talking about its internal implementation, which may be messy) that greatly simplifies things.

3 comments:

Anonymous said...

[Originally posted at 2005-03-14 03:58 am UTC]

The mixed state, some do & some don't is bad. YMMV but I found openssl expectations of a .pc in some pkg (gaim-encryption) bit me.

I've often felt the cost of re-re-re-re-re-running autoconf to find mostly
static values is insane, so I too am temprementally accepting of .pc files to
encode what a given package believed was valid machine state. But I also see why some people dislike this: its better to ask, than assume.

-George

Julio M. Merino Vidal said...

[Originally posted at 2005-03-14 08:00 pm UTC]

About the openssl thing, you are right (I've suffered it too). I think I'll post something about that.

But what do you mean with "running autoconf to find mostly static values"? When you run autoconf, all you need is the pkgconfig.m4 file to be able to use the PKG_CHECK_MODULES macro. Everything else about libraries is searched for while running the configure script, and that data is not "static". (I think I misunderstood you.)

Anonymous said...

[Originally posted at 2005-03-14 11:16 pm UTC]

well for the variant part, I suppose you have to run autoconf to find out but it seems bizarre to me to run a compilation phase to test for the existence of routines when a .pc file type approach can front-load that during install of the library.