Linux操作系統的頭文件和庫文件搜索路徑

一、 頭文件

1 “”中的頭文件,在源文件當前目錄查找

2 -I 中指定目錄 -I可以在CFLAG中指定

3 gcc的環境變量 C_INCLUDE_PATH, CPLUS_INCLUDE_PATH, OBJC_INCLUDE_PATH

4 編譯器預設路徑、內定目錄:

/usr/include

/usr/local/include

/usr/lib/gcc-lib/i386-linux/2.95.2/include

/usr/lib/gcc-lib/i386-linux/2.95.2/../../../../include/g -3

/usr/lib/gcc-lib/i386-linux/2.95.2/../../../../i386-linux/include

但是假如裝gcc的時候,有給定的prefix的話,那麼就是

/usr/include

prefix/include

prefix/xxx-xxx-xxx-gnulibc/include

prefix/lib/gcc-lib/xxxx-xxx-xxx-gnulibc/2.8.1/include

此外還可用pkg-config 程序,用來在編譯腳本中向編譯器傳遞頭文件包含路徑或庫文件路徑。 Linux下那麼多庫,在./configure時時怎麼判斷它們存不存在的,難道是靠遞歸搜索?pkg-config這個命令和/*/lib/pkgconfig下的一些.pc文件纔是主角。每個.pc文件定義了庫的名字、路徑、編譯選項等,比如glib-2.0.pc文件:

prefix=/usr

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

glib_genmarshal=glib-genmarshal 
gobject_query=gobject-query 
glib_mkenums=glib-mkenums

Name: Glib 
Description: C Utilitiy Library 
Version: 2.14.4 
Libs: -L${libdir} -lglib-2.0 
Cflags: -I${includedir}/glib-2.0 -I${libdir}/glib-2.0/include

--cflags 參數可以給出在編譯時所需要的選項,而 --libs 參數可以給出連接時的選項

configure到某個庫的時候,pkg-config命令會首先去環境變量PKG_CONFIG_PATH定義好的路徑下搜索庫名字對應的.pc文件(庫名加.pc),找到了就行了,等會兒make的時候就可以通過正則表達式取出libs和cflags的值來使用。

如configure文件中有:

pkg_XLIB_CFLAGS='$PKG_CONFIG --cflags "x11" 2>/dev/null'(還是`***`)(結果是-I的形式)

(x11表示libx11庫),這些參數配置結束後寫入Makefile。

配置 pkgconfig

PKG_CONFIG_PATH 的缺省設置是 /lib/pkgconfig, /usr/lib/pkgconfig 和 /usr/local/lib/pkgconfig. 這些設置都是硬編碼的,所以不用另外設置它們。

二、 庫文件

Ø 編譯的時候動態庫的搜索路徑:

1 gcc會去找-L 指定的路徑和 -l指定的庫(指定庫的路徑)

2 由'-rpath-link'選項指定的搜索路徑 在LDFLAGS中gcc 的參數"-Wl,-rpath-link,-Wl"指定。 '-rpath-link'比‘-L’多一功能,指定的目錄還可用於搜索依賴庫。

3 由'-rpath'指定的搜索路徑. '-rpath'跟'-rpath_link'的不同之處在於,由'-rpath'指定的路徑被包含在可執行文件中,並在運行時使用, 而'-rpath-link'選項僅僅在連接時起作用.'-rpath'比'-rpath-link'多一功能,指定路徑編譯進程序,當程序運行時,首先從這些目錄中尋找庫。

4 再找內定目錄 /lib、 /usr/lib、 /usr/local/lib 這是當初compile gcc時寫在程序內的

  '-rpath'跟'-rpath_link'用來指定依賴庫的路徑

Ø 對於交叉編譯,鏈接時庫搜索路徑及優先順序如下:

1 -rpath-link 指定

2 -rpath 指定

3 –L 指定

4 連接器的默認鏈接目錄,通常在交叉編譯器目錄下。

Ø 如何指定-rpath-link :在configure之前設置LDFLAGS,如

export LDFLAGS = " -Wl,-rpath-link -Wl,目錄/lib"(-Wl表示用於連接器)

在configure文件中也有:

pkg_XLIB_CFLAGS='$PKG_CONFIG --libs "x11" 2>/dev/null'(還是`***`)

本人註解:

man gcc:

-Wl,option

Pass option as an option to the linker. If option contains commas, it is split into multiple options at the commas. You can use this syntax to pass an argument to the option. For example, -Wl,-Map,output.map' passes -Map output.map' to the linker. When u> sing the GNU linker, you can also get the same effect with `-Wl,-Map=output.map'.

-Wl指示參數option是傳給ld的,而option如果包含逗號,則option會以逗號切割爲多個參數傳遞給ld

gcc -Wl,aaa,bbb,ccc

最終會變成:

ld aaa bbb ccc

你也可以這樣:

gcc -Wl,aaa, -Wl,bbb -Wl,ccc

Ø 運行時動態庫的搜索路徑

1Ø進程啓動時加載

首先  LD_PRELOAD

1、 -rpath指定目錄(在編譯目標代碼時指定程序的動態庫搜索路徑"-Wl,-rpath,"指定)

2、 通過環境變量LD_LIBRARY_PATH指定動態庫搜索路徑(當通過該環境變量指定多個動態庫搜索路徑時,路徑之間用冒號":"分隔)

3、 /etc/ld.so.cache中指定的動態庫搜索路徑, 由ldconfig讀取配置文件/etc/ld.so.conf 生成。

4、 默認的動態庫搜索路徑/lib

5、 默認的動態庫搜索路徑/usr/lib

2Ø 運行時加載 dlopen()

第一個參數:指定共享庫的名稱,將會在下面位置查找指定的共享庫。 
-/開頭,絕對路徑,名字必須完全匹配。

-環境變量LD_LIBRARY_PATH列出的用分號間隔的所有目錄。 
-文件/etc/ld.so.cache中找到的庫的列表,用ldconfig維護。 
-目錄usr/lib。 
-目錄/lib。 
-當前目錄。 
第二個參數:指定如何打開共享庫。  
其中flag有:RTLD_LAZY RTLD_NOW RTLD_GLOBAL,其含義分別爲: 
RTLD_LAZY:在dlopen返回前,對於動態庫中存在的未定義的變量(如外部變量extern,也可以是函數)不執行解析,就是不解析這個變量的地址。 
RTLD_NOW:與上面不同,他需要在dlopen返回前,解析出每個未定義變量的地址,如果解析不出來,在dlopen會返回NULL,錯誤爲: 
: undefined symbol: xxxx....... 
RTLD_GLOBAL:它的含義是使得庫中的解析的定義變量在隨後的隨後其它的鏈接庫中變得可以使用。


轉載子Linux操作系統的頭文件和庫文件搜索路徑紅色部分爲本人添加註釋。


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