pkg-config - 返回相关已安装库的元信息

pkg-config - 返回相关已安装库的元信息

pkg-config is a computer program that defines and supports a unified interface for querying installed libraries for the purpose of compiling software that depends on them. It allows programmers and installation scripts to work without explicit knowledge of detailed library path information. pkg-config was originally designed for Linux, but it is now also available for the various BSDs, Microsoft Windows, Mac OS X, and Solaris.
pkg-config 是一个在源代码编译时查询已安装的库的使用接口的计算机工具软件。pkg-config 原本是设计用于 Linux 的,但现在各个版本的 BSDs, Microsoft Windows, Mac OS X and Solaris 上都有着可用的版本。

It outputs various information about installed libraries. This information may include:

  • Parameters for C or C++ compiler
  • Parameters for linker
  • Version of the package in question

它输出已安装的库的相关信息,包括:

  • C/C++ 编译器需要的输入参数
  • 链接器需要的输入参数
  • 已安装软件包的版本信息

如果库的头文件不在 /usr/include 目录中,在编译的时候需要用 -I 参数指定其路径。由于同一个库在不同系统上可能位于不同的目录下,用户安装库的时候也可以将库安装在不同的目录下。即使使用同一个库,由于库的路径的不同,造成了用 -I 参数指定的头文件的路径和在连接时使用 -L 参数指定 lib 库的路径都可能不同,其结果就是造成了编译命令界面的不统一。可能由于编译,连接的不一致,造成同一份程序从一台机器复制到另一台机器时就可能会出现问题。

pkg-config 就是用来解决编译连接界面不统一问题的一个工具。

库文件在链接 (静态库和共享库) 和运行 (仅限于使用共享库的程序) 时被使用,其搜索路径是在系统中进行设置的。一般 Linux 系统把 /lib/usr/lib 两个目录作为默认的库搜索路径,所以使用这两个目录中的库是不需要进行设置搜索路径即可直接使用。对于处于默认库搜索路径之外的库,需要将库的位置添加到库的搜索路径之中。设置库文件的搜索路径有下列两种方式:

  1. 在环境变量 LD_LIBRARY_PATH 中指明库的搜索路径。
  2. /etc/ld.so.conf 文件中添加库的搜索路径。

将自己可能存放库文件的路径都加入到 /etc/ld.so.conf 也是可行的。

在程序链接时,对于库文件 (静态库和共享库) 的搜索路径,可以通过 -L 参数显式指定。用 -L 设置的路径将被优先搜索,在连接的时候通常都会以这种方式直接指定要连接的库的路径。

/etc/ld.so.conf 文件中添加库的搜索路径,这种设置方式对于程序链接时的库 (包括共享库和静态库) 的定位已经足够了,但是对于使用共享库的程序的执行还是不够的。为了加快程序执行时对共享库的定位速度,避免使用搜索路径查找共享库的低效率,所以是直接读取库列表文件 /etc/ld.so.cache 从中进行搜索的。

/etc/ld.so.cache 是一个非文本的数据文件,不能直接编辑,它是根据 /etc/ld.so.conf 中设置的搜索路径由 sudo /sbin/ldconfig 命令将这些搜索路径下的共享库文件集中在一起而生成的 (sudo ldconfig 命令要以 root 权限执行)。为了保证程序执行时对库的定位,在 /etc/ld.so.conf 中进行库搜索路径的设置之后,还必须要运行 sudo /sbin/ldconfig 命令更新 /etc/ld.so.cache 文件。

ldconfig 的作用就是将 /etc/ld.so.conf 列出的路径下的库文件缓存到 /etc/ld.so.cache 以供使用。当安装完一些库文件,或者修改 ld.so.conf 增加新的库路径后,需要运行一下 /sbin/ldconfig 使所有的库文件都被缓存到 ld.so.cache 中。如果不这样做,即使库文件明明就在 /usr/lib 下的,也是不会被使用的,编译过程中报错,缺少 xxx 库。

