Wednesday, August 3, 2011

pkg-config

A reasonably brief post about pkg-config, which we used to help build matplotlib the other day (here).

The web page is here and there is a guide here.

As it says on the first page:

pkg-config is a helper tool used when compiling applications and libraries. It helps you insert the correct compiler options on the command line so an application can use gcc -o test test.c `pkg-config --libs --cflags glib-2.0` for instance, rather than hard-coding values on where to find glib (or other libraries). It is language-agnostic, so it can be used for defining the location of documentation tools, for instance.

And from the man page:


DESCRIPTION
The pkg-config program is used to retrieve
information about installed libraries in the
system. It is typically used to compile and
link against one or more libraries. Here is a
typical usage scenario in a Makefile:

program: program.c
cc program.c $(pkg-config --cflags --libs gnomeui)

pkg-config retrieves information about pack-
ages from special metadata files. These files
are named after the package, and has a .pc
extension. On most systems, pkg-config looks
in and
for these files. It will additionally look
in the colon-separated (on Windows, semicolon-
separated) list of directories specified by
the PKG_CONFIG_PATH environment variable.

The package name specified on the pkg-config
command line is defined to be the name of the
metadata file, minus the .pc extension. If a
library can install multiple versions simulta-
neously, it must give each version its own
name (for example, GTK 1.2 might have the
package name "gtk+" while GTK 2.0 has
"gtk+-2.0").


What's happening is that the matplotlib setup.py script uses pkg-config if it's present. The binary is in /usr/local/bin/pkg-config. It looks for a subdirectory of /usr/X11/lib (and /usr/local/lib) called pkgconfig that constains .pc files for packages that specify metadata about themselves to take advantage of pkgconfig functionality:


> cat /usr/X11/lib/pkgconfig/libpng.pc
prefix=/usr/X11
exec_prefix=${prefix}
libdir=${exec_prefix}/lib
includedir=${prefix}/include/libpng12

Name: libpng
Description: Loads and saves PNG files
Version: 1.2.44
Libs: -L${libdir} -lpng12
Libs.private: -lz
Cflags: -I${includedir}





We used Homebrew only to grab pkg-config. You could get it yourself: 0.26 is the newest, but requires glib-2.0; 0.25 bundles glib with pkg-config. 0.25 builds with no dependencies using the standard ./configure; make; make install. Download page for version 0.25 and 0.26 is here. Or of course, you can use Homebrew like we did.

Not clear why it doesn't ship with OS X. The license is GPLv2. But then, so is BASH.

Some minor issues:

• when I tried using pkg-config on my iMac (Snow Leopard, littered with MacPorts and other stuff), matplotlib seemed to build and install but died with:


> python x.py
Traceback (most recent call last):
File "x.py", line 1, in
import matplotlib.pyplot as plt
File "/Library/Python/2.6/site-packages/matplotlib/pyplot.py", line 95, in
new_figure_manager, draw_if_interactive, _show = pylab_setup()
File "/Library/Python/2.6/site-packages/matplotlib/backends/__init__.py", line 25, in pylab_setup
globals(),locals(),[backend_name])
File "/Library/Python/2.6/site-packages/matplotlib/backends/backend_macosx.py", line 243, in
class TimerMac(_macosx.Timer, TimerBase):
AttributeError: 'module' object has no attribute 'Timer'


For reasons that I don't understand, the version of the file in the build directory


/Users/telliott/Software/matplotlib-1.0.1/build/lib.macosx-10.6-universal-2.6/matplotlib/backends/backend_macosx.py


is not the same as the one in site-packages


/Library/Python/2.6/site-packages/matplotlib/backends/backend_macosx.py


Simply replacing the site-packages version fixed the problem:


> sudo cp /Users/telliott/Software/matplotlib-1.0.1/build/lib.macosx-10.6-universal-2.6/matplotlib/backends/backend_macosx.py /Library/Python/2.6/site-packages/matplotlib/backends/backend_macosx.py
> python -c "import matplotlib.pyplot as plt"
>


• the Homebrew "Formula" in /usr/local/Library/Formula/pkg-config.rb tells the installed pkg-config which paths to search for lib.pc files:


        /usr/local/lib/pkgconfig
/usr/lib/pkgconfig
/usr/X11/lib/pkgconfig


I'm not quite sure how that would work for a manual install.

• the libpng in /usr/local/lib that I installed shadowed the one in /usr/X11/lib so to use the X11 version, I removed the files from /usr/local

• The notation libpng.pcfileLibs.private: -lz indicates that libpng does depend on zlib, but it's already been linked against it (hence private). I'm not sure where it is, though.