1. 程式人生 > >如何使用新的glibc來編譯自己的程序

如何使用新的glibc來編譯自己的程序

環境 software ins 執行 nsh path gcc x86-64 .so

http://www.sysnote.org/2015/08/25/use-new-glibc/

通常情況下我們都是直接使用glibc提供的一些庫函數,但是某些特殊的情況,比如要修改glibc的一些代碼或者加入glibc的一些編譯選項或者要使用其他版本的glibc,我們就需要重新編譯glibc。
編譯glibc時特別要註意,不能去替換系統自帶的glibc,因為glibc作為linux系統的核心庫,很多底層模塊都依賴它,稍有不慎就會把系統搞掛掉。因此我們編譯glibc時最好要指定prefix=/new/path,
這樣編譯完了之後make install的時候就不會去覆蓋系統自帶的版本。那麽問題來了,編譯好glibc後,如何讓我們的程序使用這個新編譯的glibc呢?下面就以我們實際編譯glibc的步驟來說明。

1.下載glibc源代碼

http://www.gnu.org/software/libc/,在官網上有各個glibc的發行版,這裏我選用的是glibc-2.17

2.解壓glibc到當前目錄

1
root@xxx:~# tar zxvf glibc-2.17.tar.gz

3.創建glibc的build目錄

不能在glibc-2.17源碼目錄下./configure,會報錯“configure: error: you must configure in a separate build directory”

1
root@xxx:~# mkdir -p build/glibc-build

4.configure glibc

這裏我指定了自己需要的一些編譯選項,並且指定prefix目錄

1
root@xxx:~/build/glibc-build# /root/glibc-2.17/configure CFLAGS="-fno-builtin-strlen -ggdb -O2" FEATURES="preserve-libs nostrip splitdebug" --prefix=/root/build/glibc-build

5.編譯安裝

1
2
root@xxx:~/build/glibc-build# make -j10
root@xxx:~/build/glibc-build# make install

可以看到glibc相關的庫都在glibc-build目錄下了

1
2
3
4
5
6
7
8
9
10
11
root@xxx:~/build/glibc-build# ls lib
audit libanl.so libcidn.so libdl.a libm.so.6 libnss_db.so.2 libnss_nis-2.17.so libpthread.so librt.so.1 Scrt1.o
crt1.o libanl.so.1 libcidn.so.1 libdl.so libnsl-2.17.so libnss_dns-2.17.so libnss_nisplus-2.17.so libpthread.so.0 libSegFault.so
crti.o libBrokenLocale-2.17.so libc_nonshared.a libdl.so.2 libnsl.a libnss_dns.so libnss_nisplus.so libresolv-2.17.so libthread_db-1.0.so
crtn.o libBrokenLocale.a libcrypt-2.17.so libg.a libnsl.so libnss_dns.so.2 libnss_nisplus.so.2 libresolv.a libthread_db.so
gconv libBrokenLocale.so libcrypt.a libieee.a libnsl.so.1 libnss_files-2.17.so libnss_nis.so libresolv.so libthread_db.so.1
gcrt1.o libBrokenLocale.so.1 libcrypt.so libm-2.17.so libnss_compat-2.17.so libnss_files.so libnss_nis.so.2 libresolv.so.2 libutil-2.17.so
ld-2.17.so libbsd-compat.a libcrypt.so.1 libm.a libnss_compat.so libnss_files.so.2 libpcprofile.so librpcsvc.a libutil.a
ld-linux-x86-64.so.2 libc-2.17.so libc.so libmcheck.a libnss_compat.so.2 libnss_hesiod-2.17.so libpthread-2.17.so librt-2.17.so libutil.so
libanl-2.17.so libc.a libc.so.6 libmemusage.so libnss_db-2.17.so libnss_hesiod.so libpthread.a librt.a libutil.so.1
libanl.a libcidn-2.17.so libdl-2.17.so libm.so libnss_db.so libnss_hesiod.so.2 libpthread_nonshared.a librt.so Mcrt1.o

6.使用新的glibc來編譯程序,這裏我編譯的是valgrind

1
2
3
4
root@xxx:~# tar jxvf valgrind-3.10.1.tar.bz2
root@xxx:~# mkdir -p build/valgrind-build
root@xxx:~# cd valgrind-3.10.1
root@xxx:~/valgrind-3.10.1# ./configure CFLAGS="-I/root/build/glibc-build/include" LDFLAGS="-L/home/nbs/glibc/lib -Wl,--rpath=/root/build/glibc-build/lib -Wl,--dynamic-linker=/root/build/glibc-build/lib/ld-linux-x86-64.so.2" --prefix=/root/build/valgrind-build

下面對configure的選項進行說明:
CFLAGS=”-I/root/build/glibc-build/include” 這個是指定頭文件的查找路徑,去新編譯的glibc裏查找
LDFLAGS: Makefile的鏈接選項,其中
-L: 告訴鏈接器先從指定的路徑查找庫來鏈接,如果沒找到,再從默認的地方找。編譯時的-L選項並不影響環境變量LD_LIBRARY_PATH,-L只是指定了程序編譯連接時庫的路徑,並不影響程序執行時庫的路徑,系統還是會到默認路徑下查找該程序所需要的庫,如果找不到,還是會報錯,類似cannot open shared object file。
可以設定LD_LIBRARY_PATH來讓程序在運行時查找除默認路徑(默認是先搜索/lib和/usr/lib這兩個目錄,然後按照/etc/ld.so.conf裏面的配置搜索絕對路徑)之外的其他路徑,不過LD_LIBRARY_PATH的設定作用是全局的,建議使用gcc的的-R或-rpath選項來在編譯時就指定庫的查找路徑,並且該庫的路徑信息保存在可執行文件中,運行時它會直接到該路徑查找庫,避免了使用LD_LIBRARY_PATH環境變量查找。
因此我在上面指定了-Wl,–rpath=/root/build/glibc-build/lib,說明一下,-Wl,option是將選項傳給鏈接器

另外,也需要使用新編譯的鏈接器,使用–dynamic-linker指定鏈接器
然後再使用make && make install就可以編譯完成,完成後,可以看到安裝的東西都在/root/build/valgrind-build/下。

如何使用新的glibc來編譯自己的程序