diff --git a/Makefile.am b/Makefile.am index 95998a6..b9edccc 100644 --- a/Makefile.am +++ b/Makefile.am @@ -11,6 +11,8 @@ SUBDIRS = $(GLIB_SUBDIR) check m4dir = $(datadir)/aclocal m4_DATA = pkg.m4 +dist_doc_DATA = pkg-config-guide.html + man_MANS = pkg-config.1 EXTRA_DIST = $(m4_DATA) $(man_MANS) README.win32 diff --git a/pkg-config-guide.html b/pkg-config-guide.html new file mode 100644 index 0000000..0f6c72f --- /dev/null +++ b/pkg-config-guide.html @@ -0,0 +1,420 @@ + + + + + + + + + + Guide to pkg-config + + + +

Guide to pkg-config

+ +

Dan Nicholson

+ + + +

Overview

+ +

This document aims to give an overview to using the pkg-config + tool from the perspective of both a user and a developer. It reviews the + concepts behind pkg-config, how to write pkg-config files + to support your project, and how to use pkg-config to integrate + with 3rd party projects.

+ +

More information on pkg-config can be found at the + website and in the + pkg-config(1) manual page.

+ +

This document assumes usage of pkg-config on a Unix-like + operating system such as Linux. Some of the details may be different on + other platforms.

+ +

Why?

+ +

Modern computer systems use many layered components to provide + applications to the user. One of the difficulties in assembling these parts + is properly integrating them. pkg-config collects metadata about + the installed libraries on the system and easily provides it to the user. +

+ +

Without a metadata system such as pkg-config, it can be very + difficult to locate and obtain details about the services provided on a + given computer. For a developer, installing pkg-config files with + your package greatly eases adoption of your API.

+ +

Concepts

+ +

The primary use of pkg-config is to provide the necessary + details for compiling and linking a program to a library. This metadata is + stored in pkg-config files. These files have the suffix + .pc and reside in specific locations known to the + pkg-config tool. This will be described in more detail later.

+ +

The file format contains predefined metadata keywords and freeform + variables. An example may be illustrative:

+ +

prefix=/usr/local
+exec_prefix=${prefix}
+includedir=${prefix}/include
+libdir=${exec_prefix}/lib
+
+Name: foo
+Description: The foo library
+Version: 1.0.0
+Cflags: -I${includedir}/foo
+Libs: -L${libdir} -lfoo
+ +

The keyword definitions such as Name: begin with a keyword + followed by a colon and the value. The variables such as prefix= + are a string and value separated by an equals sign. The keywords are defined + and exported by pkg-config. The variables are not necessary, but + can be used by the keyword definitions for flexibility or to store data not + covered by pkg-config.

+ +

Here is a short description of the keyword fields. A more in depth + description of these fields and how to use them effectively will be given in + the Writing pkg-config files section.

+ + + +

Writing pkg-config files

+ +

When creating pkg-config files for a package, it is first + necessary to decide how they will be distributed. Each file is best used to + describe a single library, so each package should have at least as many + pkg-config files as they do installed libraries.

+ +

The package name is determined through the filename of the + pkg-config metadata file. This is the portion of the filename prior + to the .pc suffix. A common choice is to match the library name to + the .pc name. For instance, a package installing libfoo.so + would have a corresponding libfoo.pc file containing the + pkg-config metadata. This choice is not necessary; the .pc + file should simply be a unique identifier for your library. Following the + above example, foo.pc or foolib.pc would probably work + just as well.

+ +

The Name, Description and URL fields are + purely informational and should be easy to fill in. The Version + field is a bit trickier to ensure that it is usable by consumers of the + data. pkg-config uses the algorithm from + RPM for version comparisons. This works best + with a dotted decimal number such as 1.2.3 since letters can cause + unexpected results. The number should be monotonically increasing and be + as specific as possible in describing the library. Usually it's sufficient + to use the package's version number here since it's easy for consumers to + track.

+ +

Before describing the more useful fields, it will be helpful to + demonstrate variable definitions. The most common usage is to define the + installation paths so that they don't clutter the metadata fields. Since + the variables are expanded recursively, this is very helpful when used in + conjunction with autoconf derived paths.

+ +
prefix=/usr/local
+includedir=${prefix}/include
+
+Cflags: -I${includedir}/foo
+ +

The most important pkg-config metadata fields are + Requires, Requires.private, Cflags, Libs + and Libs.private. They will define the metadata used by external + projects to compile and link with the library.

+ +

Requires and Requires.private define other modules + needed by the library. It is usually preferred to use the private variant of + Requires to avoid exposing unnecessary libraries to the program + that is linking with your library. If the program will not be using the + symbols of the required library, it should not be linking directly to that + library. See the discussion of + overlinking for a more + thorough explanation.

+ +

Since pkg-config always exposes the link flags of the + Requires libraries, these modules will become direct dependencies + of the program. On the other hand, libraries from Requires.private + will only be included when static linking. For this reason, it is usually + only appropriate to add modules from the same package in Requires. +

+ +

The Libs field contains the link flags necessary to use that + library. In addition, Libs and Libs.private contain link + flags for other libraries not supported by pkg-config. Similar to + the Requires field, it is preferred to add link flags for external + libraries to the Libs.private field so programs do not acquire an + additional direct dependency.

+ +

Finally, the Cflags contains the compiler flags for using the + library. Unlike the Libs field, there is not a private variant of + Cflags. This is because the data types and macro definitions are + needed regardless of the linking scenario.

+ +

Using pkg-config files

+ +

