PkgConfigDeps

Warning

These tools are still experimental (so subject to breaking changes) but with very stable syntax. We encourage the usage of it to be prepared for Conan 2.0.

PkgConfigDeps

Available since: 1.38.0

The PkgConfigDeps is the dependencies generator for pkg-config. Generates pkg-config files named <PKG-NAME>.pc (where <PKG-NAME is the name declared by dependencies in cpp_info.names["pkg_config"] if specified), containing a valid pkg-config file syntax. Indeed, it can also be defined using set_property and the property pkg_config_name (available since Conan 1.36), for instance:

self.cpp_info.components["mycomponent"].set_property("pkg_config_name", "mypkg-config-name")

Note

In Conan 2.0 that will be the default way of setting those properties and also passing custom properties to generators. Check the cpp_info attributes reference for more information.

The prefix variable is automatically adjusted to the package_folder.

The PkgConfigDeps generator can be used by name in conanfiles:

conanfile.py
class Pkg(ConanFile):
    generators = "PkgConfigDeps"
conanfile.txt
[generators]
PkgConfigDeps

And it can also be fully instantiated in the conanfile generate() method:

from conans import ConanFile
from conan.tools.gnu import PkgConfigDeps

class App(ConanFile):
    settings = "os", "arch", "compiler", "build_type"
    requires = "zlib/1.2.11"

    def generate(self):
        pc = PkgConfigDeps(self)
        pc.generate()

The PkgConfigDeps will generate the *.pc file after a conan install command:

$ conan install .
# Check the [PC_FILE_NAME].pc created in your current folder

Now, running this command using the previous conanfile.py, you can check the zlib.pc file created into your current folder:

prefix=/Users/YOUR_USER/.conan/data/zlib/1.2.11/_/_/package/647afeb69d3b0a2d3d316e80b24d38c714cc6900
libdir=${prefix}/lib
includedir=${prefix}/include

Name: zlib
Description: Conan package: zlib
Version: 1.2.11
Libs: -L"${libdir}" -lz -F Frameworks
Cflags: -I"${includedir}"

Components

If a recipe uses components, the files generated will be <[PKG-NAME]-[COMP-NAME]>.pc with their corresponding flags and require relations.

Additionally, a <PKG-NAME>.pc is generated to maintain compatibility for consumers with recipes that start supporting components. This <PKG-NAME>.pc file will declare all the components of the package as requires while the rest of the fields will be empty, relying on the propagation of flags coming from the components <[PKG-NAME]-[COMP-NAME]>.pc files.

Properties

The following properties affect the PkgConfigDeps generator:

  • pkg_config_name property will define the name of the generated *.pc file (xxxxx.pc)

  • pkg_config_aliases property sets some aliases of any package/component name for pkg_config generator. This property only accepts list-like Python objects.

  • pkg_config_custom_content property will add user defined content to the .pc files created by this generator.

  • component_version property sets a custom version to be used in the Version field belonging to the created *.pc file for that component.

These properties can be defined at global cpp_info level or at component level.

Example:

def package_info(self):
    custom_content = "datadir=${prefix}/share"
    self.cpp_info.set_property("pkg_config_custom_content", custom_content)
    self.cpp_info.set_property("pkg_config_name", "myname")
    self.cpp_info.components["mycomponent"].set_property("pkg_config_name", "componentname")
    self.cpp_info.components["mycomponent"].set_property("pkg_config_aliases", ["alias1", "alias2"])
    self.cpp_info.components["mycomponent"].set_property("component_version", "1.14.12")

Names and aliases

Aliases are available since: 1.43.0

By default, the *.pc files will be named following these rules:

  • For packages, it uses the package name, e.g., package zlib/1.2.11 -> zlib.pc.

  • For components, the package name + hyphen + component name, e.g., openssl/3.0.0 with self.cpp_info.components["crytpo"] -> openssl-crypto.pc.

