Using pkg-config to discover PJSIP in cmake

comments

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

sudo apt-get install pkg-config

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

sudo apt-get install pjproject

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

# install srtp prereqisite
sudo apt-get install libsrtp0 libsrtp0-dev
# get sources
wget http://www.pjsip.org/release/2.3/pjproject-2.3.tar.bz2
tar jxf pjproject-2.3.tar.bz2

# configure, make, install
pushd pjproject-2.3
./configure
make dep
make clean
make
sudo make install
popd

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 convinient 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:

[email protected][email protected]
exec_prefix=${prefix}
libdir=${prefix}/lib
includedir=${prefix}/pjlib/include;${prefix}/pjlib-util/include;${prefix}/pjmedia/include;${prefix}/pjnath/include;${prefix}/pjsip/include

Name:         libpjproject
Description:  Multimedia communication library
URL:          http://www.pjsip.org
Version:      2.3.0
Libs:         -L${libdir} -llibpjproject-$$(Platform)-$$(PlatformToolset)-$$(Configuration)-Dynamic.lib
Libs.private: -lWs2_32.lib
Cflags:       -I${includedir}

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:

pkg-config --cflags libpjproject
pkg-config --libs --msvc-syntax libpjproject

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

# find pkg-config executable, define pkg_check_modules() macro
find_package(PkgConfig REQUIRED)
if (NOT PKG_CONFIG_FOUND)
   message(SEND_ERROR "PkgConfig not found")
   return()
endif()

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:
  pkg_check_modules(PJSIP libpjproject=2.3 REQUIRED)
  • find least version supported
  pkg_check_modules(PJSIP libpjproject>=2.3 REQUIRED)
  • find any version
  pkg_check_modules(PJSIP libpjproject REQUIRED)

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.

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

Comments