cmakepkg-config

What is the proper way to use `pkg-config` from `cmake`?


I have seen a lot of code like this:

include(FindPkgConfig)
pkg_search_module(SDL2 REQUIRED sdl2)

target_include_directories(app SYSTEM PUBLIC ${SDL2_INCLUDE_DIRS})
target_link_libraries(app ${SDL2_LIBRARIES})

However, that seems to be the wrong way about doing it, as it only uses the include directories and libraries, but ignores defines, library paths and other flags that might be returned by pkg-config.

What would be the correct way to do this and ensure that all compile and link flags returned by pkg-config are used by the compiled app? And is there a single command to accomplish this, i.e., something like target_use(app SDL2)?

ref:


Solution

  • If you're using cmake and pkg-config in a pretty normal way, this solution works.

    If, however, you have a library that exists in some development directory (such as /home/me/hack/lib), then using other methods seen here fail to configure the linker paths. Libraries that are not found under the typical install locations would result in linker errors, like /usr/bin/ld: cannot find -lmy-hacking-library-1.0. This solution fixes the linker error for that case.

    Another issue could be that the pkg-config files are not installed in the normal place, and the pkg-config paths for the project need to be added using the PKG_CONFIG_PATH environment variable while cmake is running (see other Stack Overflow questions regarding this). This solution also works well when you use the correct pkg-config path.

    Using IMPORTED_TARGET is key to solving the issues above. This solution is an improvement on this earlier answer and boils down to this final version of a working CMakeLists.txt:

    cmake_minimum_required(VERSION 3.14)
    project(ya-project C)
    
    # the `pkg_check_modules` function is created with this call
    find_package(PkgConfig REQUIRED) 
    
    # these calls create special `PkgConfig::<MODULE>` variables
    pkg_check_modules(MY_PKG REQUIRED IMPORTED_TARGET any-package)
    pkg_check_modules(YOUR_PKG REQUIRED IMPORTED_TARGET ya-package)
    
    add_executable(program-name file.c ya.c)
    
    target_link_libraries(program-name PUBLIC
            PkgConfig::MY_PKG
            PkgConfig::YOUR_PKG)
    

    Note that target_link_libraries does more than change the linker commands. It also propagates other PUBLIC properties of specified targets like compiler flags, compiler defines, include paths, etc., so, use the PUBLIC keyword with caution.