Installing pkg config windows

Using pkg-config to discover PJSIP in cmake

In this note I will use pkg-config in cmake to discover PJSIP libraries. Cmake script can be used without changes for linux and windows, but for windows it is necessary to do some hand-work (hand work can be automated).

There is three sections in this note:

  • Installing pkg-config executable
  • Installing right libpjrpoject.pc
  • Discover PJSIP in cmake

Installing pkg-config executable

Pkg-config on Linux

pkg-config has native support in linux.

For ubuntu you can install it with

Pkg-config on Windows

There is also pkg-config binaries for Windows. You can download pkg-config with all dependencies from this answer on stackoverflow. Or you can simply download pkg-config-lite which is just single executable without any dependency.

Make sure that directory with pkg-config binaries is stored in PATH environment variable. You also need set PKG_CONFIG_PATH to directory which contains *.pc files with libraries metadata.

Install right libpjrpoject.pc

It is necessary to put libpjproject.pc to pkg-config search path. In Linux it can be done very simple due to autoconf tools. In Windows it can be done by do some hand-work.

Install PJSIP in Linux with apt-get

When you install PJSIP with

you get right libpjproject.pc file in pkg-config search path.

Install PJSIP in Linux from sources

You can also install PJSIP from sources with commands

In this case sudo make install will put libpjproject.pc to pkg-config search path.

Install PJSIP from sources on Windows

Windows is differ from linux in way you build software. Several CRT (C Runtime Library) versions must be supported: Static/Dynamic linkage, Debug/Release configurations, x86/x64 cpu target, Win8/WinXP toolset. pkg-config package file can contain only one such library.

So, it is convenient on Windows to represent library in terms of Visual Studio Macros, like:

  • libpjproject-$(Platform)-$(PlatformToolset)-$(Configuration)-Dynamic.lib for Dynamic CRT
  • libpjproject-$(Platform)-$(PlatformToolset)-$(Configuration)-Static.lib for Static CRT

The Visual Studio Macros used here is (I use Visual Studio 2013 Express): — $(Platform) — values Win32 or x64 depends on current build platform selected — $(PlatformTooslet) — platform toolset used in build: value v120 is default in Visual Studio 2013, v120_xp is for Windows XP compatible builds — $(Configuration) — usually Debug or Release values (cmake extends this list with RelWithDebInfo and MinSizeRel values)

You can use unofficial fork of PJSIP which prepared to generate binaries in that way when building in Visual Studio.

There is no prepared libpjproject.pc files exists for Windows, but you can write your own:

Note that you need specify directory to PJSIP sources instead @[email protected] .

So, if you put this lipjproject.pc to pkg-config search path, pkg-config will be able to discover PJSIP binaries in Windows.

Discover PJSIP in cmake

When you have pkg-config tool and you have libpjproject.pc in pkg-config search path, you can discover PJSIP with command:

Default way to discover libraries in cmake is to consume Find*.cmake module and find_package() function. In this example I just highlight some details. Full implementation you can find in FindPJSIP.cmake.

To find pkg-config executable in cmake

If pkg-config executable found, FindPkgConfig.cmake module will define macro pkg_check_modules() .

With this macro you can specify

  • find exact version of library:

If library is found, pkg_check_modules() macro will

  • set variable PJSIP_FOUND=1
  • set variable PJSIP_INCLUDE_DIRS=$(pkg-config —cflags libpjproject)
  • set variable PJSIP_LIBRARY_DIRS , PJSIP_STATIC_LIBRARY_DIRS and PJSIP_LIBRARIES by parsing output of $(pkg-config —libs libpjproject) and $(pkg-config —libs —static libpjproject) commands.
Читайте также:  Comic sans ms linux

Conclusion

This method is good enough to discover dependent libraries in cmake «in a portable way» (one cmake-script for linux and windows). For windows there is some hand-work to be done (this work can be automated in some way).

If you like this post, consider supporting me on liberapay

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.

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:

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 =, , =.
  • 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.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.
Читайте также:  Linux ubuntu terminal команды

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.

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:

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

Читайте также:  Прочитать iso образ windows

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

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 $ 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 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.

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

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

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

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.

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 _CFLAGS and _LIBS according to the output from pkg-config --cflags and pkg-config --libs.

Frequently asked questions

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

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

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.

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.

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

Оцените статью