You can change that default behavior with the pkg_config_name and pkg_config_aliases properties. For instance, openssl/3.0.0` recipe has these pkg_config_name properties already declared:

from conans import ConanFile

class OpenSSLConan(ConanFile):
    name = "openssl"

    # any code here

    def package_info(self):
        self.cpp_info.set_property("pkg_config_name", "openssl")
        self.cpp_info.components["crypto"].set_property("pkg_config_name", "libcrypto")
        self.cpp_info.components["ssl"].set_property("pkg_config_name", "libssl")

Run conan install openssl/3.0.0@ -g PkgConfigDeps and check the *.pc files created:

  • libcrypto.pc

  • libssl.pc

  • openssl.pc

  • zlib.pc (openssl requires zlib)

Their pkg_config_name properties are used as the final *.pc file names:

openssl.pc
Name: openssl
Description: Conan package: openssl
Version: 3.0.0
Requires: libcrypto libssl
libcrypto.pc
prefix=/Users/conan_user/.conan/data/openssl/3.0.0/_/_/package/88955cec2844f731470e07bd44ce5a3a24ec88b7
libdir1=${prefix}/lib
includedir1=${prefix}/include

Name: libcrypto
Description: Conan component: libcrypto
Version: 3.0.0
Libs: -L"${libdir1}" -lcrypto -F Frameworks
Cflags: -I"${includedir1}"
Requires: zlib

A special mention when a component shares the same *.pc file name as the root package one:

from conans import ConanFile

class OpenCLConan(ConanFile):

    # ...

    def package_info(self):
        self.cpp_info.set_property("pkg_config_name", "OpenCL")  # -> OpenCL.pc
        self.cpp_info.components["_opencl-headers"].set_property("pkg_config_name", "OpenCL")  # -> OpenCL.pc

The only *.pc file created will be the one belonging to the component:

  • OpenCL.pc (from component)

Now, let’s see how pkg_config_aliases property works step by step.

Let’s create our own myopenssl/1.0.0 recipe and define several aliases like the following:

from conans import ConanFile

class MyOpenSSLConan(ConanFile):
    name = "myopenssl"
    version = "1.0.0"

    def package_info(self):
        # Aliases
        self.cpp_info.set_property("pkg_config_aliases", ["myopenssl_alias"])
        self.cpp_info.components["mycrypto"].set_property("pkg_config_aliases", ["mycrypto", "crp"])
        self.cpp_info.components["myssl"].set_property("pkg_config_aliases", ["myssl"])

Then, after creating the package locally with conan create . and consuming it conan install myopenssl/1.0.0@ -g PkgConfigDeps, the files created will be:

  • myopenssl-mycrypto.pc

  • myopenssl-myssl.pc

  • myopenssl.pc

  • crp.pc (alias of myopenssl-mycrypto)

  • mycrypto.pc (alias of myopenssl-mycrypto)

  • myssl.pc (alias of myopenssl-myssl)

  • myopenssl_alias.pc (alias of myopenssl)

Where any of those aliases files contains something like this:

mycrypto.pc
Name: mycrypto
Description: Alias mycrypto for myopenssl-mycrypto
Version: 1.0.0
Requires: myopenssl-mycrypto

It’s also possible to use both properties together:

from conans import ConanFile

class MyOpenSSLConan(ConanFile):
    name = "myopenssl"
    version = "1.0.0"

    # any code here

    def package_info(self):
        self.cpp_info.set_property("pkg_config_name", "myopenssl")
        self.cpp_info.components["mycrypto"].set_property("pkg_config_name", "libmycrypto")
        self.cpp_info.components["myssl"].set_property("pkg_config_name", "libmyssl")
        # Aliases
        self.cpp_info.set_property("pkg_config_aliases", ["myopenssl_alias"])
        self.cpp_info.components["mycrypto"].set_property("pkg_config_aliases", ["mycrypto", "crp"])
        self.cpp_info.components["myssl"].set_property("pkg_config_aliases", ["myssl"])

After executing the commands mentioned above, the files are:

  • libmycrypto.pc

  • libmyssl.pc

  • myopenssl.pc

  • crp.pc (alias of libmycrypto)

  • mycrypto.pc (alias of libmycrypto)

  • myssl.pc (alias of libmyssl)

  • myopenssl_alias.pc (alias of myopenssl)

The only change is which name the alias is pointing to:

mycrypto.pc
Name: mycrypto
Description: Alias mycrypto for libmycrypto
Version: 1.0.0
Requires: libmycrypto