Assuming that there are .pc files installed on the system, the + pkg-config tool is used to extract the metadata for usage. A short + description of the options can be seen by executing + pkg-config --help. A more in depth discussion can be found in the + pkg-config(1) manual page. This section will provide a brief + explanation of common usages. + +

Consider a system with two modules, foo and bar. + Their .pc files might look like this:

+ +
foo.pc:
+prefix=/usr
+exec_prefix=${prefix}
+includedir=${prefix}/include
+libdir=${exec_prefix}/lib
+
+Name: foo
+Description: The foo library
+Version: 1.0.0
+Cflags: -I${includedir}/foo
+Libs: -L${libdir} -lfoo
+
+bar.pc:
+prefix=/usr
+exec_prefix=${prefix}
+includedir=${prefix}/include
+libdir=${exec_prefix}/lib
+
+Name: bar
+Description: The bar library
+Version: 2.1.2
+Requires.private: foo >= 0.7
+Cflags: -I${includedir}
+Libs: -L${libdir} -lbar
+ +

The version of the modules can be obtained with the --modversion + option.

+ +
$ pkg-config --modversion foo
+1.0.0
+$ pkg-config --modversion bar
+2.1.2
+ +

To print the link flags needed for each module, use the --libs + option.

+ +
$ pkg-config --libs foo
+-lfoo
+$ pkg-config --libs bar
+-lbar
+ +

Notice that pkg-config has suppressed part of the Libs + field for both modules. This is because it treats the -L flag + specially and knows that the ${libdir} directory /usr/lib + is part of the system linker search path. This keeps pkg-config + from interfering with the linker operation.

+ +

Also, although foo is required by bar, the link flags + for foo are not output. This is because foo is not + directly needed by an application that only wants to use the bar + library. For statically linking a bar application, we need both + sets of linker flags:

+ +
$ pkg-config --libs --static bar
+-lbar -lfoo
+ +

pkg-config needs to output both sets of link flags in this case + to ensure that the statically linked application will find all the necessary + symbols. On the other hand, it will always output all the Cflags. +

+ +
$ pkg-config --cflags bar
+-I/usr/include/foo
+$ pkg-config --cflags --static bar
+-I/usr/include/foo
+ +

Another useful option, --exists, can be used to test for a + module's availability.

+ +
$ pkg-config --exists foo
+$ echo $?
+0
+ +

One of the nicest features of pkg-config is providing version + checking. It can be used to determine if a sufficient version is available. +

+ +
$ pkg-config --libs "bar >= 2.7"
+Requested 'bar >= 2.7' but version of bar is 2.1.2
+ +

Some commands will provide more verbose output when combined with the + --print-errors option.

+ +
$ pkg-config --exists --print-errors xoxo
+Package xoxo was not found in the pkg-config search path.
+Perhaps you should add the directory containing `xoxo.pc'
+to the PKG_CONFIG_PATH environment variable
+No package 'xoxo' found
+ +

The message above references the PKG_CONFIG_PATH environment + variable. This variable is used to augment pkg-config's search + path. On a typical Unix system, it will search in the directories + /usr/lib/pkgconfig and /usr/share/pkgconfig. This will + usually cover system installed modules. However, some local modules may be + installed in a different prefix such as /usr/local. In that case, + it's necessary to prepend the search path so that pkg-config can + locate the .pc files.

+ +
$ pkg-config --modversion hello
+Package hello was not found in the pkg-config search path.
+Perhaps you should add the directory containing `hello.pc'
+to the PKG_CONFIG_PATH environment variable
+No package 'hello' found
+$ export PKG_CONFIG_PATH=/usr/local/lib/pkgconfig
+$ pkg-config --modversion hello
+1.0.0
+ +

A few autoconf macros + are also provided to ease integration of pkg-config modules into + projects.

+ + + + +

Frequently asked questions

+ +
    +
  1. My program uses library x. What do I do?
  2. + +

    The pkg-config output can easily be used on the compiler + command line. Assuming the x library has a x.pc + pkg-config file:

    + +
    cc `pkg-config --cflags --libs x` -o myapp myapp.c
    + +

    The integration can be more robust when used with + autoconf and + automake. By using the + supplied PKG_CHECK_MODULES macro, the metadata is easily accessed + in the build process.

    + +
    configure.ac:
    +PKG_CHECK_MODULES([X], [x])
    +
    +Makefile.am:
    +myapp_CFLAGS = $(X_CFLAGS)
    +myapp_LDADD = $(X_LIBS)
    + +

    If the x module is found, the macro will fill and substitute + the X_CFLAGS and X_LIBS variables. If the module is not + found, an error will be produced. Optional 3rd and 4th arguments can be + supplied to PKG_CHECK_MODULES to control actions when the module + is found or not.

    + +
  3. My library z installs header files which include libx + headers. What do I put in my z.pc file?
  4. + +

    If the x library has pkg-config support, add it to + the Requires.private field. If it does not, augment the + Cflags field with the necessary compiler flags for using the + libx headers. In either case, pkg-config will output + the compiler flags when --static is used or not.

    + +
  5. My library z uses libx internally, but does not + expose libx data types in its public API. What do I put in my + z.pc file?
  6. + +

    Again, add the module to Requires.private if it supports + pkg-config. In this case, the compiler flags will be emitted + unnecessarily, but it ensures that the linker flags will be present when + linking statically. If libx does not support pkg-config, + add the necessary linker flags to Libs.private.

    +
+ +
+ +
Dan Nicholson <dbn.lists (at) gmail (dot) com>
+ +

Copyright (C) 2010 Dan Nicholson.
+ This document is licensed under the + GNU General Public License, Version 2 + or any later version.

+ + +