For some time now, Unix developers have struggled with the problem of libraries, and more specifically, finding out where they are installed. For example, in the Makefile for a program using the X libraries, you might have:
CFLAGS=-I/usr/X11R6/include
LDFLAGS=-L/usr/X11R6/lib
This works for most systems as the X libraries are usually installed in /usr/X11R6. However, its clearly messy as if they're installed anywhere else (either by the distribution or the sysadmin) you end up having to hand hack the Makefiles of every single program you compile to change the path. autoconf provided a pseudo-solution to this with macros that would search your system for the libraries for you, but still fell over if they were installed in some nonstandard place.

Gtk+ came up with an elegant solution for this: when the library is installed, it places a shell script in your PATH called "gtk-config". Running the shell script lets you find which extra directories to search for include files and libraries. eg.

$ gtk-config --cflags
-I/usr/include/gtk-1.2 -I/usr/include/glib-1.2 -I/usr/lib/glib/include -I/usr/X11R6/include
There is therefore no longer any need to hand hack Makefiles. You can simply put:
CFLAGS=`gtk-config --cflags`
LDFLAGS=`gtk-config --libs`
This will then work on any system. The packate no longer needs to know where the libraries it uses are installed, as the script takes care of finding them.

Unfortunately, while elegant this mechanism also creates problems of its own. Consider the GNOME system which has in excess of 20 libraries, all with their own scripts. Before long you have glib-config, gconf-config, gnome-config, sdl-config and half a dozen others cluttering your PATH.

The pkg-config approach solves this by unifying the scripts into a single script named pkg-config. It comes from the freedesktop.org group, creating cross-desktop standards for linux. pkg-config has been used extensively for all the libraries in GNOME 2.x.

The approach is simple; instead of installing a shell script, the library installs a .pc file. These look like this:

prefix=/usr
exec_prefix=${prefix}
libdir=${exec_prefix}/lib
includedir=${prefix}/include
gconf_serverdir=${prefix}/lib/gconf2

Name: gconf
Description: GNOME Config System.
Version: 2.2.0
Requires: ORBit-2.0
Libs: -L${libdir} -lgconf-2
Cflags: -I${includedir}/gconf/2
Compiling is then a simple process of calling pkg-config with a list of the packages you want to use, eg:
PACKAGES=gtk+-2.0 gconf-2.0
CFLAGS=`pkg-config --cflags $(PACKAGES)`
LDFLAGS=`pkg-config --libs $(PACKAGES)`
This system also dependencies on other libraries and pkg-config will automatically include other libraries that the ones you have specified depend on. It allows extra data to be stored about the packages, such as a human readable description and a version number.

By default, pkg-config looks for .pc files in /usr/lib/pkgconfig, but you can specify other directories for it to search by setting the PKG_CONFIG_PATH variable.