strong@foreverstrong:~$ sudo ldconfig
strong@foreverstrong:~$ 

strong@foreverstrong:~$ sudo /sbin/ldconfig
strong@foreverstrong:~$ 

Linux 系统中,为了让动态链接库能被系统中的其它程序共享,其名字应符合 lib*.so.* 格式。如果某个动态链接库不符合此格式,则 Linux 的动态链接库自动装入程序 (ld) 将搜索不到此链接库,其它程序也无法共享。

格式中,第一个 * 通常表示为简写的库名,第二个 * 通常表示为该库的版本号。基本 C 动态链接库的名字为 libc.so.6,线程 pthread 动态链接库的名字为 libpthread.so.0。如果没有指定版本号,也是符合要求的格式。

为了让动态链接库为系统所共享,还需运行动态链接库的管理命令 sudo ldconfig
sudo ldconfig 命令的用途是在默认搜寻目录 (/lib/usr/lib) 以及动态库配置文件 /etc/ld.so.conf 内所列的目录下,搜索出可共享的动态链接库 (lib*.so*),进而创建出动态装入程序 (ld.so) 所需的连接和缓存文件。

缓存文件默认为 /etc/ld.so.cache,文件保存已排好序的动态链接库名字列表。Linux 下的共享库机制采用了类似于高速缓存的机制,将库信息保存在 /etc/ld.so.cache 里边。程序链接时首先从这个文件里边查找,然后再到 ld.so.conf 的路径里边去详细找。这就是修改了 ld.so.conf 要重新运行一下 ldconfig 的原因。

-shared:该选项指定生成动态链接库 (不用该标志外部程序无法连接)。
-fPIC:该选项表示编译为位置独立的代码,不用此选项的话编译后的代码是位置相关的。动态载入时是通过代码拷贝的方式来满足不同进程的需要,而不能达到真正代码段共享的目的。
-L.:该选项表示要链接的库在当前目录中。
-lstrong:编译器查找动态连接库时有隐含的命名规则,即在给出的名字前面加上 lib,后面加上 .so 来确定库的名称 (libstrong.so)。

如果有 root 权限的话,可以修改 /etc/ld.so.conf 文件,然后调用 /sbin/ldconfig 来达到同样的目的。如果没有 root 权限,可以采用输出 LD_LIBRARY_PATH 的方法。

The first implementation was written in shell. Later, it was rewritten in C using the GLib library.

1. Name

pkg-config - Return metainformation about installed libraries
pkg-config - 返回相关已安装库的元信息

metainformation:元信息

2. Synopsis

pkg-config [--modversion] [--version] [--help] [--atleast-pkgconfig-version=VERSION] [--print-errors] [--short-errors] [--silence-errors] [--errors-to-stdout] [--debug] [--cflags] [--libs] [--libs-only-L] [--libs-only-l] [--cflags-only-I] [--libs-only-other] [--cflags-only-other] [--variable=VARIABLENAME] [--define-variable=VARIABLENAME=VARIABLEVALUE] [--print-variables] [--uninstalled] [--exists] [--atleast-version=VERSION] [--exact-version=VERSION] [--max-version=VERSION] [--validate] [--list-all] [--print-provides] [--print-requires] [--print-requires-private] [LIBRARIES...]

