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.

Name

pkg-config - Return metainformation about installed libraries
pkg-config - 返回相關已安裝庫的元信息

metainformation:元信息

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`

上述兩個示例是等同的。

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 文件。

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:~$

--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:~$ 

–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+.

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