2023年7月10日发(作者:)
pkg-config⽤法详解⼀、背景 当开发过程中使⽤第三⽅库时,我们需要知道被使⽤的第三⽅库,它包含的头⽂件在哪⼉、它依赖哪些库、它的编译选项有哪些、它的链接选项有哪些等等,也就是说需要知道这些信息我们才能正确的编译和链接它。当然可以通过直接在编译选项中指定的⽅式来使⽤,但是,对于⼀些⼤型或者⽐较复杂的第三⽅库,包含的头⽂件或者依赖库⾮常多、⾮常复杂的时候,这样做的成本就⾮常⾼,⽽且⾮常不便于在不同平台之间的移植。 pkg-config就是解决这个问题的⼀种⽅案。⼆、pkg-config是什么 pkg-config是⼀个⽤于获取系统中安装的包/库的相关信息(例如依赖头⽂件⽬录、依赖库⽂件⽬录)的程序,通常⽤于编译和链接⼀个或多个库,典型的⽤法为:# Makefileprogram: program.c cc program.c `pkg-config --cflags --libs XXX` # 此处的XXX表⽰库名称 pkg-config通过读取⼀个名为.pc的⽂件来获取包的信息,⼀般会从/usr/lib/pkgconfig, /usr/share/pkgconfig,
/usr/local/lib/pkgconfig, /usr/local/share/pkgconfig来查找.pc⽂件,除此之外,也会查找PKG_CONFIG_PATH环境变量指定的路径。三、如何使⽤pkg-config Linux或macOS系统可以通过man pkg-config来查看pkg-config的⽤法,选项有很多,此处不⼀⼀介绍,最常⽤到的两个选项是pkg-config --cflags 和pkg-config --libs ,其含义分别为:--cflags:获取编译包的所需要的预处理或者编译选项,例如-I/usr/include,指定编译包的头⽂件搜索路径。--libs:获取编译包所需要的链接选项,例如-L/usr/lib指定库⽂件搜索路径,或-lXXX指定具体的库⽂件。 下⾯以⼀个例⼦来说明pkg-config的⽤法,例⼦将会⽤到liblzma库(可以使⽤pkg-config --list-all来查看当前pkg-config已经识别的库),程序很简单,就是通过调⽤⼀个接⼝打印出liblzma的版本号,当然,接⼝是库liblzma提供的://
// 打印lzma库的版本号#include "lzma.h"#include int main(int argc, char** argv){ const char* version = lzma_version_string(); std::cout << "lzma version is: " << version << std::endl; return 0;} lzma.h是lzma库提供的⼀个头⽂件,lzma_version_string是lzma库提供的⼀个接⼝,功能为获取lzma库的版本号,不需要⼊参,返回⼀个常量字符串。程序调⽤此接⼝并将版本号打印出来。 直接使⽤g++ -o test 是⽆法编译通过的,因为我们不知道关于lzma库的任何信息(例如头⽂件lzma.h头⽂件在哪个⽬录下,lzma库在哪个⽬录下等等),此时就是pkg-config发挥作⽤的时候了,编译命令如下:// 在命令⾏中执⾏g++ -o test `pkg-config --cflags --libs liblzma` 编译通过后得到可执⾏⽂件test,在我的环境中运⾏test得到如下输出:./testlzma version is: 5.2.5四、⾃⼰编写的库如何让pkg-config使⽤ 从前⾯的介绍可以知道,pkg-config会在常⽤的系统路径下查找.pc⽂件,除此之外,还会查找PKG_CONFIG_PATH环境变量指定的路径。 那么⾃⼰编写的库,想让pkg-config找到并使⽤,需要两个步骤:编写库相关的.pc⽂件;将.pc⽂件放在pkg-config的查找路径之下; 第⼆点好办,将.pc⽂件放在⼏个指定的路径或者环境变量PKG_CONFIG_PATH指定的路径即可,那么.pc⽂件怎么编写呢?.pc⽂件的格式是⽤来描述⼀个库的名称、版本、编译选项、链接选项等内容的⽂件,因此它需要包含:名称、描述、版本信息、编.pc译选项和链接选项⼏个部分,具体来说,是对Name、Description、Version、Cflags、Libs五个变量的⼀个定义,定义⽅式为变量:
内容,其中Cflags和Libs可能会使⽤编译或者链接的⼀些选项,例如-I、-L等。# : mylibDescription: mylib for testVersion: 1.0Cflags:-I/XXX/mylib/includeLibs:-L/XXX/mylib/lib –lmylib当然,这个⽂件也可以定义其他变量,以⽅便使⽤。例如⽬录可以使⽤⼀个变量来定义,这样在Cflags或Libs中就直接使⽤该变量即可,例如:# ootdir=/XXX/mylibName: mylibDescription: mylib for testVersion: 1.0Cflags:-I${librootdir}includeLibs:-L${librootdir}/lib –lmylib 下⾯来写⼀个简单的⽰例,4.1 库⽂件的编写 ⾸先编写⼀个库⽂件,⽬录结构如下:mymath # 库的顶层⽬录-- # .pc⽂件,以便pkg-config使⽤--include # 库提供的头⽂件⽬录----mymath.h # 库提供的头⽂件--lib # 库⽂件⽬录----libmymath.a # 库⽂件 库⽂件提供的内容很简单:⼀个add接⼝⽤于计算两个整数的和并打印出来。由于是使⽤库的⽅式,⽂件只是在编译libmymath.a时需要使⽤,并不需要对外提供,下⾯是和mymath.h的内容:// pace mymath { int add(int a, int b);};// #include "mymath.h"#include namespace mymath { int add(int a, int b) { std::cout << "Add " << a << " and " << b << " is " << a + b << std::endl; return a + b; }};4.2 .pc⽂件的编写 头⽂件和库⽂件所在的⽬录根据实际指定即可,此处以/XXX代替.# ootdir=/XXX/mymathName: mymathDescription: a simple add functionVersion: 1.0Cflags: -I${librootdir}/includeLibs: -L${librootdir}/lib -lmymath4.3 让.pc⽂件被pkg-config可见 可以把拷贝到系统查找的⼏个⽬录或者将⽂件所在的⽬录添加到环境变量PKG_CONFIG_PATH中,此处使⽤第⼆种办法:# 命令⾏中执⾏,/XXX需要替换成实际的⽬录PKG_CONFIG_PATH=/XXX/mymathexport PKG_CONFIG_PATH 这样就可以使⽤pkg-config命令来获取mymath库的信息了:# 命令⾏中执⾏pkg-config --list-all | grep "mymath"mymath mymath - a simple add functionpkg-config --cflags --libs mymath-I/XXX/mymath/include -L/XXX/mymath/lib -lmymath4.4 测试// -config对库mymath的使⽤#include "mymath.h"int main(int argc, char** argv){ mymath::add(1, 2); return 0;} 编译命令如下:g++ -o test `pkg-config --cflags --libs mymath` 运⾏结果:./testAdd 1 and 2 is 3
发布者:admin,转转请注明出处:http://www.yc00.com/news/1688986684a191871.html
评论列表(0条)