Linux標頭檔案和庫的搜尋路徑
本文轉自:https://blog.csdn.net/pwl999/article/details/78219374
1.1、glibc安裝時.so庫檔案和.h標頭檔案都安裝到什麼資料夾,gcc怎麼能正確的找到相應的資料夾?
當我們在build gcc時設定–prefix=/path/,則gcc安裝到/path/,gcc預設會在/path/lib/路徑下搜尋庫,在/path/include/路徑下搜尋標頭檔案。
例如,一般linux系統把gcc和glibc都安裝到/usr/目錄,所以gcc可執行檔案在/usr/bin目錄下,而glibc的庫檔案在/usr/lib目錄下,glibc的標頭檔案在/usr/include目錄下。
當然上述的關係並不是一定的,在安裝gcc和glibc的時候可以手工指定。可以使用命令“gcc -print-search-dirs”來檢視gcc庫的搜尋路徑:
可以使用以下幾種方法來更改gcc預設搜尋的庫路徑和標頭檔案路徑:
- (1)使用 “gcc –nostdlib –Lusrlibpath”來改變gcc的預設庫搜尋路徑,使用 “gcc –nostdinc –Iusrincpath”來改變gcc的預設標頭檔案搜尋路徑。
- (2)使用“gcc –Wl, –sysroot=” 來改變gcc的預設庫搜尋路徑。
- (3)更改gcc的specs檔案來自定義gcc的任何選項。
Specs是gcc的配置檔案。這種修改方法功能最強大,但是難度和風險也最大,因為gcc的spec檔案比較晦澀難懂,我也暫時不會修改,只是先給大家介紹有這種方法的存在。
使用“gcc –v“命令檢視gcc specs的路徑:
也有些安裝的gcc使用的是內建的spec,而沒有外接的spec檔案:
對於內建的spec,可以使用命令“gcc -dumpspecs “檢視具體的spec內容:
也可以使用“gcc -specs= “來指定gcc的spec檔案。
- (4) gcc預設的配置是否在build時由configure命令傳入的?
使用“gcc –v“命令可以檢視gcc的configure值,關於configure選項的說明在gcc-4.1.0\gcc\doc\install.texi檔案中有詳細描述。
1.2、程式連結時,連結庫的搜尋路徑有哪些?
連結時,庫的搜尋路徑的配置有以下方法:(具體使用可參見例項一章的描述)
- (1) 使用 “gcc –Llibpath –llibname”指定連結庫搜尋路徑。
- (2)使用環境變數“LIBRARY_PATH” 指定連結庫搜尋路徑。
- (3)使用ld連線指令碼中的 “SEARCH_DIR” 指定連結庫搜尋路徑。
1.3、程式執行時,動態連結庫的搜尋路徑有哪些?
連結時,庫的搜尋路徑的配置有以下方法:(具體使用可參見例項一章的描述)
- (1) 編譯時使用 “gcc –Wl,-rpath”指定執行時動態連結庫的搜尋路徑,硬編碼進ELF檔案 “RPATH”選項。
- (2) 編譯時使用環境變數 “LD_RUN_PATH”指定執行時動態連結庫的搜尋路徑,硬編碼進ELF檔案 “RPATH”選項。
- (3)使用環境變數 “LD_LIBRARY_PATH”指定執行時動態連結庫的搜尋路徑。
- (4)使用配置檔案“/etc/ld.so.conf”指定執行時動態連結庫的搜尋路徑。
- (5)使用執行時動態連結庫的預設搜尋路徑“/lib、/usr/lib”。
1.4、程式編譯時,標頭檔案的搜尋路徑有哪些?
編譯時,標頭檔案的搜尋路徑的配置有以下方法:(具體使用可參見例項一章的描述)
- (1) 編譯時使用“gcc –I incpath”指定標頭檔案搜尋路徑。
- (2) 編譯時使用環境變數 “C_INCLUDE_PATH”指定標頭檔案搜尋路徑。
- (3) 編譯時使用gcc的預設標頭檔案搜尋路徑。
常用標頭檔案目錄的說明:
- (1)、/usr/src/linux/include:
/usr/src/linux/是核心原始碼路徑,/usr/src/linux/include包含的是核心標頭檔案,一般在編譯模組時使用。
- (2)、/usr/include
/usr/include路徑主要是glibc的標頭檔案,是用來編譯使用者態檔案的。但是/usr/include其中也包含核心標頭檔案所需的linux/、asm/資料夾,但是這兩個資料夾主要是用來做一些相容性用的,真正用到核心標頭檔案還是要用/usr/src/linux/include。
1.5、製作交叉編譯器時,各項搜尋路徑的配置?
製作交叉編譯器時,需要關注相關四種路徑的配置:編譯時連結的庫檔案路徑、編譯時用到的標頭檔案路徑、編譯時用到的二進位制工具路徑、編譯時指定的動態載入器的名稱路徑。
- (1)、編譯時連結的庫檔案路徑:
如果不指定,應該是和安裝路徑相關的預設路徑。如果要指定,可以在編譯binutils中ld的時候,使用“LIB_PATH”選項指定:
- (2)、編譯時用到的標頭檔案路徑:
- (3)、編譯時用到的二進位制工具路徑:
預設二進位制工具的路徑,可以使用以下命令檢視:
使用指定的二進位制工具,可以使用“gcc -B”選項:
- (4)、編譯時指定的動態載入器的路徑和名稱:
硬編碼進elf的動態載入器路徑和名稱,由gcc spec檔案指定:
2、例項操作
生成兩個.c檔案:
cat >say.c<<eof
#include "stdio.h"
void say()
{
printf("Say!");
}
Eof
cat >test.c <<eof
#include "stdio.h"
void say();
main(){
say();
}
eof
2.1、連結時庫的搜尋路徑
將say.c編譯成libsay.so,再在編譯test.c時來連結libsay.so,用以測試gcc連結時庫的搜尋路徑。
- (1)使用 “gcc –Llibpath –llibname”指定連結庫搜尋路徑:
-
(2)使用環境變數“LIBRARY_PATH” 指定連結庫搜尋路徑:
-
(3)使用ld連線指令碼中的 “SEARCH_DIR” 指定連結庫搜尋路徑:
使用“ld –verbose”命令檢視gcc的預設連結指令碼中SEARCH_DIR引數,當然你也可以使用 “ld –Txxx.lds”來指定連結指令碼。
拷貝libsay.so到SEARCH_DIR指定路徑,並連結測試:
2.2、執行時動態載入庫的搜尋位置
- (1) 編譯時使用 “gcc –Wl,-rpath”指定執行時動態連結庫的搜尋路徑,硬編碼進ELF檔案 “RPATH”選項:
使用readelf檔案檢視elf檔案中的硬編碼執行時庫搜尋路徑:
- (2) 編譯時使用環境變數 “LD_RUN_PATH”指定執行時動態連結庫的搜尋路徑,硬編碼進ELF檔案 “RPATH”選項:
- (3)使用環境變數 “LD_LIBRARY_PATH”指定執行時動態連結庫的搜尋路徑:
-
(4)使用配置檔案“/etc/ld.so.conf”指定執行時動態連結庫的搜尋路徑:
-
(5)使用執行時動態連結庫的預設搜尋路徑“/lib、/usr/lib”:
生成一個.c檔案和一個.h檔案:
cat >test1.c <<eof
> #include "test1.h"
> void main()
> {
> printf("Test .h include!\n");
> }
> eof
cat >test1.h <<eof
> #include "stdio.h"
> eof
2.3、程式編譯時,標頭檔案的搜尋路徑有哪些?
-
(1) 編譯時使用“gcc –I incpath”指定標頭檔案搜尋路徑:
-
(2) 編譯時使用環境變數 “C_INCLUDE_PATH”指定標頭檔案搜尋路徑:
- (3) 編譯時使用gcc的預設標頭檔案搜尋路徑:
gcc的預設標頭檔案搜尋路徑設定方法還沒弄明白。但是可以使用以下命令檢視:
使用預設路徑來編譯: