pkg-config 了解
开源库的编译链接参数管理神器
pkg-config是Linux/Unix 系统下用于管理开源库编译和链接参数的命令行工具,核心作用是自动化解析库的元数据(安装路径、依赖关系、编译 / 链接参数),避免开发者手动输入冗长的-I(头文件路径)、-L(库路径)、-l(库名)参数,同时解决库的依赖链传递问题。
pkg-config原理
- 查找 .pc 配置文件
而.pc配置文件路径一般位于:
- 环境变量PKG_CONFIG_PATH
用户自定义路径(如手动安装的库放在/usr/local/lib/pkgconfig)
- 系统架构相关路径
如/usr/lib/x86_64-linux-gnu/pkgconfig(Debian/Ubuntu 系)
- 系统全局路径
如/usr/lib/pkgconfig、/usr/share/pkgconfig
可通过pkg-config –variable pc_path pkg-config查看当前的搜索路径
递归解析 .pc 配置文件
输出最终的编译/链接参数
pc文件语法规范
- 变量定义:VAR=value(如prefix=/usr)
- 变量引用:${VAR}(如includedir=${prefix}/include)
- 注释:以#开头(无多行注释,需每行加#)
- 多行内容:行尾加\(如依赖项过长时换行)
- 依赖版本:库名 >= 版本号(支持>=/<=/=)
举例解释
以gtk+-3.0.pc内容为例,文件路径:/usr/lib/x86_64-linux-gnu/pkgconfig/gtk+-3.0.pc
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| prefix=/usr exec_prefix=${prefix} libdir=/usr/lib/x86_64-linux-gnu includedir=${prefix}/include targets=x11 broadway wayland
gtk_binary_version=3.0.0 gtk_host=x86_64-pc-linux-gnu
Name: GTK+ Description: GTK+ Graphical UI Library Version: 3.24.33 Requires: gdk-3.0 atk >= 2.32.0 cairo >= 1.14.0 cairo-gobject >= 1.14.0 gdk-pixbuf-2.0 >= 2.30.0 gio-2.0 >= 2.57.2 Requires.private: atk atk-bridge-2.0 wayland-client >= 1.14.91 xkbcommon >= 0.2.0 wayland-cursor >= 1.14.91 wayland-egl epoxy >= 1.4 fribidi >= 0.19.7 pangoft2 gio-unix-2.0 >= 2.57.2 Libs: -L${libdir} -lgtk-3 Cflags: -I${includedir}/gtk-3.0
|
基础路径
1 2 3 4 5
| prefix=/usr exec_prefix=${prefix} libdir=/usr/lib/x86_64-linux-gnu includedir=${prefix}/include targets=x11 broadway wayland
|
上述内容描述了gtk安装的一些信息:
- prefix: 根安装目录前缀为/usr
- exec_prefix: 可执行文件前缀。通常继承prefix,仅当库的可执行文件和库文件分离时才单独设置(如/usr/local/bin和/usr/local/lib)
- libdir:库文件路径为/usr/lib/x86_64-linux-gnu
- includedir: 头文件根路径,后续会通过Cflags追加具体的子目录
- targets: 支持的窗口系统目标
版本与平台信息
1 2 3 4 5
| gtk_binary_version=3.0.0 gtk_host=x86_64-pc-linux-gnu Name: GTK+ Description: GTK+ Graphical UI Library Version: 3.24.33
|
- gtk_binary_version: GTK + 二进制兼容版本
即SOVERSION(共享库版本),是 Linux 共享库的核心机制:系统中实际的库文件是libgtk-3.so.0(或libgtk-3.so.3.24.33)3.0.0表示:主版本 3,次版本 0,修订版 0—— 只要主版本不变,共享库就保持二进制兼容(程序编译时链接libgtk-3.so,运行时可加载任何兼容的版本)
- gtk_host: 构建主机的三元组
格式为架构-厂商-系统,是 autotools(autoconf/automake) 的标准标识:
x86_64:CPU 架构
pc:厂商(pc 表示通用个人计算机)
linux-gnu:系统(Linux+GNU 工具链)
用于交叉编译时识别目标平台(如编译 ARM 架构的 GTK + 程序时,该值会变为arm-linux-gnueabihf)
- Name: pkg-config 查询名
必须唯一,是pkg-config的核心查询标识(如pkg-config –cflags gtk+-3.0中的gtk+-3.0)
- Version: 库的发布版本
依赖项配置
公共依赖(Requires):程序必须依赖的库
1
| Requires: gdk-3.0 atk >= 2.32.0 cairo >= 1.14.0 cairo-gobject >= 1.14.0 gdk-pixbuf-2.0 >= 2.30.0 gio-2.0 >= 2.57.2
|
定义:使用 GTK + 的程序在编译和运行时都依赖的库,这些库的符号会被 GTK + 暴露给上层程序,因此程序必须链接这些库
私有依赖(Requires.private):GTK + 内部依赖的库
1
| Requires.private: atk atk-bridge-2.0 wayland-client >= 1.14.91 xkbcommon >= 0.2.0 wayland-cursor >= 1.14.91 wayland-egl epoxy >= 1.4 fribidi >= 0.19.7 pangoft2 gio-unix-2.0 >= 2.57.2
|
定义:GTK + 库自身内部使用的库,这些库的符号不会暴露给上层程序,因此程序不需要直接链接(但静态链接时需要)
核心设计逻辑:
动态链接时:程序只需要链接libgtk-3.so,libgtk-3.so已经内部链接了这些私有依赖库,因此程序无需关心。
静态链接时:需要将这些私有依赖库一起链接(pkg-config 的–static参数会自动处理)。
编译与链接参数
1 2
| Libs: -L${libdir} -lgtk-3 Cflags: -I${includedir}/gtk-3.0
|
这部分是直接的编译 / 链接参数,但实际使用时 pkg-config 会递归合并所有依赖库的参数
(1) Libs(链接参数)
• 字面含义:-L/usr/lib/x86_64-linux-gnu(指定库路径) + -lgtk-3(链接 libgtk-3.so)。
• 实际输出:执行pkg-config –libs gtk+-3.0时,会递归解析Requires中的所有库(如 gdk-3.0)的 Libs 参数,最终输出的参数包含所有依赖库的链接路径和库名,例如:
1
| -L/usr/lib/x86_64-linux-gnu -lgtk-3 -lgdk-3 -lpangocairo-1.0 -lpango-1.0 -lharfbuzz -latk-1.0 -lcairo-gobject -lcairo -lgdk_pixbuf-2.0 -lgio-2.0 -lgobject-2.0 -lglib-2.0
|
(2) Cflags(编译参数)
• 字面含义:-I/usr/include/gtk-3.0(指定 GTK + 头文件路径)。
• 实际输出:执行pkg-config –cflags gtk+-3.0时,会递归解析Requires中的所有库的 Cflags 参数,最终输出的参数包含所有依赖库的头文件路径,例如:
1
| -I/usr/include/gtk-3.0 -I/usr/include/at-spi2-atk/2.0 -I/usr/include/at-spi-2.0 -I/usr/include/dbus-1.0
|
常用命令与示例
以下均以gtk+-3.0为例(对应你提供的.pc文件):
(1) 基础:获取编译 + 链接参数(最常用)
1 2
| pkg-config --cflags --libs gtk+-3.0
|
(2) 单独获取编译参数(Cflags)
1 2
| pkg-config --cflags gtk+-3.0
|
(3) 单独获取链接参数(Libs)
1 2
| pkg-config --libs gtk+-3.0
|
(4) 查看库的版本
1 2 3 4 5 6
| pkg-config --modversion gtk+-3.0
pkg-config --version
|
(5) 版本校验
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| pkg-config --exists gtk+-3.0 echo $?
pkg-config --atleast-version=3.20 gtk+-3.0 echo $?
pkg-config --max-version=3.25 gtk+-3.0 echo $?
pkg-config --exact-version=3.24.33 gtk+-3.0 echo $?
|
(6) 查看库的元数据
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| pkg-config --describe-package gtk+-3.0
pkg-config --print-requires gtk+-3.0
pkg-config --print-requires-private gtk+-3.0
pkg-config --print-requires --recursive gtk+-3.0
|
(7) 态链接参数(–static)
当需要静态链接库时,需添加--static参数,pkg-config会自动包含私有依赖(Requires.private)的链接参数:
1
| pkg-config --cflags --libs --static gtk+-3.0
|
高级用法
1. 自定义.pc文件路径
如果手动安装的库放在/opt/gtk,其.pc文件在/opt/gtk/lib/pkgconfig,可通过PKG_CONFIG_PATH指定路径:
1 2 3 4 5 6
| export PKG_CONFIG_PATH=/opt/gtk/lib/pkgconfig:$PKG_CONFIG_PATH
echo 'export PKG_CONFIG_PATH=/opt/gtk/lib/pkgconfig:$PKG_CONFIG_PATH' >> ~/.bashrc source ~/.bashrc
|
2. 交叉编译时的使用
交叉编译(如 x86_64 编译 ARM 架构程序)时,需指定交叉编译的.pc文件路径:
1 2 3 4 5 6
| export PKG_CONFIG_PATH=/opt/arm-linux-gnueabihf/lib/pkgconfig export PKG_CONFIG_LIBDIR=/opt/arm-linux-gnueabihf/lib/pkgconfig
pkg-config --cflags --libs gtk+-3.0
|
3. 与建工具集成
(1) Makefile 中使用
1 2 3 4 5 6 7
| CFLAGS := $(pkg-config --cflags gtk+-3.0) LDFLAGS := $(pkg-config --libs gtk+-3.0)
my_gtk_app: main.c gcc main.c -o my_gtk_app $(CFLAGS) $(LDFLAGS)
|
(2) CMake 中使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| find_package(PkgConfig REQUIRED)
pkg_check_modules(GTK3 REQUIRED gtk+-3.0)
include_directories(${GTK3_INCLUDE_DIRS})
link_directories(${GTK3_LIBRARY_DIRS}) add_executable(my_gtk_app main.c) target_link_libraries(my_gtk_app ${GTK3_LIBRARIES})
add_definitions(${GTK3_CFLAGS_OTHER})
|