pkg-config specification

Author: Michał Górny <mgorny@gentoo.org>
Copyright: http://creativecommons.org/licenses/by/3.0/

Table of contents

Introduction

pkg-config is a helper tool for obtaining correct compiler & linker flags suitable to satisfying application dependencies. It was designed to be platform- and language-agnostic, and to support installing dependencies in any locations without the need for explicitly specifying those locations every time an application is built.

Sadly, the official pkg-config implementation had a few deficiencies. Most importantly, the upstream decided to use the glib and popt libraries. The latter being redundant and having portability problems, the former being quite large and causing circular dependencies (since glib's build required pkg-config itself), they limited the popularity and usefulness of pkg-config [1].

The fore-mentioned deficiencies of the official implementation has caused a number of alternative implementations to arose. Amongst them there were the OpenBSD implementation in Perl, and pkgconf in ANSI C. The work on those implementations and the experience in using them has shown that pkg-config lacks proper documentation. The only official documentation on it are the man page and a short tutorial-style Guide.

Thus, I have decided to write a complete and detailed specification of how pkg-config works based on the actual source code. The goal is to provide a complete, well-organized guide which would prove useful both to end-users, and to people trying to create or improve their own pkg-config implementation.

[1]The redundant popt dependency has been finally removed lately, and the necessary glib parts started to be bundled along with pkg-config in order to simplify bootstrap.

The package file format

The packages in pkg-config are specified inside files called package files. These files have an obligatory .pc suffix, and are line-oriented text files.

Data encoding

The consecutive lines are delimited using any of the following characters:

line-delim = LF / CR / CR LF / LF CR

Each line has the following form:

line = line-data *( escaped-delim line-data ) [ "#" comment ]
escaped-delim = "\" ( line-delim / "#" )

The following should be noted:

  1. The # character indicates start of a comment, except when preceded by a backslash (\). When preceded by a backslash, it is interpreted as a literal #.
  2. When not in a comment, the line delimiter can be escaped through preceding with a backslash (\). In that case, the consecutive lines are concatenated.
  3. The comments always end at the end-of-a-line.
  4. Any other occurrence of a backslash (\) is interpreted as a literal backslash.

The interpreted line data is created through concatenating the consecutive line data and escaped delimiters up to the first non-escaped #, line delimiter or end-of-file. Comments are discarded.

Data format

Each interpreted data line follows the following format:

data-line  = empty-line / keyword / variable

empty-line = *WSP
keyword    = *WSP tag *WSP ":" *WSP value *WSP
variable   = *WSP tag *WSP "=" *WSP value *WSP

tag        = 1*( ALPHA / DIGIT / "_" / "." )
value      = *( value-data / esc-var / var-ref )
esc-var    = "$$"
var-ref    = "${" tag "}"

The variable syntax defines a variable with a name defined by tag. The variable definition becomes effective (i.e. can be referenced) starting with the following line. If a variable is declared multiple times, the next declaration replaces the previous value [2] and a warning is printed.

The keyword syntax defines a keyword with a name defined by tag. The list of allowed names and their meaning is described in Keywords. If a keyword uses a name unknown to the particular pkg-config version, it is silently ignored. If a keyword is declared multiple times, the next declaration replaces the previous value and a warning is printed.

For both variable and keyword definition values, variable substitution is performed. All occurrences of var-ref are substituted with the current, effective value of a variable named by tag. In order to prevent the variable substitution, the $ character can be escaped by repeating it twice; all occurrences of $$ (esc-var) will be substituted with a single $.

Please note that aside to the package-defined variables, additional (global) variables can be either defined by user (using --define-variable, see: Other program options) or by pkg-config itself (see: Special variables).

[2]Note that the new value is effective starting with the next line, thus the old value will still be used for previous lines and the variable declaration itself.

Special variables

A few variables in pkg-config files have special meaning. Some of them are declared either by pkg-config or the user (using environment variables).

pc_sysrootdir

Set through the PKG_CONFIG_SYSROOT_DIR environment variable; if unset, defaults to /.

The path specified by this variable is automatically prepended to the include and library paths in -I (Cflags) and -L (Libs) flags.

pc_top_builddir

Set through the PKG_CONFIG_TOP_BUILD_DIR environment variable; if unset, defaults to literal $(top_builddir) (for Makefile).

The value of this variable may be used by package files to refer to the top build directory of the current project.

Keywords

The following list describes all the keywords interpreted by pkg-config as of version 0.27:

Name
Free-form package name. Please note that the name specified here is intended for display only; the package is always identified in pkg-config by the package key. Obligatory.
Description
Free-form package description. Obligatory.
Version

Package version. Obligatory.

There are no direct requirements on version string format; however, their use in a package list disallow use of whitespace, <, >, = and ! characters. Additionally, it is important to consider version comparison rules.

URL

Package homepage URL.

The URL listed here is used to recommend a download location for new versions of package whenever a newer version than installed is requested.

Cflags or CFlags

Required compiler flags. These flags are always used.

The syntax for Cflags value is detailed in Cflags.

Libs

Dependant libraries, and required compiler linking flags. These flags are always used when a package is requested directly; they are also used when the package is a requisite for another package and the library format does not express inter-library dependencies.

The syntax for Libs value is detailed in Libs.

Libs.private
Private dependant libraries. The flags listed there will be appended to the value of Libs if the library format does not express inter-library dependencies.
Requires

Public package dependencies. All packages mentioned there will be required for the package check to succeed, and the effective Cflags for each of them will be appended to the effective Cflags of the current package. Additionally, if the library format does not express inter-library dependencies, the same applies to Libs.

The syntax for Requires value is detailed in the package list description.

Requires.private
Private package dependencies. The packages mentioned there will be appended to the effective Requires list if the library format does not support inter-library dependencies.
Conflicts

The list of conflicting packages. If any of the packages mentioned there is used by the application, the current package can not be used.

The syntax for Conflicts value is detailed in the package list description.

If any of the keywords marked as obligatory is not specified by the particular package, it is considered ill-formed and pkg-config exits with an error if it is requested (either directly or indirectly).

Keyword value interpretation

Package key

Every package is identified in pkg-config by a unique package key. The key is created from the package filename, after stripping the .pc suffix, and then an optional -uninstalled suffix.

Cflags

The Cflags keyword contains compiler flags, in a form suitable for passing to a POSIX shell (excluding the shell expansions). When parsing the variable, pkg-config uses shell quoting rules to split it into consecutive command-line arguments.

The flags encountered in Cflags are grouped into the two following groups:

  1. the -I (include path) flags,
  2. other flags.

Additionally, pkg-config applies flag mangling rules to the flags.

Libs

The Libs keyword contains compiler linking flags, in a form suitable for passing to a POSIX shell (excluding the shell expansions). When parsing the variable, pkg-config uses shell quoting rules to split it into consecutive command-line arguments.

The flags encountered in Libs are grouped into the three following groups:

  1. the -l (library name) flags [3],
  2. the -L (library path) flags,
  3. other flags.

Please note that if pc_sysrootdir variable is defined (see: Environment variables), its value will be prepended to the library paths (in -L flags).

Additionally, pkg-config applies flag mangling rules to the flags.

[3]pkg-config additionally ensures not to put C# -lib: to that group.

Flag mangling rules

The following mangling is applied to the Cflags and Libs:

  1. If pc_sysrootdir variable is set (see: Special variables), its value is prepended to the paths in the variables accepting paths.
  2. Unless PKG_CONFIG_ALLOW_SYSTEM_* environment variables are set, the variables pointing to the system include/library directories are removed.

Package list

The Requires and Conflicts keywords, and also command-line arguments to pkg-config form package lists. A package list is formed using the following syntax:

package-list = *WSP *( package-spec *( package-sep ) )
package-sep  = WSP / ","

package-spec = package-key [ ver-op package-version ]
ver-op       = "<" / "<=" / "=" / "!=" / ">=" / ">"

If ver-op and package-version are specified, only packages satisfying the specified version requirement will match. Otherwise, any package with matching package-key will match.

The rules for version matching are detailed in Version comparison.

Version comparison

pkg-config version comparison rules follow those established for the RPM package manager.

As seen by the comparison algorithm, the versions could be described using the following syntax:

version-string = 1*( alpha-seg / numeric-seg / version-sep )
alpha-seg      = 1*( ALPHA )
numeric-seg    = 1*( DIGIT )

For the comparison, the version number is split into alphabetic (alpha-seg) and/or numeric segments (numeric-seg), either alternating or separated by non-alphanumeric characters.

Afterwards, for each corresponding segment of the two version numbers, the following algorithm is repeated until either one of the segments is indicated newer or the end of either version string is reached:

  1. If both compared segments are numeric, the segment with larger integer value is considered newer [4].
  2. If both compared segments are alphabetic, a semi-lexical (ASCII code) comparison is applied (using strcmp()).
  3. If the compared segments are of different type (one numeric and the other alphabetic), the version with numeric segment is considered newer.

If all version components from both strings are used without finding a segment indicating that one of the versions is newer, the versions are considered equal. If all version components from one of the strings are used while the other has more components, the latter is considered newer.

[4]Note that the version numbers can be arbitrarily long. For that reason, the comparison used in pkg-config uses semi-lexical comparison of normalized numeric strings.

Version comparison example

The following table lists a number of version strings, sorted using the version comparison rules. Next to the strings, the interpreted components are shown and the components directly responsible for the particular version being newer are emphasized.

? Version string Version components
. 0 0
< 0.0 0 0
< 0.37 0 37
< 0.37.1 0 37 1
= 0.37-1 0 37 1
< 0.37-1b 0 37 1 b
= 0.37.1.b 0 37 1 b
< 0.37.1.0 0 37 1 0
= 0.037.001.000 0 37 1 0
< 0.37.4a 0 37 4 a
< 0.37.4b 0 37 4 b
< 0.37.4b-pkgconf1 0 37 4 b pkgconf 1
< 0.37.4c 0 37 4 c
= !!0@@37##4$$c 0 37 4 c

Package file lookup

Whenever a package is requested by a package list, the following algorithm is used to find the requested package:

  1. If the package-key ends with a .pc suffix, it is interpreted as an absolute path to the package file and that file is used. If the file is not readable or does not exist, the package is considered not found.
  2. If the package-key does not end with an -uninstalled suffix and uninstalled package versions are preferred (the default), the mentioned suffix is temporarily appended to the package key and a package search is performed with that name. If it succeeds, the package found is returned.
  3. A package search is performed using the given package key. If it succeeds, the package found is returned.
  4. If the package-key is pkg-config, a virtual package for pkg-config is returned. The package specifies at least a Version keyword matching a pkg-config version [5], and a pc_path variable expressing the default package search paths.
[5]

Please note that a particular consumer may require a specific pkg-config version. For that reason, it is recommended to use version numbers matching upstream versions; an implementation following this specification should use the version 0.27.

If the implementor wishes to append a program-specific version, it is recommended to use an alphabetic version separator, e.g. 0.27/pkgconf-0.8.7. This ensures that the particular version is always considered older than the next upstream version (see: Version comparison).

Command-line interface

pkg-config provides a public command line interface through the pkg-config executable. The executable accepts GNU-style long options and an arbitrary number of positional parameters. Those parameters are concatenated, forming a requested package list.

The list specified here is closely based on the actual pkg-config and pkgconf behavior, and its use in various packages.

Exclusive commands

The options listed in this section fully influence the operation mode of pkg-config. If any of them is specified, pkg-config performs the appropriate operation and exits. If more than one is specified, the behavior is implementation-defined.

--version
Outputs the pkg-config version and exits with 0 status.
--atleast-pkgconfig-version=VERSION

Checks whether pkg-config version is at least VERSION. Exits with 0 status if it is, or 1 if it is older.

The version is compared using package version comparison rules.

--list-all

Prints a list containing all packages found in package search paths.

For each found package (with an unique package key), the following is printed:

package-key *WSP name SP "-" SP description

The name and description fields correspond to the appropriate package keywords. No line wrapping is performed. If multiple packages with the same key are found, the one occurring in the earlier package search directory is used.

Afterwards, pkg-config exits with 0 status.

--exists
Checks silently whether all specified packages (with matching versions) are available. Exits with 0 status if they are, with 1 otherwise.
--uninstalled
Check whether the package list contains at least one uninstalled package (having -uninstalled suffix in the matching filename), and exit with 0 status if it does. Exits with 1 status otherwise.

Line-mode output commands

The commands listed in this section enable the output of a particular information regarding the specified packages. If multiple commands are specified, the behavior is implementation-defined.

These functions output the information in line mode. Consecutive values are printed one per line, and the output is always finished with a newline. If multiple packages are requested, the output format is implementation-defined.

The program exits with 0 status if all packages were found, with 1 otherwise.

--print-variables
Prints a list of all variables declared in the specified package. The list contains variable names, one per line.
--modversion
Prints the installed version for each of the specified packages.
--print-provides

For each of the specified packages, prints the following string:

package-key SP "=" SP package-version
--print-requires
For each of the specified packages, print all the packages in Requires, one package-spec per line.
--print-requires-private
For each of the specified packages, print all the packages in Requires.private, one package-spec per line.

Inline output commands

The commands listed in this section enable the output of a particular information regarding the specified packages. If multiple commands are specified, the behavior is implementation-defined. However, it is guaranteed that --cflags --libs will output both.

These functions output the information inline. Consecutive values are separated by a single space; a single newline is added after the complete output.

The program exits with 0 status if all packages were found, with 1 otherwise.

--variable=VARIABLE
For each of the specified packages, print the value of variable VARIABLE. If the variable is not declared, nothing is output.
--cflags-only-I
Output the effective list of Cflags from the -I group for all the requested packages.
--cflags-only-other
Output the effective list of Cflags from the other flags group for all the requested packages.
--cflags
Output the effective list of Cflags for all the requested packages.
--libs-only-l
Output the effective list of Libs from the -l group for all the requested packages.
--libs-only-L
Output the effective list of Libs from the -L group for all the requested packages.
--libs-only-other
Output the effective list of Libs from the other flags group for all the requested packages.
--libs
Output the effective list of Libs for all the requested packages.

Other program options

The options in this group affect the behavior of most of the commands.

--static
Assume that static linking will be used, and thus properties of static libraries should be considered.
--short-errors
Use shorter error messages.
--define-variable=NAME=VALUE
Set the variable named NAME to a constant value of VALUE. Further assignments to the variable within the package files will be ignored, and thus this option can be used to override values of in-package variables.
--atleast-version=VERSION
Assume that the directly requested packages have to be at least of version VERSION. This overrides all version specifiers in the command-line arguments, and replaces them with >= VERSION.
--exact-version=VERSION

Assume that the directly requested packages have to be at exact version VERSION. This overrides all version specifiers in the command-line arguments, and replaces them with = VERSION.

If the --atleast-version option is specified as well, it takes precedence over this one.

--max-version=VERSION

Assume that the directly requested packages have to be at most of version VERSION. This overrides all version specifiers in the command-line arguments, and replaces them with <= VERSION.

If the --exact-version option is specified as well, it takes precedence over this one.

--print-errors

Print missing requirement and package conflict errors.

This option is enabled by default if any of the commands resulting in output is used. It can be disabled using --silence-errors, and in that case --silence-errors takes precedence over explicit --print-errors.

--silence-errors

Silence missing requirement and package conflict errors.

This option is enabled by efault if none of the commands resulting in output is used. It can be disabled using --print-errors, and in that case --print-errors takes precedence over explicit --silence-errors.

--errors-to-stdout
Output the errors (from --print-errors) on the stdout instead of stderr.

Environment variables

Aside to the program options, a few environment variables influence the behavior of pkg-config as well.

PKG_CONFIG_PATH

A list of directories prepended to the package search path (either the default one or defined by PKG_CONFIG_LIBDIR).

The directories use platform convention for path lists; they are colon-separated on POSIX and semicolon-separated on win32.

PKG_CONFIG_LIBDIR

A list of directories replacing the default package search path. PKG_CONFIG_PATH will still be honored.

The directories use platform convention for path lists; they are colon-separated on POSIX and semicolon-separated on win32.

PKG_CONFIG_DISABLE_UNINSTALLED
If this environment variable is set, then uninstalled packages are no longer preferred when performing the package file lookup.
PKG_CONFIG_ALLOW_SYSTEM_CFLAGS
Disable stripping of standard include directories from Cflags.
PKG_CONFIG_ALLOW_SYSTEM_LIBS
Disable stripping of standard library directories from Libs.
PKG_CONFIG_SYSROOT_DIR

The value for global pc_sysrootdir variable. If unset, defaults to /.

If set, the value of this variable will be automatically prepended to all -L and -I flags. It can be used when building in an alternate root.

PKG_CONFIG_TOP_BUILD_DIR

The value for global pc_top_builddir variable. If unset, defaults to $(top_builddir).

This variable can be used within pkg-config files to refer to the top build directory. It is not used internally.

Platform-specific notes

POSIX

  1. The search path separator (for PKG_CONFIG_PATH and PKG_CONFIG_LIBDIR) is a colon (:).
  2. The package key comparison is case-sensitive.
  3. The default package search path is set at build-time, and defaults to the installation prefix subdirectories.

Win32

  1. The search path separator (for PKG_CONFIG_PATH and PKG_CONFIG_LIBDIR) is a semicolon (;).
  2. The package key comparison is case-insensitive (following the filename comparison rules for the platform).
  3. The default package search path is determined at runtime using the actual program installation directory.

Autoconf macros

pkg-config installs the following autoconf macros:

PKG_PROG_PKG_CONFIG([MIN-VERSION])

Checks for the pkg-config executable. If MIN-VERSION is specified, the specified pkg-config version is required.

If the PKG_CONFIG variable is set, the check uses its value as requested pkg-config invocation; otherwise, it uses pkg-config.

If the check succeeds, the PKG_CONFIG variable is set to a valid invocation and exported for substitution. If the invocation fails or pkg-config is too old, the variable is set to a null value.

The calls to the two remaining macros expand PKG_PROG_PKG_CONFIG implicitly. However, please note that due to m4 expansion rules, you should either ensure that the first call to either of the two macros is unconditional, or call PKG_PROG_PKG_CONFIG unconditionally first.

Aside from PKG_CONFIG, this macro should also define PKG_CONFIG_LIBDIR and PKG_CONFIG_PATH configure variables with the same meaning as the respective environment variables.

PKG_CHECK_EXISTS(MODULES, [IF-FOUND], [IF-NOT-FOUND])

Check if the specified MODULES are available. If the check succeeds, execute IF-FOUND. Otherwise, execute IF-NOT-FOUND (both default to no-op).

This macro does not query any specific properties nor print errors.

PKG_CHECK_MODULES(PREFIX, MODULES, [IF-FOUND], [IF-NOT-FOUND])

Query pkg-config for the specified MODULES.

If ${PREFIX}_CFLAGS or ${PREFIX}_LIBS are set, the respective flags are not queried. If both are set, no pkg-config invocation occurs (thus making it possible to build the package without pkg-config installed).

If all the requested packages are found (or both variables were set), fills in ${PREFIX}_CFLAGS and ${PREFIX}_LIBS, then executes IF-FOUND (defaults to no-op).

Otherwise, it either executes IF-NOT-FOUND or (if the former is not set) terminates with a verbose error message. The same behavior applies when pkg-config is not available.

This macro should define ${PREFIX}_CFLAGS and ${PREFIX}_LIBS configure variables, allowing the user to override Cflags and Libs respectively.

PKG_INSTALLDIR([DIRECTORY])

Add a --with-pkgconfigdir command-line option as a location for arch-dependent package files, and export pkgconfigdir for substitution. The variable defaults either to DIRECTORY if set or to ${libdir}/pkgconfig.

The directory can be used in automake files like the following:

pkgconfig_DATA = mylib.pc
PKG_NOARCH_INSTALLDIR([DIRECTORY])

Add a --with-noarch-pkgconfigdir command-line option as a location for arch-independent package files, and export noarch_pkgconfigdir for substitution. The variable defaults either to DIRECTORY if set or to ${datarootdir}/pkgconfig.

The directory can be used in automake files like the following:

noarch_pkgconfig_DATA = mydata.pc

Missing information

This specification is still incomplete, and there are a few features which probably should be described in the future.

  1. Redundant (repeating) Cflags and Libs removal. The implementation of that feature is known to be buggy (bug #16101 and duplicates), and it is not strictly required by applications using pkg-config.
  2. Win32-specific ${prefix} mangling.
  3. Win32-specific command-line options.
  4. Package search path retrieval from Win32 registry. The feature is documented, however I don't see any implementation code for it.