歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Unix知識 >> 關於Unix >> Linux下的庫(上)--如何使用非標准庫

Linux下的庫(上)--如何使用非標准庫

日期:2017/3/6 15:30:05   编辑:關於Unix
在 linux 上編程時,很多時候會用到一些非標准的庫(即自己裝上去的庫),這些非標准的庫安裝位置可能不盡相同,這就給我們編寫程序時帶來了麻煩。 1。頭文件的位置 gcc默認會在/usr/include目錄下尋找頭文件,這是標准庫的頭文件的路徑,但非標准的庫一般不會 在linux上編程時,很多時候會用到一些非標准的庫(即自己裝上去的庫),這些非標准的庫安裝位置可能不盡相同,這就給我們編寫程序時帶來了麻煩。


1。頭文件的位置
gclearcase/" target="_blank" >cc默認會在/usr/include目錄下尋找頭文件,這是標准庫的頭文件的路徑,但非標准的庫一般不會把頭文件直接放在該目錄下,一般的作法是在該目錄下創建一個自己的目錄,然後在此目錄下直接或分門別類(即再創建更深層次的目錄,gtk+即一例證)放自己的頭文件。如果是這樣,gcc編譯時是不會找到這些頭文件的,我們會看到有“×××: No such file or directory”的出錯信息。解決的方法就是用gcc的-I選項列出這些非標准的路徑(實際編程當中一般是由pkg-config --cflags 完成這一工作的)。
2。庫的位置
gcc默認會鏈接標准c語言庫,但如果所用的庫是“舶來品”,gcc自然不會自動鏈接,如果也沒有顯式鏈接的話,在鏈接階段就會出現諸如“: undefined reference to `gtk_container_set_border_width'
/tmp/ccvHaxUx.o(.text+0x1af): In function `main':”的錯誤。 解決的方法就是利用gcc的-l參數顯式鏈接需要鏈接的庫。這樣gcc就會按照一種特定的命名規則到默認的目錄(/usr/lib和/lib等目錄)下去尋找這些庫,並自動鏈接。但如果庫放在自己的定義的目錄下,gcc還是不能找到的,這種情況下可以用gcc -L來列出非標准庫的路徑。實際編程中這一工作是由pkg-config --libs完成的。
上面兩次提到pkg-config命令,各位可能就會有疑問了:難道pkg-config前知八百年,後知八百年,無所不能?非也,其實pkg-config也有自己的一套規則來提供關於所查詢庫的信息。
當要查詢指定庫(如gtk+-2.0庫)的信息時,我們要以gtk+-2.0為參數運行pkg-config命令(如pkg-config --libs --cflags gtk+-2.0)。此時,pkg-config會到默認目錄(如/usr/lib/pkgconfig目錄)以及PKG_CONFIG_PATH指定的目錄去找一個配置文件,該文件就記錄了所查詢的庫在該系統上信息。該配置文件的命名規則是:所查詢庫的名字加上後綴.pc。若要查詢gtk+-2.0的信息,則pkg-config會按上面所說的尋找gtk+-2.0.pc。如果找到,萬事大吉,直接根據找到的文件的內容顯式庫的信息。如果找不到以.pc為後綴的配置文件,則顯示出錯信息提示用戶繼續尋找。例如:
[leo@leo ~]$ pkg-config --libs --cflags gtkmm-2.0
Package gtkmm-2.0 was not found in the pkg-config search path.
Perhaps you should add the directory containing `gtkmm-2.0.pc'
to the PKG_CONFIG_PATH environment variable
No package 'gtkmm-2.0' found
這就有兩種可能:一是gtkmm-2.0.pc沒有放在/usr/lib/pkg-config下。二就是gtkmm-2.0根本就沒有裝。
對應的解決方法:第一種情況直接用find,locate等命令把gtkmm-2.0.pc找出來,把路徑加入環境變量PKG_CONFIG_PATH中,再運行命令pkg-config --libs --cflags gtkmm-2.0。第二種情況就只能安裝gtkmm-2.0庫了。
關pkg-config的更詳細的用法請參加pkg-config的manpage:)

如前所述,當顯式鏈接庫時,gcc會按自己的規則去尋找庫的名字,現在就來說說庫的命名規則。
系統中的庫分兩類,靜態庫和動態庫(關於動態庫和靜態庫的區別以及如何添加自己的庫,請參看我在blog上的另一篇文章)。靜態庫和動態庫在命名上的區別就是後綴名不同而已。動態庫以.so(意為shared object)結尾,而靜態庫一.a(意為archive)結尾。由於種種原因,鏈接時是優先鏈接動態庫的,如果不成功,則鏈接靜態庫。
除了有相區別的後綴外,動態和靜態庫都有相同的前綴lib,這樣動態庫就有形如libXX.so的形式,相應的,靜態庫的名字看起來會是這樣libXX.a。
比如,用-lm參數鏈接數學庫時,gcc就會去尋找libm.so或libm.a。

Copyright © Linux教程網 All Rights Reserved