[gcc 官方網(wǎng)站](https://gcc.gnu.org/)
GCC(GNU Compiler Collection,GNU編譯器套件),是由 GNU 開發(fā)的編程語言編譯器。它是以 GPL(General Public License)許可證所發(fā)行的自由軟件,也是 GNU 計劃的關(guān)鍵部分(GPU 是一個軟件工程項目,是 GNU's Not Unix 的縮寫)。
GCC 原本作為 GNU 操作系統(tǒng)的官方編譯器,現(xiàn)已被大多數(shù)類 Unix 操作系統(tǒng)(如Linux、BSD、Mac OS X等)采納為標(biāo)準(zhǔn)的編譯器,GCC 同樣適用于微軟的Windows。GCC 是自由軟件過程發(fā)展中的著名例子,由自由軟件基金會以 GPL 協(xié)議發(fā)布。
[glibc 官方網(wǎng)站](
https://www.gnu.org/software/libc/)
glibc 是 gnu 發(fā)布的 libc 庫,即 c 運行庫。glibc 是 linux 系統(tǒng)中最底層的 api,幾乎其他任何的運行庫都會依賴 glibc. glibc 除了封裝 linux 操作系統(tǒng)所提供的系統(tǒng)服務(wù)外,它本身提供了許多其它一些必要服務(wù)的實現(xiàn),主要有:
string:字符串處理
signal:信號處理
dlfcn:管理共享庫的動態(tài)加載
direct:文件目錄操作
elf:共享庫的動態(tài)加載器,即 interpreter
iconv:不同字符集的編碼轉(zhuǎn)換
inet:socket 接口的實現(xiàn)
intl:gettext 的實現(xiàn)
io
linuxthreads
locale:本地化
login:虛擬終端設(shè)備的管理,及系統(tǒng)的安全訪問
malloc:動態(tài)內(nèi)存管理的分配與管理
nis
stdlib
math
首先,gcc 是編譯器,基本上 linux 下所有程序(包括內(nèi)核)都是 gcc 編譯的,libc 也是。但 gcc 和 libc 又是相互依賴的,什么意思呢?就是在編譯 c/cpp 代碼時,既需要 gcc,也需要 libc.
截止2021年8月,最新版本已經(jīng)到 gcc11.2 了。
截止2021年8月,最新版本已經(jīng)到 glibc2.34 了,歷史版本有 glibc2.29、2.30、2.31、2.32、2.33 等。
方法1:
/lib/x86_64-linux-gnu/libc.so.6
為什么這個庫可以直接運行呢?原來是在 libc 的代碼中有一點小手腳:
void__libc_main (void) { __libc_print_version (); _exit (0); }
方法2:
ldd 命令也是 glibc 提供的,所以也能查看 glibc 版本:
ldd --version
strings /lib/x86_64-linux-gnu/libc.so.6 | grep GLIBC
`objdump -p test_gcc.so`,其他類似命令還有 `nm` 和 `readelf`
方法1:
`ldd test_gcc.so`
方法2:
`objdump -x test_gcc.so | grep NEEDED`
`gcc --print-file-name=libz.so.1`
`echo | gcc -v -x c -E -`
`objdump -T test_gcc.so | grep GLIBC_2.23`
`nm test_gcc.so | grep memcpy -w``objdump -T /lib/x86_64-linux-gnu/libc.so.6 | grep memcpy`
`export CPLUS_INCLUDE_PATH=/opt/compiler/gcc-8.2/x86_64-custom-linux-gnu/include/c++/8.2.0:/usr/include/x86_64-linux-gnu/``export C_INCLUDE_PATH=......`
指定正確的 ldd 路徑,也就是對應(yīng)具體的 glibc 版本(非常重要)。
方法1:
先查看:`echo $LD_LIBRARY_PATH`,可通過該環(huán)境變量直接設(shè)置。
或者,`gcc --print-search-dirs`
方法2:使用動態(tài)庫管理命令 ldconfig
`ldconfig -v`: 查看所有動態(tài)鏈接庫
`vim /etc/ld.so.conf`,顯示 `include /etc/ld.so.conf.d/*.conf`,然后`cd /etc/ld.so.conf.d`
修改完之后,要重新運行下 `ldconfig`
解釋:
linux 下的共享庫機制采用了類似于高速緩存的機制,將庫信息保存在`/etc/ld.so.cache`里邊。
程序連接的時候首先從這個文件里邊查找,然后再到`ld.so.conf`的路徑里邊去詳細(xì)找。
這就是為什么修改了`ld.so.conf`要重新運行一下`ldconfig`的原因
`objdump -T /usr/lib/gcc/x86_64-linux-gnu/5/libstdc++.so | grep GLIBCXX`
1. 優(yōu)先搜索`-I`指定的路徑2. 查找GCC的環(huán)境變量`C_INCLUDE_PATH`/`CPLUS_INCLUDE_PATH`/`OBJC_INCLUDE_PATH`指定的路徑3. 查找默認(rèn)的搜索路徑`/usr/include`、`/usr/local/include`
gcc在編譯時按照如下順序?qū)ふ宜枰膸煳募?/p>
1. gcc會去找`-L`指定的目錄
2. 再找gcc的環(huán)境變量`LIBRARY_PATH`
3. 再找內(nèi)定目錄
/lib和/lib64
/usr/lib 和/usr/lib64
/usr/local/lib和/usr/local/lib64
這是當(dāng)初 compile gcc 時寫在程序內(nèi)的。
這里有兩個問題:
默認(rèn)情況下,gcc編譯時只會查找相應(yīng)的頭文件,而不會連接具體的lib。也就是說只要include設(shè)置完全,就可以編譯通過。它沒有進一步檢查include中的類和函數(shù)有沒有實現(xiàn),而是在運行時才開始查找。所以就會經(jīng)常發(fā)生編譯可以通過,但運行時卻無法運行,因為在運行時它找不到相關(guān)類或者函數(shù)的實現(xiàn)。
這時,使用`-Wl`,`--no-undefined`參數(shù),如果使用了 include 文件,鏈接器卻找不到相應(yīng)的實現(xiàn),就會產(chǎn)生錯誤提示。
編譯時默認(rèn)不查找當(dāng)前目錄,需要使用`-L ./`指定,例如
運行時動態(tài)庫的搜索路徑的先后順序是:
1. 編譯目標(biāo)代碼時指定的動態(tài)庫搜索路徑;這是通過gcc的參數(shù)`-Wl,-rpath=`指定。當(dāng)指定多個動態(tài)庫搜索路徑時,路徑之間用冒號 :分隔
2. 環(huán)境變量`LD_LIBRARY_PATH`指定的動態(tài)庫搜索路徑
3. 配置文件`/etc/ld.so.conf`中指定的動態(tài)庫搜索路徑
4. 默認(rèn)的動態(tài)庫搜索路徑,如:`/lib`, `/usr/lib`
注意:
1. 動態(tài)庫搜尋路徑并不包括當(dāng)前目錄,所以當(dāng)即使可執(zhí)行文件和其所需的so文件在同一文件夾,也會出現(xiàn)找不到問題
2. 一般不推薦直接修改環(huán)境變量,而是修改`/etc/ld.so.conf`,將相應(yīng)的路徑添加上,然后`ldconfig`一下就好
3. ldconfig做的這些東西都與運行程序時有關(guān),跟編譯時一點關(guān)系都沒有,編譯的時候還是該加`-L`就得加,不要混淆了
4. 往`/lib`和`/usr/lib`里面加 `lib`,是不用修改`/etc/ld.so.conf`的,但是完了之后要調(diào)一下`ldconfig`(很重要),不然這個`lib`會找不到。而往其他目錄加`lib`,需要修改`/etc/ld.so.conf`,并且要`ldconfig`一下。
從官網(wǎng)下載,解壓,如 ./glibc-2.21
cd glibc-2.21
mkdir build
mkdir /opt/glibc-2.21
cd build
../configure --prefix=/opt/glibc-2.21
apt-get install gawk
make
需要解決一些編譯告警或錯誤問題
報錯(解決):./stdlib/setenv.c +270
報錯(未解決):
../sysdeps/x86_64/multiarch/strstr.c:47:30
未完待續(xù)。。。
聯(lián)系客服