pkg-config的作用和用法

以前不习惯用pkg-config,喜欢在Makefile中指定程序的依赖项。但是这样做存在一个问题,即当你的机器上安装了同一名称但不同版本的依赖库时,就有可能导致链接失败。这时,pkg-config就显示了它的优势:使编译选项简洁明了。

那么pkg-config是干啥的呢?按照官方说法,它用来返回已安装库的基本信息。

pkg-config的参数有如下一堆,想获得更全的参数及用法,可以通过执行“pkg-config --help”来查看全部参数及意义。

pkg-config [--modversion] [--help] [--print-errors] [--silence-errors] [--cflags] [--libs] [--libs-only-L] [--libs-only-l] [--cflags-only-I] [--variable=VARIABLENAME] [--define-variable=VARIABLENAME=VARIABLEVALUE] [--uninstalled] [--exists] [--atleast-version=VERSION] [--exact-version=VERSION] [--max-version=VERSION] [LIBRARIES...]

以上参数中,我们常用的基本就是[--cflags] [--libs],用来指出程序依赖的头文件和库文件路径。典型用法如下:

program: program.c
        cc program.c ‘pkg-config --cflags --libs gnomeui‘

其中,gnomeui就是程序要链接的库的名称。

例如,我们常用的opencv库,若执行“pkg-config --cflags --libs opencv”,得到如下结果:

以上内容,不就是我们在Makefile里写的一堆依赖库信息吗?现在好了,一句pkg-config语句搞定。

那么问题来了,pkg-config是如何获得这些信息的呢?原来,pkg-config程序是去读取库名称对应的.pc文件,如果用opencv的库,就会去读opencv.pc。

首先,.pc文件在哪里?

默认情况下,会去prefix/lib/pkgconfig/路径下查找,具体到Linux系统,就是/usr/lib/pkgconfig/目录,若找不到,则会去PKG_CONFIG_PATH环境变量指定的路径下查找。因此,如果我们安装的库文件不在系统环境变量中,需要将其添加到PKG_CONFIG_PATH中,具体来说,执行如下操作:

export PKG_CONFIG_PATH=/home/mylibs/lib/pkgconfig:$PKG_CONFIG_PATH

其中,/home/mylibs/lib/pkgconfig就是我们所安装的库文件对应的.pc文件的存放路径。以我们安装OpenCV的路径为例,看一下pkgconfig下面都有哪些文件:

可以看到,有我们安装的libavcodec.pc、opencv.pc、x264.pc等等。

其次,.pc文件里面都有哪些内容?

我们打开opencv.pc,可以看到如下内容:

.pc中明确列出了库的prefix、执行文件地址、库地址、头文件地址,以及库的名称、描述、版本号、具体子模块库列表等等,可以说有了这个文件,我们程序依赖的内容就都有了。当然,如果你的系统装了两份不同版本的某个库,那么在使用pkg-config时就需要指定版本号了。

有了pkg-config,我们的Makefile编写起来就简洁多了,以下是依赖opencv的某工程的Makefile,贴上来做参考。

CFLAGS := -O3 $(EXTRA_INC) -std=c++11 `pkg-config --cflags --libs opencv`
LDFLAGS := $(EXTRA_LIBS)

SOURCE := $(wildcard *.cpp)
OBJ := $(patsubst %.cpp, %.o, $(wildcard *.cpp))
EXE := SmartDetect


$(EXE):$(OBJ)
        g++ -o $(EXE) $^ -I. $(CFLAGS) $(LDFLAGS)

%.o:%.cpp
        g++ -o $@ -c $^ $(CFLAGS)  -I.


.PHONY:clean
clean:
        rm $(OBJ) $(EXE)

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章