pkg-config

news2025/2/27 11:11:42

前言

在介绍 pkg-config 之前,先讲一个我的经历。
有一次我想用 libgtk 库在 ubuntu 上实现一个简单的图形界面,就像下面代码

#include <gtk/gtk.h>

int main(int argc, char *argv[])
{
	GtkWidget *window;

	gtk_init(&argc, &argv);
	window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
	gtk_widget_show(window);
	g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);
	gtk_main();

	return 0;
}

写个 Makefile 进行编译

gtk:
	gcc gtk.c -o gtk.out -lgtk

run:
	./gtk.out

想的简单,使用 gtk 库就引用下库 -lgtk 就好了,结果,编译报错

gcc gtk.c -o gtk.out -lgtk
gtk.c:1:10: fatal error: gtk/gtk.h: 没有那个文件或目录
    1 | #include <gtk/gtk.h>
      |          ^~~~~~~~~~~
compilation terminated.
make: *** [Makefile:4:gtk] 错误 1

没有 gtk.h,那就查找该文件在哪,

$ locate gtk.h
/usr/include/gtk-2.0/gtk/gtk.h

添加下头文件路径

gtk:
	gcc gtk.c -o gtk.out -lgtk \
	-I /usr/include/gtk-2.0

run:
	./gtk.out

编译,结果又报错

$ make
gcc gtk.c -o gtk.out -lgtk \
-I /usr/include/gtk-2.0
In file included from /usr/include/gtk-2.0/gdk/gdk.h:32,
                 from /usr/include/gtk-2.0/gtk/gtk.h:32,
                 from gtk.c:1:
/usr/include/gtk-2.0/gdk/gdkapplaunchcontext.h:30:10: fatal error: gio/gio.h: 没有那个文件或目录
   30 | #include <gio/gio.h>
      |          ^~~~~~~~~~~
compilation terminated.
make: *** [Makefile:4:gtk] 错误 1

就这样,头文件路径我一直加到如下,

gtk:
	gcc gtk.c -o gtk.out -lgtk \
	-I /usr/include/gtk-2.0 \
	-I /usr/include/glib-2.0 \
	-I /usr/lib/x86_64-linux-gnu/glib-2.0/include \
	-I /usr/lib/x86_64-linux-gnu/gtk-2.0/include \
	-I /usr/include/cairo \
	-I /usr/include/pango-1.0 \
	-I /usr/include/harfbuzz/ \
	-I /usr/include/gdk-pixbuf-2.0 \
	-I /usr/include/atk-1.0

run:
	./gtk.out

结果报 找不到 -lgtk,崩溃

pkg-config

后来,找到了 pkg-config 这个绝招,只要一行就解决了我上面的问题

gtk:
	gcc gtk.c -o gtk.out `pkg-config --cflags --libs gtk+-2.0`

run:
	./gtk.out

编译成功,运行效果如下
在这里插入图片描述
回过头再来看下 pkg-config 作用

什么是 pkg-config

pkg-config 是一个 linux 下的命令,用于获得某一个库/模块的所有编译相关的信息。
例子

$ pkg-config --cflags --libs gtk+-2.0
-pthread -I/usr/include/gtk-2.0 -I/usr/lib/x86_64-linux-gnu/gtk-2.0/include -I/usr/include/pango-1.0 -I/usr/include/atk-1.0 -I/usr/include/gdk-pixbuf-2.0 -I/usr/include/libmount -I/usr/include/blkid -I/usr/include/pango-1.0 -I/usr/include/fribidi -I/usr/include/cairo -I/usr/include/pixman-1 -I/usr/include/harfbuzz -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -I/usr/include/uuid -I/usr/include/freetype2 -I/usr/include/libpng16 -lgtk-x11-2.0 -lgdk-x11-2.0 -lpangocairo-1.0 -latk-1.0 -lcairo -lgdk_pixbuf-2.0 -lgio-2.0 -lpangoft2-1.0 -lpango-1.0 -lgobject-2.0 -lglib-2.0 -lharfbuzz -lfontconfig -lfreetype

为什么要有 pkg-config

从上面的例子,可以看出,pkg-config 给出了 gtk+-2.0 的头文件和库的所有信息!
这有什么好处?
所有用 gtk+-2.0 的其他程序,在编译时,只需要写 pkg-config --cflags --libs gtk+-2.0,而不需要自己去找 gtk+-2.0 的头文件在哪里,要链接的库在哪里!省时省力!
如果你写了一个库,不管是静态的还是动态的,要提供给第三方使用,那除了给人家库/头文件,最好也写一个 pkg-config 文件,这样别人使用就方便很多,不用自己再手动写依赖了你哪些库,只需要敲一个 pkg-config --libs --cflags [YOUR_LIB]