synopsis [sɪ'nɒpsɪs]:n. 概要,大纲
explicit [ɪk'splɪsɪt; ek-]:adj. 明确的,清楚的,直率的,详述的

When a library is installed (automatically through the use of an RPM, deb, or other binary packaging system or by compiling from the source), a .pc file should be included and placed into a directory with other .pc files (the exact directory is dependent upon the system and outlined in the pkg-config man page). This file has several entries.
当安装一个库时 (例如从 RPM,deb 或其他二进制包管理系统),会包括一个后缀名为 .pc 的文件,它会放入某个文件夹下 (依赖于你的系统设置)。

These entries typically contain a list of dependent libraries that programs using the package also need to compile. Entries also typically include the location of header files, version information and a description.
在这个 .pc 文件里包含有数个条目。这些条目通常包含用于其他使用这个库的程序编译时需要的库设置,以及头文件的位置,版本信息和一个简介。
一般来讲,第三方库都会提供一个 *.pc 文件,pkg-config 程序通过读取这个 *.pc 的文件,获取了库的头文件位置和库的路径等信息,然后告知编译器,实现库的自动使用。

Here is an example .pc file for libpng:
这是一个用于 libpng.pc 文件的样例:

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

Name: libpng
Description: Loads and saves PNG files
Version: 1.2.8
Libs: -L${libdir} -lpng12 -lz
Cflags: -I${includedir}/libpng12

This file demonstrates how libpng informs that its libraries can be found in /usr/local/lib and its headers in /usr/local/include, that the library name is libpng, and that the version is 1.2.8. It also gives the additional linker flags that are needed to compile code that uses this library.
这个文件告诉我们这些库可以在 /usr/local/lib 找到,头文件可以在 /usr/local/include 里找到,库的名字是 libpng 并且版本号是 1.2.8。它也提供了用于编译依赖于 libpng 的源代码时需要的链接器参数。

Here is an example of usage of pkg-config while compiling:
这儿是一个编译时使用 pkg-config 的样例:

$ gcc -o test test.c $(pkg-config --libs --cflags libpng)
$ gcc -o test test.c `pkg-config --libs --cflags libpng`

上述两个示例是等同的。

3. Description

The pkg-config program is used to retrieve information about installed libraries in the system. It is typically used to compile and link against one or more libraries. Here is a typical usage scenario in a Makefile:
pkg-config 程序用于检索系统中相关已安装库的信息。它通常用于编译和链接一个或多个库。以下是 Makefile 中的典型使用方案:

program: program.c
	cc program.c $(pkg-config --cflags --libs gnomeui)
strong@foreverstrong:~$ pkg-config --cflags --libs gnomeui
Package gnomeui was not found in the pkg-config search path.
Perhaps you should add the directory containing `gnomeui.pc'
to the PKG_CONFIG_PATH environment variable
No package 'gnomeui' found
strong@foreverstrong:~$
strong@foreverstrong:~$ pkg-config --cflags --libs opencv
-I/usr/include/opencv /usr/lib/x86_64-linux-gnu/libopencv_calib3d.so -lopencv_calib3d /usr/lib/x86_64-linux-gnu/libopencv_contrib.so -lopencv_contrib /usr/lib/x86_64-linux-gnu/libopencv_core.so -lopencv_core /usr/lib/x86_64-linux-gnu/libopencv_features2d.so -lopencv_features2d /usr/lib/x86_64-linux-gnu/libopencv_flann.so -lopencv_flann /usr/lib/x86_64-linux-gnu/libopencv_gpu.so -lopencv_gpu /usr/lib/x86_64-linux-gnu/libopencv_highgui.so -lopencv_highgui /usr/lib/x86_64-linux-gnu/libopencv_imgproc.so -lopencv_imgproc /usr/lib/x86_64-linux-gnu/libopencv_legacy.so -lopencv_legacy /usr/lib/x86_64-linux-gnu/libopencv_ml.so -lopencv_ml /usr/lib/x86_64-linux-gnu/libopencv_objdetect.so -lopencv_objdetect /usr/lib/x86_64-linux-gnu/libopencv_ocl.so -lopencv_ocl /usr/lib/x86_64-linux-gnu/libopencv_photo.so -lopencv_photo /usr/lib/x86_64-linux-gnu/libopencv_stitching.so -lopencv_stitching /usr/lib/x86_64-linux-gnu/libopencv_superres.so -lopencv_superres /usr/lib/x86_64-linux-gnu/libopencv_ts.so -lopencv_ts /usr/lib/x86_64-linux-gnu/libopencv_video.so -lopencv_video /usr/lib/x86_64-linux-gnu/libopencv_videostab.so -lopencv_videostab
strong@foreverstrong:~$ 
MAKEFILE

ifeq ($(OPENCV), 1) 
COMMON+= -DOPENCV
CFLAGS+= -DOPENCV
LDFLAGS+= `pkg-config --libs opencv` -lstdc++
COMMON+= `pkg-config --cflags opencv` 
endif

命令中的 ` 是反引号,不是单引号。位于 Tab 键正上方,数字键 1 的左边。
在 shell 中,反引号具有解引用的作用,命令输出代替命令本身,输出变量进行赋值。

pkg-config retrieves information about packages from special metadata files. These files are named after the package, and has a .pc extension. On most systems, pkg-config looks in /usr/lib/pkgconfig, /usr/share/pkgconfig, /usr/local/lib/pkgconfig and /usr/local/share/pkgconfig for these files. It will additionally look in the colon-separated (on Windows, semicolon-separated) list of directories specified by the PKG_CONFIG_PATH environment variable.
pkg-config 从特殊元数据文件中检索有关包的信息。 这些文件以包的名称命名,并具有 .pc 扩展名。在大多数系统上,pkg-config/usr/lib/pkgconfig, /usr/share/pkgconfig, /usr/local/lib/pkgconfig and /usr/local/share/pkgconfig 中查找这些文件。它还将查看由 PKG_CONFIG_PATH 环境变量指定的以冒号分隔的 (在 Windows上,以分号分隔的) 目录列表。

The package name specified on the pkg-config command line is defined to be the name of the metadata file, minus the .pc extension. If a library can install multiple versions simultaneously, it must give each version its own name (for example, GTK 1.2 might have the package name “gtk+” while GTK 2.0 has “gtk±2.0”).
pkg-config 命令行中指定的软件包名称定义为元数据文件的名称,减去 .pc 扩展名。如果库可以同时安装多个版本,它必须为每个版本提供自己的名称 (例如,GTK 1.2可能具有包名称 “gtk+” 而 GTK 2.0 具有 “gtk±2.0”)。

retrieve [rɪ'triːv]:vt. 检索,恢复,重新得到 vi. 找回猎物 n. 检索,恢复,取回
typically ['tɪpɪkəlɪ]:adv. 代表性地,作为特色地
GNOME UI Library,libgnomeui
metadata ['metədeɪtə]:n. 元数据
colon ['kəʊlən]:n. 结肠,冒号,科郎
semicolon [,semɪ'kəʊlən; -'kəʊlɒn]:n. 分号

In addition to specifying a package name on the command line, the full path to a given .pc file may be given instead. This allows a user to directly query a particular .pc file.
除了在命令行上指定包名称之外,还可以给出给定 .pc 文件的完整路径。这允许用户直接查询特定的 .pc 文件。

4. Options

The following options are supported:

--version

Displays the version of pkg-config and terminates.

strong@foreverstrong:~$ pkg-config --version
0.29.1
strong@foreverstrong:~$

--short-errors

Print short error messages.
打印简短的错误消息。

--errors-to-stdout

If printing errors, print them to stdout rather than the default stderr.
如果打印错误,请将它们打印到 stdout 而不是默认的 stderr。

--help

Displays a help message and terminates.

terminate ['tɜːmɪneɪt]:vt. 使终止,使结束,解雇 vi. 结束,终止,结果 adj. 结束的

The following options are used to compile and link programs:

--cflags - 预处理和编译 flags

This prints pre-processor and compile flags required to compile the packages on the command line, including flags for all their dependencies. Flags are “compressed” so that each identical flag appears only once. pkg-config exits with a nonzero code if it can’t find metadata for one or more of the packages on the command line.
这将打印在命令行上编译包所需的预处理器和编译标志,包括所有依赖项的标志。标志被“压缩”,因此每个相同的标志只出现一次。如果 pkg-config 无法在命令行上找到一个或多个软件包的元数据,则它将以非零代码退出。

compressed [kəm'prest]:adj. 被压缩的,扁平的
strong@foreverstrong:~$ pwd
/home/strong
strong@foreverstrong:~$ 
strong@foreverstrong:~$ pkg-config --cflags opencv
-I/usr/include/opencv
strong@foreverstrong:~$

--cflags-only-I

This prints the -I part of --cflags. That is, it defines the header search path but doesn’t specify anything else.
这将打印 --cflags-I 部分。也就是说,它定义了 header 搜索路径,但没有指定任何其他内容。

--cflags-only-other

This prints parts of --cflags not covered by --cflags-only-I.
这会打印 --cflags 部分未被 --cflags-only-I 覆盖的部分。

--libs - 链接 flags

This option is identical to --cflags, only it prints the link flags. As with --cflags, duplicate flags are merged (maintaining proper ordering), and flags for dependencies are included in the output.
此选项与 --cflags 相同,只打印链接标志。与 --cflags 一样,重复的标志被合并 (保持正确的排序),并且依赖的标志包含在输出中。

strong@foreverstrong:~$ pwd
/home/strong
strong@foreverstrong:~$ 
strong@foreverstrong:~$ pkg-config --libs opencv
/usr/lib/x86_64-linux-gnu/libopencv_calib3d.so -lopencv_calib3d /usr/lib/x86_64-linux-gnu/libopencv_contrib.so -lopencv_contrib /usr/lib/x86_64-linux-gnu/libopencv_core.so -lopencv_core /usr/lib/x86_64-linux-gnu/libopencv_features2d.so -lopencv_features2d /usr/lib/x86_64-linux-gnu/libopencv_flann.so -lopencv_flann /usr/lib/x86_64-linux-gnu/libopencv_gpu.so -lopencv_gpu /usr/lib/x86_64-linux-gnu/libopencv_highgui.so -lopencv_highgui /usr/lib/x86_64-linux-gnu/libopencv_imgproc.so -lopencv_imgproc /usr/lib/x86_64-linux-gnu/libopencv_legacy.so -lopencv_legacy /usr/lib/x86_64-linux-gnu/libopencv_ml.so -lopencv_ml /usr/lib/x86_64-linux-gnu/libopencv_objdetect.so -lopencv_objdetect /usr/lib/x86_64-linux-gnu/libopencv_ocl.so -lopencv_ocl /usr/lib/x86_64-linux-gnu/libopencv_photo.so -lopencv_photo /usr/lib/x86_64-linux-gnu/libopencv_stitching.so -lopencv_stitching /usr/lib/x86_64-linux-gnu/libopencv_superres.so -lopencv_superres /usr/lib/x86_64-linux-gnu/libopencv_ts.so -lopencv_ts /usr/lib/x86_64-linux-gnu/libopencv_video.so -lopencv_video /usr/lib/x86_64-linux-gnu/libopencv_videostab.so -lopencv_videostab
strong@foreverstrong:~$
proper ['prɒpə]:adj. 适当的,本身的,特有的,正派的 adv. 完全地
dependency [dɪ'pend(ə)nsɪ]:n. 属国;从属;从属物

--libs-only-L

This prints the -L/-R part of --libs. That is, it defines the library search path but doesn’t specify which libraries to link with.
这将打印 --libs-L/-R 部分。也就是说,它定义了库搜索路径,但没有指定要链接的库。

--libs-only-l

This prints the -l part of --libs for the libraries specified on the command line. Note that the union of --libs-only-l and --libs-only-L may be smaller than --libs, due to flags such as -rdynamic.
这将为命令行中指定的库打印 --libs-l 部分。请注意,由于诸如 -rdynamic 之类的标志,--libs-only-l--libs-only-L 的并集可能小于 --libs

strong@foreverstrong:~$ pkg-config --libs-only-L opencv

strong@foreverstrong:~$ 
strong@foreverstrong:~$ pkg-config --libs-only-l opencv
-lopencv_calib3d -lopencv_contrib -lopencv_core -lopencv_features2d -lopencv_flann -lopencv_gpu -lopencv_highgui -lopencv_imgproc -lopencv_legacy -lopencv_ml -lopencv_objdetect -lopencv_ocl -lopencv_photo -lopencv_stitching -lopencv_superres -lopencv_ts -lopencv_video -lopencv_videostab
strong@foreverstrong:~$

编译的时候 -I 指定头文件路径,-L 指定库文件路径。
在程序链接时,对于库文件 (静态库和共享库) 的搜索路径,可以通过 -L 参数显式指定。用 -L 设置的路径将被优先搜索,在连接的时候通常都会以这种方式直接指定要连接的库的路径。

--variable=VARIABLENAME

This returns the value of a variable defined in a package’s .pc file. Most packages define the variable “prefix”, for example, so you can say:
这将返回包的 .pc 文件中定义的变量的值。例如,大多数软件包定义变量 “prefix”,因此您可以说:

$ pkg-config --variable=prefix glib-2.0
/usr/
strong@foreverstrong:~$ pkg-config --variable=prefix glib-2.0
/usr
strong@foreverstrong:~$ 

--define-variable=VARIABLENAME=VARIABLEVALUE

This sets a global value for a variable, overriding the value in any .pc files. Most packages define the variable “prefix”, for example, so you can say:
这将为变量设置全局值,从而覆盖任何 .pc 文件中的值。 例如,大多数软件包定义变量 “prefix”,因此您可以说:

$ pkg-config --print-errors --define-variable=prefix=/foo \
             --variable=prefix glib-2.0
/foo
strong@foreverstrong:~$ pkg-config --print-errors --define-variable=prefix=/foo \
>              --variable=prefix glib-2.0
/foo
strong@foreverstrong:~$ 

--static

Output libraries suitable for static linking. That means including any private libraries in the output. This relies on proper tagging in the .pc files, else a too large number of libraries will ordinarily be output.
输出库适用于静态链接。这意味着在输出中包含任何私有库。这依赖于 .pc 文件中的正确标记,否则通常会输出太多的库。

tag [tæg]:n. 标签,名称,结束语,附属物 vt. 尾随,紧随,连接,起浑名,添饰 vi. 紧随
ordinarily ['ɔːd(ə),n(ə)rɪlɪ; ,ɔːdɪ'nerɪlɪ]:adv. 通常地,一般地

--list-all

List all modules found in the pkg-config path.

strong@foreverstrong:~$ pkg-config --list-all
sqlite3                        SQLite - SQL database engine
Qt5DBus                        Qt5 DBus - Qt DBus module
......
......

静态库 .a.o 文件的集合,编译链接后集成到应用程序中。
共享库是在程序运行的时才被使用的,其搜索路径是在系统中预先设置的。对于搜索路径之外的库,使用时必须设置好环境变量 LD_LIBRARY_PATH,否则应用程序找不到。库放到了应用程序文件夹的 ./lib 中,在启动应用前调用下面这句:

export LD_LIBRARY_PATH="./lib"

最好写在启动脚本里。

References

https://linux.die.net/man/1/pkg-config
https://man.openbsd.org/pkg-config.1
https://www.freedesktop.org/wiki/Software/pkg-config/

pkgconfig 1.5.1
https://pypi.org/project/pkgconfig/
pkgconfig is a Python module to interface with the pkg-config command line tool and supports Python 2.6+ and 3.3+.

展开阅读全文

没有更多推荐了,返回首页

©️2019 CSDN 皮肤主题: 编程工作室 设计师: CSDN官方博客
应支付0元
点击重新获取
扫码支付

支付成功即可阅读