Dan Nicholson

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.

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.

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:

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.

Name: A human-readable name for the library or package. This
does not affect usage of the pkg-config tool, which uses the name
of the .pc file.

Description: A brief description of the package.

URL: An URL where people can get more information about and
download the package.

Version: A string specifically defining the version of the
package.

Requires: A list of packages required by this package. The
versions of these packages may be specified using the comparison operators
=, <, >, <= or >=.

Requires.private: A list of private packages required by this
package but not exposed to applications. The version specific rules from
the Requires field also apply here.

Conflicts: An optional field describing packages that this one
conflicts with. The version specific rules from the Requires
field also apply here. This field also takes multiple instances of the
same package. E.g., Conflicts: bar < 1.2.3, bar >= 1.3.0.

Cflags: The compiler flags specific to this package and any
required libraries that don't support pkg-config. If the required
libraries support pkg-config, they should be added to
Requires or Requires.private.

Libs: The link flags specific to this package and any required
libraries that don't support pkg-config. The same rule as
Cflags applies here.

Libs.private: The link flags for private libraries required by
this package but not exposed to applications. The same rule as
Cflags applies here.

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.

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.

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:

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.

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.

PKG_PROG_PKG_CONFIG([MIN-VERSION]): Locates the
pkg-config tool on the system and checks the version for
compatibility.

PKG_CHECK_EXISTS(MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]):
Checks to see whether a particular set of modules exists.

PKG_CHECK_MODULES(VARIABLE-PREFIX, MODULES, [ACTION-IF-FOUND], [ACTION-IF-NOT-FOUND]):
Checks to see whether a particular set of modules exists. If so, it sets
<VARIABLE-PREFIX>_CFLAGS and
<VARIABLE-PREFIX>_LIBS according to the output from
pkg-config --cflags and pkg-config --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.

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

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.

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?

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.