pkg-config 的信息从哪里来

很简单,有 2 种路径:
第一种:取系统的 /usr/lib 下的所有 *.pc 文件。
第二种:PKG_CONFIG_PATH 环境变量所指向的路径下的所有 *.pc 文件。

这些 pc 文件什么时候有的?都是在你安装某个库/模块的时候,添加的。比如你往系统安装libcrypt-dev 时,就会在 /usr/lib/x86_64-linux-gnu/pkgconfig/ 目录下,放一个 libcrypt.pc。
那么,pc文件到底写了什么?
打开看看就知道啦。比如 libcrypt.pc

$ cat /usr/lib/x86_64-linux-gnu/pkgconfig/libcrypt.pc
#############################################
#####   Pkg-Config file for libxcrypt   #####
#############################################

prefix=/usr
exec_prefix=${prefix}

libdir=/usr/lib/x86_64-linux-gnu
includedir=${prefix}/include

Name: libxcrypt
Version: 4.4.10
Description: Extended crypt library for DES, MD5, Blowfish and others
Libs: -L${libdir} -lcrypt
Cflags: -I${includedir}

一目了然,就是存了所有 libcrypt 的头文件/库的路径信息。

pkg-config 都有哪些命令参数

所有参数,可以通过 pkg-config –help 来查看。
但我觉得其实就 3 个参数有用。
pkg-config --cflags [NAME],查看头文件信息,如

$ pkg-config --cflags gtk+-2.0
-pthread -I/usr/include/gtk-2.0 -I/usr/lib/x86_64-linux-gnu/gtk-2.0/include -I/usr/include/pango-1.0 -I/usr/include/atk-1.0 -I/usr/include/gdk-pixbuf-2.0 -I/usr/include/libmount -I/usr/include/blkid -I/usr/include/pango-1.0 -I/usr/include/fribidi -I/usr/include/cairo -I/usr/include/pixman-1 -I/usr/include/harfbuzz -I/usr/include/glib-2.0 -I/usr/lib/x86_64-linux-gnu/glib-2.0/include -I/usr/include/uuid -I/usr/include/freetype2 -I/usr/include/libpng16

pkg-config --libs [NAME],查看库信息,如

pkg-config --libs gtk+-2.0
-lgtk-x11-2.0 -lgdk-x11-2.0 -lpangocairo-1.0 -latk-1.0 -lcairo -lgdk_pixbuf-2.0 -lgio-2.0 -lpangoft2-1.0 -lpango-1.0 -lgobject-2.0 -lglib-2.0 -lharfbuzz -lfontconfig -lfreetype

pkg-config --list-all。查看 pkg-config 的所有模块信息,如

$ pkg-config --list-all
xf86driproto                   XF86DRIProto - XF86DRI extension headers
libelf                         libelf - elfutils libelf library to read and write ELF files
cairo-ps                       cairo-ps - PostScript surface backend for cairo graphics library
ncursesw                       ncursesw - ncurses 6.2 library
libcrypto                      OpenSSL-libcrypto - OpenSSL cryptography library
libnfnetlink                   libnfnetlink - Low-level netfilter netlink communication library
libffi                         libffi - Library supporting Foreign Function Interfaces
python-2.7                     Python - Python library
...

如何添加自己的 pc 文件

如上文所说,有 2 种方式。

  1. 把你的 pc 文件,直接放到 /usr/lib/… 默认路径下。
  2. 把你的 pc 文件的路径写到 PKG_CONFIG_PATH 环境变量里。

比如,你可以在 ~/.bashrc 的文件末尾添加:

PKG_CONFIG_PATH=$PKG_CONFIG_PATH:xxx/pkgconfig/
export PKG_CONFIG_PATH

那么,pkg-config 就会到 xxx/pkgconfig/ 寻找 *.pc 文件。
我猜你想问,那我这个pc文件何时生效呢?
答案是,如果是 /usr/lib 下,立马生效!!!如果在环境变量里,只要先 source ~/.bashrc 一下,让环境变量生成,也立马生效。
并不需要什么 pkg-config update 啥命令,让其更新信息。
其实每次你执行 pkg-config,都会去遍历所有的 *.pc 文件。

如何自己写 pkg-config 的 pc 文件

其实很简单,只需要拿别人的 pc 文件改一改就行了。不过我还是提一下吧。
pc 文件的所有参数:

