為什麼 /usr/include 中有多個標頭檔副本?
我一直在瀏覽我的 /usr/include 文件夾,試圖熟悉佈局,我注意到標頭檔有多個副本(至少按名稱,我實際上並沒有區分它們是否準確副本)在 /usr/include 的幾個子目錄中找到。對於標準 C 和 C++ 標頭檔以及 POSIX/LSB 標準標頭檔尤其如此。
一些範例包括(注意 ./ 指的是 /usr/include):
./asm-generic/unistd.h ./linux/unistd.h ./unistd.h ./x86_64-linux-gnu/sys/unistd.h ./x86_64-linux-gnu/bits/unistd.h ./x86_64-linux-gnu/asm/unistd.h ./stdlib.h ./x86_64-linux-gnu/bits/stdlib.h ./c++/7/stdlib.h ./c++/7/tr1/stdlib.h ./c++/7/cmath ./c++/7/ext/cmath ./c++/7/tr1/cmath ./asm-generic/termios.h ./linux/termios.h ./x86_64-linux-gnu/sys/termios.h ./x86_64-linux-gnu/bits/termios.h ./x86_64-linux-gnu/asm/termios.h ./termios.h ./linux/time.h ./time.h ./x86_64-linux-gnu/sys/time.h ./x86_64-linux-gnu/bits/time.h
為什麼是這樣?為什麼一些 C 標準標頭檔會出現在 C++ 位置?
我只安裝了一個編譯器(GCC 7)。
不,它們不是精確的副本。
如果您願意調查,您會發現頂層的文件
/usr/include
通常會有很多#ifdef
s 或其他條件,它們只會定義與體系結構無關的部分,並且會#include
在更深層次的體系結構特定目錄中定義其他內容層次結構。由於某些特定於體系結構的部分可能反過來依賴於某些與體系結構無關的部分,因此可能存在多個相互疊加的包含層。同樣,下面的文件
/usr/include/c++
將具有僅對 C++ 有意義的附加聲明,並#include
在適當的情況下為相應的 C 包含文件提供 s。遊戲的名稱是可維護性的重複數據刪除:目的是當 glibc 開發人員需要添加僅影響應用程序和 glibc 之間的 ABI 並且沒有特定於架構的部分的新內容時,理想情況下只需要添加一個包含文件樹中的位置,它將對所有使用 glibc 的硬體架構生效。或者說,當一個新的系統呼叫被添加到 Linux 核心時,會有一個添加它的地方,而不會干擾 *BSD 或 GNU Hurd 系統呼叫定義,例如。或者,如果您要將 glibc 移植到另一個硬體/核心架構,您會發現可以插入必要的核心 ABI 定義的地方,而不會干擾與架構無關的東西,而不是絕對必要的。
是的,這很複雜。
我沒有任何簡單的參考資料可供您參考,因為整個
/usr/include
佈局是 ISO C 和 POSIX 標準要求以及 GCC 和 glibc 項目做出的選擇的總和。我建議您記下您的架構三元組(
x86_64-linux-gnu
在您的情況下;可gcc -dumpmachine
通過 GCC 支持的任何架構獲得),然後研究編譯器的預設#include <...>
文件搜尋路徑。您可以通過以下方式查看搜尋路徑:
cpp -v /dev/null -o /dev/null
對於普通 Ccpp -x c++ -v /dev/null -o /dev/null
對於 C++我手頭沒有帶有 GCC 7 的系統,但對於 GCC 6,包含路徑的列表對於 C 如下所示:
... #include <...> search starts here: /usr/lib/gcc/x86_64-linux-gnu/6/include /usr/local/include /usr/lib/gcc/x86_64-linux-gnu/6/include-fixed /usr/include/x86_64-linux-gnu /usr/include End of search list. ...
…對於 C++ 來說就像這樣:
... #include <...> search starts here: /usr/include/c++/6 /usr/include/x86_64-linux-gnu/c++/6 /usr/include/c++/6/backward /usr/lib/gcc/x86_64-linux-gnu/6/include /usr/local/include /usr/lib/gcc/x86_64-linux-gnu/6/include-fixed /usr/include/x86_64-linux-gnu /usr/include End of search list. ...
如果該
/usr/local/include/<architecture triplet>
目錄存在,它將被添加到列表中,就在/usr/local/include
.因此,對於您自己的項目,如果您需要具有特定於體系結構的包含文件版本,您可以將它們
/usr/[local/]include/<architecture triplet>/
放在/usr/[local/]include/
. 如果沒有很好的理由,我不會碰任何路徑名包含編譯器主要版本號的包含目錄。如果你打算修改
glibc
,在開發者文件中找不到你需要的東西,你最好在開發郵件列表中glibc
尋求建議;更加複雜,因為它也可以在使用 GCC 以外的編譯器的架構上使用,因此可能沒有架構三元組約定作為標準。glibc``glibc