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)

 

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