Name: 该模块的名字,比如你的 pc 名字是 xxxx.pc,那么名字最好也是 xxxx。
Description: 模块的简单描述。上文 pkg-config --list-all 命令出来的结果,每个名字后面就是 description。
URL: 用户可以通过该 URL 获得更多信息,或者下载信息。也是辅助的,可要可不要。
Version: 版本号。
Requires: 该模块有木有依赖于其他模块。一般没有。
Requires.private: 该模块有木有依赖于其他模块,并且还不需要第三方知道的。一般也没有。
Conflicts: 有没有和别的模块冲突。常用于版本冲突。比如,Conflicts: bar < 1.2.3,表示和 bar 模块的 1.2.3 以下的版本有冲突。
Cflags: 这个就很重要了。pkg-config 的参数 --cflags 就指向这里。主要用于写本模块的头文件的路径。
Libs: 也很重要,pkg-config 的参数 --libs 就指向这里。主要用于写本模块的库/依赖库的路径。
Libs.private: 本模块依赖的库,但不需要第三方知道。

其实必须写的只有 5 个。Name、Description、Version、Cflags、Libs。

参考

pkg-config 详解

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/426872.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

UG NX二次开发(C#)-建模-获取曲面的法矢

文章目录 1、前言2、曲面的法矢示例3、获取曲面的法矢3.1 采用 uFModl.AskFaceProps实现3.2采用 uFSo实现4、结论1、前言 在UG NX二次开发过程中,我们想获取曲面的法矢,是通过ufun函数来获取的。我们以一个平面和一个曲面来说明其开发过程。 2、曲面的法矢示例 创建一张曲…

商城系统开发方案分析

互联网的不断发展&#xff0c;电商行业已经成为了当前最重要的商业形式之一。商城系统的开发也因此而备受关注。商城系统的开发是针对B2C、B2B2C等多种商业模式&#xff0c;如用户熟知的SHOP、商派等一系列商城系统&#xff0c;将商品和服务进行在线销售的一个综合性平台。那么…

【软考备战·希赛网每日一练】2023年4月17日

文章目录一、今日成绩二、错题总结第一题第二题第三题第四题三、知识查缺题目及解析来源&#xff1a;2023年04月17日软件设计师每日一练 一、今日成绩 二、错题总结 第一题 解析&#xff1a; 第二题 解析&#xff1a; 第三题 解析&#xff1a; SCAN调度算法 也叫 “电梯”算…

RocketMQ 发送批量消息、过滤消息和事务消息

前面我们知道RocketMQ 发送延时消息与顺序消息&#xff0c;现在我们看下怎么发送批量消息、过滤消息和事务消息。 发送批量消息 限制是这些批量消息应该有相同的 topic&#xff0c;相同的 waitStoreMsgOK&#xff0c;而且不能是延时消息。 此外&#xff0c;这一批消息的总大小…

如何合理选择ClickHouse表主键

ClickHouse提供索引和数据存储的复杂机制&#xff0c;能够实现在高负载下仍有优异的读写性能。当创建MergeTree表时需要选择主键&#xff0c;主键影响大多数查询性能。本文介绍主键的工作原理&#xff0c;让我们知道如何选择合适的主键。 设置主键 MergeTree表可以设置主键&am…

香橙派5使用RK3588S内置NPU加速yolov5推理,实时识别数字达到50fps

前言&#xff1a; 香橙派5采用了RK3588S&#xff0c;内置的NPU达到了6Tops的算力&#xff0c;博主这里记录一下自己的踩坑过程&#xff0c;好不容易做出来的不能以后忘记了&#xff08;手动狗头&#xff09;。这里博主还在B站上发布了效果视频&#xff0c;大家感兴趣的话可以看…

TensorFlow 和 Keras 应用开发入门:1~4 全

原文&#xff1a;Beginning Application Development with TensorFlow and Keras 协议&#xff1a;CC BY-NC-SA 4.0 译者&#xff1a;飞龙 本文来自【ApacheCN 深度学习 译文集】&#xff0c;采用译后编辑&#xff08;MTPE&#xff09;流程来尽可能提升效率。 不要担心自己的形…

Java 中的 非并发容器

1.四大类容器 java中容器主要有四大类&#xff0c;如下图所示 2.非并发容器 1) List 类 List 类 不支持并发的有 ArrayList 与 LinkedList ArrayList 底层实现 ArrayList 底层为 数组&#xff0c;由于数组的特性&#xff0c;非常适合用于 查询多&#xff0c;增删改的业务…

【数据结构学习1】数据结构

目录数据结构定义数据结构的构成逻辑结构逻辑结构的类型存储结构数据运算数据类型和抽象数据类型算法定义分析基础时间复杂度分析事前分析估算法 -> 分析算法的执行时间时间复杂度时间复杂度类型简化的算法时间复杂度分析空间复杂度分析数据结构 定义 数据&#xff1a;所有…

工作流调度系统 Azkaban介绍与安装(一)

文章目录前言1、为什么要用工作流调度系统2、常见的工作流调度系统1 集群规划2 配置 MySQL3 配置 Executor Server3.1 修改 azkaban.properties3.2 启动3.3 激活4 配置 Web Server4.1 修改 azkaban.properties4.2 修改azkaban-users.xml文件&#xff0c;添加 atguigu 用户4.3 启…

VM 虚拟机没有网络,无法Ping通

场景&#xff1a; 虚拟机用过&#xff0c;之前一切正常&#xff0c;使用NAT模式联网&#xff0c;配置了静态IP换了路由器&#xff0c;推测是主机IP网段变了无法使用ssh工具连接虚拟机&#xff0c;且相互都ping不通&#xff08;后来经历了主机可以ping通虚拟机&#xff0c;虚拟…

PWM寄存器初始化

本模块主要实现输出频率占空比可调的 PWM 波形功能和输入捕获功能&#xff0c;同时也可作为计数器使用。一、主要特性 1. 16位向上或向下计数器&#xff1b; 2. 支持最多6路PWM通道&#xff1b; 3. 每个通道支持输出比较或边缘对齐PWM模式波形输出&#xff0c;支持设置、清除、…

关于 CSDN-AI 机器人 programmer_ada —— 阿达·洛夫莱斯(Ada Lovelace)

收到早期文章的一条新评论&#xff1a; 文笔和内容稍稍透漏着机器人的风格&#xff0c;打开主页果不其然 看到个人介绍中的巴贝奇的分析机&#xff0c;突然觉得头像很是眼熟。 最近刚读了《人工智能简史》&#xff0c;第4章——从汇编语言到TensorFlow&#xff0c;人工智能的…

使用layui组件库制作进度条

使用layui组件库制作进度条 html代码 <!DOCTYPE html> <html> <head><meta charset"UTF-8"><title>Example</title><!-- 引入 layui 的 CSS 文件 --><link rel"stylesheet" href"https://cdn.staticfil…

Day948.组件化成熟度评估,你的目的地在哪里呢 -系统重构实战

组件化成熟度评估&#xff0c;你的目的地在哪里呢 Hi&#xff0c;我是阿昌&#xff0c;今天学习记录的是关于组件化成熟度评估&#xff0c;你的目的地在哪里呢的内容。 一、组件化成熟度模型 组件化成熟度模型可以帮助咱全局去思考当前的现状&#xff0c;并制定更有针对性的…

ChatGPT带火的百万年薪职业究竟是什么?

对话有ChatGPT、画图有Midjourney&#xff0c;哪怕被封号了&#xff0c;国内的文心一言、通义千问也不遑多让。 ChatGPT等生成式AI工具涌现程度堪比“乱花渐欲迷人眼”。 拟一份演讲稿&#xff0c;画一张海报&#xff0c;做一份PPT大纲&#xff0c;生成个图表&#xff0c;敲一…

【数据结构】- 线性表+顺序表(上)

文章目录前言一、线性表二、顺序表2.1概念及结构2.2接口实现2.3具体实现总结前言 所有的失败都是上帝在考验你是否真的热爱 本章是关于数据结构中的顺序表和链表 提示&#xff1a;以下是本篇文章正文内容&#xff0c;下面案例可供参考 一、线性表 线性表&#xff08;linear …

Xilinx CDC Constraints(ug903: Chapter6 )

&#xff08;1&#xff09;About CDC Constraints 跨时钟域约束适用于具有不同启动和捕获时钟的定时路径。根据启动和捕获时钟的关系以及在CDC路径上设置的时序异常&#xff0c;有同步CDC和异步CDC。例如&#xff0c;同步时钟之间但被错误路径约束覆盖的CDC路径不被定时…

传统图像处理——颜色迁移

转自知乎&#xff1a;https://zhuanlan.zhihu.com/p/267832794,仅供学习。 利用一张图片的颜色去修改另一张图片的颜色风格。 原理是利用颜色空间的正交化&#xff0c;即更改某个颜色&#xff0c;不会影响到其它属性。这里的色彩迁移的论文则是使用了LAB空间&#xff08;RGB颜…

C语言初阶--连用scanf(以%c读取时)遇到的问题

目录前言总结前言 在我们写程序的过程中&#xff0c;会频繁使用scanf函数&#xff0c;当在一个程序中scanf用多了&#xff0c;会出现输入不了的问题&#xff01;大家有没有想过是什么原因导致的该问题呢&#xff1f;下面我们一起探讨一下吧&#xff01; 遇到问题的例子&#…