1. 程式人生 > >Linux標頭檔案和庫的搜尋路徑

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庫的搜尋路徑:

1

可以使用以下幾種方法來更改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的路徑:

2

也有些安裝的gcc使用的是內建的spec,而沒有外接的spec檔案:

3

對於內建的spec,可以使用命令“gcc -dumpspecs “檢視具體的spec內容:

4

也可以使用“gcc -specs= “來指定gcc的spec檔案。

  • (4) gcc預設的配置是否在build時由configure命令傳入的?

使用“gcc –v“命令可以檢視gcc的configure值,關於configure選項的說明在gcc-4.1.0\gcc\doc\install.texi檔案中有詳細描述。

5

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”選項指定:

6

  • (2)、編譯時用到的標頭檔案路徑:
  • (3)、編譯時用到的二進位制工具路徑:

預設二進位制工具的路徑,可以使用以下命令檢視:

7

使用指定的二進位制工具,可以使用“gcc -B”選項:

  • (4)、編譯時指定的動態載入器的路徑和名稱:

硬編碼進elf的動態載入器路徑和名稱,由gcc spec檔案指定:

8

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連結時庫的搜尋路徑。

9

  • (1)使用 “gcc –Llibpath –llibname”指定連結庫搜尋路徑:

10

  • (2)使用環境變數“LIBRARY_PATH” 指定連結庫搜尋路徑:

    11

  • (3)使用ld連線指令碼中的 “SEARCH_DIR” 指定連結庫搜尋路徑:

使用“ld –verbose”命令檢視gcc的預設連結指令碼中SEARCH_DIR引數,當然你也可以使用 “ld –Txxx.lds”來指定連結指令碼。

12

拷貝libsay.so到SEARCH_DIR指定路徑,並連結測試:

13

2.2、執行時動態載入庫的搜尋位置

  • (1) 編譯時使用 “gcc –Wl,-rpath”指定執行時動態連結庫的搜尋路徑,硬編碼進ELF檔案 “RPATH”選項:

這裡寫圖片描述

使用readelf檔案檢視elf檔案中的硬編碼執行時庫搜尋路徑:

15

  • (2) 編譯時使用環境變數 “LD_RUN_PATH”指定執行時動態連結庫的搜尋路徑,硬編碼進ELF檔案 “RPATH”選項:

16

  • (3)使用環境變數 “LD_LIBRARY_PATH”指定執行時動態連結庫的搜尋路徑:

17

  • (4)使用配置檔案“/etc/ld.so.conf”指定執行時動態連結庫的搜尋路徑:

    18

  • (5)使用執行時動態連結庫的預設搜尋路徑“/lib、/usr/lib”:

19

生成一個.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”指定標頭檔案搜尋路徑:

    20

  • (2) 編譯時使用環境變數 “C_INCLUDE_PATH”指定標頭檔案搜尋路徑:

21

  • (3) 編譯時使用gcc的預設標頭檔案搜尋路徑:

gcc的預設標頭檔案搜尋路徑設定方法還沒弄明白。但是可以使用以下命令檢視:

22

使用預設路徑來編譯:

23