pkg-config

编译配置的时候,需要依赖的库不一定都在 /usr/local/include 目录下,大部分情况下需要对编译器手动指定 include 目录,同理也可能需要对链接器手动指定 lib 所在目录,而由于不同系统下安装的库所在的目录不一定一致,会导致编译配置难以跨平台执行,可以用 pkg-config 来解决这个问题。

pkg-config 查找依赖

pkg-config 是通过读取目录下的 pc 文件在确定查找结果的,这个目录通常是 libdir/pkgconfig,比如你的 libwebp 安装在 /usr/local/lib 下,那么放 pc 文件就是 /usr/local/lib/pkgconfig 下的 libavcodec.pc 文件。
文件中定义了这个依赖的名称、版本号、在当前环境的目录前缀、编译选项等等。pkg-config的输出就是来自文件

prefix=/usr/local
exec_prefix=${prefix}
libdir=/usr/local/lib
includedir=/usr/local/include

Name: libavcodec
Description: FFmpeg codec library
Version: 58.91.100
Requires: libswresample >= 3.7.100, libavutil >= 56.51.100
Requires.private:
Conflicts:
Libs: -L${libdir}  -lavcodec -pthread -lm -llzma -lz -lva
Libs.private:
Cflags: -I${includedir}

外部依赖之间可能也会有依赖关系,库的依赖也是会在 pc 文件中定义的,比如harfbuzz 的 pc 文件:

prefix=/usr/local/Cellar/harfbuzz/2.8.0_1
libdir=${prefix}/lib
includedir=${prefix}/include

Name: harfbuzz
Description: HarfBuzz text shaping library
Version: 2.8.0
Requires.private: freetype2, graphite2, glib-2.0
Libs: -L${libdir} -lharfbuzz
Libs.private: -lm -framework ApplicationServices
Cflags: -I${includedir}/harfbuzz

可以发现这个库同时依赖了 freetype2、graphite2、glib-2.0 这三个库,只要在 pc 文件中有通过 Requires 或者 Requires.private 声明过依赖,在 cflags 或者 libs 的输出结果中也会带有依赖的编译选项:

-I/usr/local/Cellar/harfbuzz/2.8.0_1/include/harfbuzz -I/usr/local/opt/freetype/include/freetype2 -I/usr/local/Cellar/graphite2/1.3.14/include -I/usr/local/Cellar/glib/2.68.1/include/glib-2.0 -I/usr/local/Cellar/glib/2.68.1/lib/glib-2.0/include -I/usr/local/opt/gettext/include -I/usr/local/Cellar/pcre/8.44/include

通常一个 lib 对应一个 pc 文件,有些项目有多个 lib,那么它也会分别定义多个 pc 文(如:ffmpeg)

pkg-config 查找路径配置

使用 pkg-config 过程中遇到库找不到的情况,不一定是外部库没有安装,默认情况下 pkg-config 的查找路径为 /usr/lib/pkgconfig/usr/share/pkgconfig,可以通过环境变量 PKG_CONFIG_PATH 在额外指定 pkg-config 的查找路径

export PKG_CONFIG_PATH="/usr/local/opt/icu4c/lib/pkgconfig:${PKG_CONFIG_PATH}"
export PKG_CONFIG_PATH="/usr/local/opt/jpeg-turbo/lib/pkgconfig:${PKG_CONFIG_PATH}"

简单使用

  • 输出 libavcodec 在当前环境的编译选项
$ pkg-config libavcodec --cflags
// 输出:
-I/usr/local/include
  • 输出 libavcodec 的链接选项
$ pkg-config libavcodec --libs
// 输出
-L/usr/local/lib -lavcodec -pthread -lm -llzma -lz -lva -lswresample -lm -lavutil -pthread -lva-drm -lva -lm -lva
  • 查看外部库在当前环境下的版本号
$ pkg-config libavcodec --version
// 输出
0.29.1
  • 命令行和编译工具可以直接结合起来
$ gcc -o test test.c `pkg-config --libs --cflags libavcodec`

CMake 中使用 pkg-config

find_package(PkgConfig REQUIRED)

if (PKG_CONFIG_FOUND)
  pkg_check_modules(my_deps REQUIRED IMPORTED_TARGET libpng libwebp)
endif()

首先利用 CMake 的 find_package 机制找到本地的 pkg-config,如果成功找到,则有两种办法查找外部库:

  • pkg_check_modules:根据列表中给的外部库,在当前环境下都试着去找到
  • pkg_search_module:找到列表中第一个成功找到的外部库​

大部分情况下使用 pkg_check_modules,第一个参数为匹配前缀,需要依赖多个外部库时,通过这个前缀,可以一次性的消费结果。也可以指定 REQUIRED 来表示依赖对这次构建是必须的,否则直接失败终止构建。接下来就是应用 pkg-config 的结果了,在 CMake 上下文中可以使用 PkgConfig : : ${prefix} 来消费结果,直接作为 target_link_libraries 的参数即可:

target_link_libraries(${PROJECT_NAME} PkgConfig::my_deps)

你可能感兴趣的:(c++,c++,CMakeLists)