本文詳細介紹了linux 下gcc頭檔案指定方法,以及搜尋路徑順序的問題。另外,還總結了,gcc動态連結的方法以及路徑指定,同樣也讨論了搜尋路徑的順序問題。本文包含了很多的例子,具有很強的操作性,希望讀者自己去走一遍。
一.#include <>與#include “”
#include <>直接到系統指定的某些目錄中去找某些頭檔案。
#include “”先到源檔案所在檔案夾去找,然後再到系統指定的某些目錄中去找某些頭檔案。
二.gcc指定頭檔案的三種情況:
1.會在預設情況下指定到/usr/include檔案夾(更深層次的是一個相對路徑,gcc可執行程式的路徑是/usr/bin/gcc,那麼它在實際工作時指定頭檔案頭徑是一種相對路徑方法,換算成絕對路徑就是加上/usr/include,如#include 就是包含/usr/include/stdio.h)
2.GCC還使用了-I指定路徑的方式,即
gcc -I 頭檔案所在檔案夾(絕對路徑或相對路徑均可) 源檔案
舉一個例子:
設目前路徑為/root/test,其結構如下:
include_test.c
include/include_test.h
有兩種方法通路到include_test.h。
1. include_test.c中#include “include/include_test.h”然後gcc include_test.c即可
2. include_test.c中#include 或者#include 然後gcc –I include include_test.c也可
3. 參數:-nostdinc使編譯器不再系統預設的頭檔案目錄裡面找頭檔案,一般和-I聯合使用,明确限定頭檔案的位置。
在編譯驅動子產品時,由于非凡的需求必須強制GCC不搜尋系統預設路徑,也就是不搜尋/usr/include要用參數-nostdinc,還要自己用-I參數來指定核心頭檔案路徑,這個時候必須在Makefile中指定。
頭檔案搜尋順序:
1.由參數-I指定的路徑(指定路徑有多個路徑時,按指定路徑的順序搜尋)
2.然後找gcc的環境變量 C_INCLUDE_PATH, CPLUS_INCLUDE_PATH, OBJC_INCLUDE_PATH
3.再找内定目錄
/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的話,那麼就是
prefix/include
prefix/xxx-xxx-xxx-gnulibc/include
prefix/lib/gcc-lib/xxxx-xxx-xxx-gnulibc/2.8.1/include
三.Linux指定動态庫路徑
衆所周知,Linux動态庫的預設搜尋路徑是/lib和/usr/lib。動态庫被建立後,一般都複制到這兩個目錄中。當程式執行時需要某動态庫, 并且該動态庫還未加載到記憶體中,則系統會自動到這兩個預設搜尋路徑中去查找相應的動态庫檔案,然後加載該檔案到記憶體中,這樣程式就可以使用該動态庫中的函 數,以及該動态庫的其它資源了。在Linux 中,動态庫的搜尋路徑除了預設的搜尋路徑外,還可以通過以下三種方法來指定。
1.在配置檔案/etc/ld.so.conf中指定動态庫搜尋路徑。
可以通過編輯配置檔案/etc/ld.so.conf來指定動态庫的搜尋路徑,該檔案中每行為一個動态庫搜尋路徑。每次編輯完該檔案後,都必須運作指令ldconfig使修改後的配置生效。
所有源檔案:
源檔案1: lib_test.c
#include
void prt()
{
printf(“You found me!!!/n”);
}
源檔案2: main.c
void prt();
int main()
prt();
return 0;
操作過程:
我們通過以下指令用源程式lib_test.c來建立動态庫 lib_test.so。
# gcc –o lib_test.o -c lib_test.c
# gcc -shared -fPIC -o lib_test.so lib_test.o
#
或者直接一條指令:
#gcc –shared –fPIC –o lib_test.so lib_test.c
注意:
-fPIC參數聲明連結庫的代碼段是可以共享的,
-shared參數聲明編譯為共享庫。請注意這次我們編譯的共享庫的名字叫做
lib_test.so,這也是Linux共享庫的一個命名的慣例了:字尾使用so,而名稱使用libxxxx格式。
接着通過以下指令編譯main.c,生成目标程式main.out。
# gcc -o main.out -L. –l_test main.c
請注意為什麼是-l_test?
然後把庫檔案移動到目錄/root/lib中。
# mkdir /root/lib
# mv lib_test.so /root/lib/ lib_test.so
最後編輯配置檔案/etc/ld.so.conf,在該檔案中追加一行/root/lib。
運作程式main.out:
# ./main.out
./main.out: error while loading shared libraries: lib_test.so: cannot open shared object file: No such file or directory
出錯了,系統未找到動态庫lib_test.so。找找原因,原來在編輯完配置檔案/etc/ld.so.conf後,沒有運作指令ldconfig,是以剛才的修改還未生效。我們運作ldconfig後再試試。
# ldconfig
You found me!!!
程式main.out運作成功,并且列印出正确結果。
2.通過環境變量LD_LIBRARY_PATH指定動态庫搜尋路徑。
通過設定環境變量LD_LIBRARY_PATH也可以指定動态庫搜尋路徑。當通過該環境變量指定多個動态庫搜尋路徑時,路徑之間用冒号”:”分隔。下面通過例2來說明本方法。
這次我們把上面得到的檔案lib_test.so移動到另一個地方去,如/root下面,然後設定環境變量LD_LIBRARY_PATH找到lib_test.so。設定環境變量方法如下:
# export LD_LIBRARY_PATH=/root
然後運作:
#./main.out
注意:設定環境變量LD_LIBRARY_PATH=/root是不行的,非得export才行。
3.在編譯目标代碼時指定該程式的動态庫搜尋路徑。
還可以在編譯目标代碼時指定程式的動态庫搜尋路徑。-Wl,表示後面的參數将傳給link程式ld(因為gcc可能會自動調用ld)。這裡通過gcc 的參數”-Wl,-rpath,”指定
這次我們還把上面得到的檔案lib_test.so移動到另一個地方去,如/root/test/lib下面,
因為我們需要在編譯目标代碼時指定可執行檔案的動态庫搜尋路徑,是以需要用gcc指令重新編譯源程式main.c(見程式2)來生成可執行檔案main.out。
# gcc -o main.out -L. –l_test -Wl,-rpath,/root/test/lib main.c
運作結果:
程式./main.out運作成功,輸出的結果正是main.c中的函數prt的運作結果。是以程式main.out搜尋到的動态庫是/root/test/lib/lib_test.so。
關于-Wl,rpath的使用方法我再舉一個例子,應該不難從中看出指定多個路徑的方法:
gcc -Wl,-rpath,/home/arc/test,-rpath,/lib/,-rpath,/usr/lib/,-rpath,/usr/local/lib test.c
以上介紹了三種指定動态庫搜尋路徑的方法,加上預設的動态庫搜尋路徑/lib和/usr/lib,共五種動态庫的搜尋路徑,那麼它們搜尋的先後順序是什麼呢?讀者可以用下面的方法來試驗一下:
(1) 用前面介紹的方法生成5個lib_test.so放在5個不同的檔案夾下面,要求每一個lib_test.so都唯一對應一個搜尋路徑,并注意main.out程式輸出的不同。
(2) 運作main.out,即可看出他是那個搜尋路徑下的,然後删除這個路徑下的lib_test.so,然後再運作。依此類推操作,即可推出搜尋順序。
可以得出動态庫的搜尋路徑搜尋的先後順序是:
1.編譯目标代碼時指定的動态庫搜尋路徑;
2.環境變量LD_LIBRARY_PATH指定的動态庫搜尋路徑;
3.配置檔案/etc/ld.so.conf中指定的動态庫搜尋路徑;
4.預設的動态庫搜尋路徑/lib;
5.預設的動态庫搜尋路徑/usr/lib。
在上述1、2、3指定動态庫搜尋路徑時,都可指定多個動态庫搜尋路徑,其搜尋的先後順序是按指定路徑的先後順序搜尋的。有興趣的讀者自己驗證。
PS:此文網上搜得,原始出處已經無法通路,故無法給出原文連結。