Compiling

針對定制的 GLIBC 編譯 GCC

  • February 14, 2020

我試圖針對定制的 GLIBC 2.30 編譯 GCC 9.2。我在非標準位置安裝了 GLIBC。然後我按照以下步驟編譯 GCC:

sfinix@multivac:~$ GLIBCDIR=/home/sfinix/programming/repos/glibc/glibc-install/
sfinix@multivac:~$ export LDFLAGS="-Wl,-q"
sfinix@multivac:~$ CFLAGS="-L "${GLIBCDIR}/lib" -I "${GLIBCDIR}/include" -Wl,--rpath="${GLIBCDIR}/lib" -Wl,--dynamic-linker="${GLIBCDIR}/lib/ld-linux-x86-64.so.2""
sfinix@multivac:~$ cd ${GCC_BUILD_DIR}
sfinix@multivac:~$ make -j 4 CFLAGS="${CFLAGS}" CXXFLAGS="${CFLAGS}"

編譯成功,但問題是 GCC 仍在拾取舊庫:

sfinix@multivac:~$ ldd programming/repos/gcc/gcc-install/bin/gcc-9.2
       linux-vdso.so.1 (0x00007ffc3b7cb000)
       libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f177772f000)
       libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f177733e000)
       /lib64/ld-linux-x86-64.so.2 (0x00007f1777acd000)

輸出readelf -d programming/repos/gcc/gcc-install/bin/gcc-9.2

Dynamic section at offset 0x113dd8 contains 27 entries:
 Tag        Type                         Name/Value
0x0000000000000001 (NEEDED)             Shared library: [libm.so.6]
0x0000000000000001 (NEEDED)             Shared library: [libc.so.6]
0x0000000000000001 (NEEDED)             Shared library: [ld-linux-x86-64.so.2]
0x000000000000000c (INIT)               0x402a80
0x000000000000000d (FINI)               0x488440
0x0000000000000019 (INIT_ARRAY)         0x712de8
0x000000000000001b (INIT_ARRAYSZ)       48 (bytes)
0x000000000000001a (FINI_ARRAY)         0x712e18
0x000000000000001c (FINI_ARRAYSZ)       8 (bytes)
0x0000000000000004 (HASH)               0x4002b0
0x000000006ffffef5 (GNU_HASH)           0x400728
0x0000000000000005 (STRTAB)             0x4015f0
0x0000000000000006 (SYMTAB)             0x400798
0x000000000000000a (STRSZ)              1373 (bytes)
0x000000000000000b (SYMENT)             24 (bytes)
0x0000000000000015 (DEBUG)              0x0
0x0000000000000003 (PLTGOT)             0x714000
0x0000000000000002 (PLTRELSZ)           3264 (bytes)
0x0000000000000014 (PLTREL)             RELA
0x0000000000000017 (JMPREL)             0x401dc0
0x0000000000000007 (RELA)               0x401d00
0x0000000000000008 (RELASZ)             192 (bytes)
0x0000000000000009 (RELAENT)            24 (bytes)
0x000000006ffffffe (VERNEED)            0x401c80
0x000000006fffffff (VERNEEDNUM)         2
0x000000006ffffff0 (VERSYM)             0x401b4e
0x0000000000000000 (NULL)               0x0

雖然這種方法適用於其他程序,但我正在編譯自己進行測試:

sfinix@multivac:~$ GLIBDIR=/home/sfinix/programming/repos/glibc/glibc-install/
sfinix@multivac:~$ vim test.c
sfinix@multivac:~$ CFLAGS="-L ${GLIBDIR}/lib -I ${GLIBDIR}/include -Wl,--rpath=${GLIBDIR}/lib -Wl,--dynamic-linker=${GLIBDIR}/lib/ld-linux-x86-64.so.2"
sfinix@multivac:~$ gcc -Wall -g ${CFLAGS} test.c -o run
sfinix@multivac:~$ ldd run
       linux-vdso.so.1 (0x00007ffd616d5000)
       libc.so.6 => /home/sfinix/programming/repos/glibc/glibc-install//lib/libc.so.6 (0x00007f5fcdc6e000)
       /home/sfinix/programming/repos/glibc/glibc-install//lib/ld-linux-x86-64.so.2 => /lib64/ld-linux-x86-64.so.2 (0x00007f5fce22a000)

我錯過了什麼?如何針對自定義 GLIBC 編譯 GCC?如何傳遞編譯器和連結器標誌?

根據GNU 建構系統中的Autoconf 手冊,編譯器/連結器標誌/選項通過配置腳本傳遞。所以就我而言,我應該通過以下方式配置、編譯和安裝:

$ GLIBCDIR=/home/sfinix/programming/repos/glibc/glibc-install/
$ LDFLAGS="-Wl,-q"
$ CFLAGS="-L ${GLIBCDIR}/lib -I ${GLIBCDIR}/include -Wl,--rpath=${GLIBCDIR}/lib -Wl,--dynamic-linker=${GLIBCDIR}/lib/ld-linux-x86-64.so.2"
$ mkdir ~/gcc-build
$ cd ~/gcc-build'
$ ~/gcc-src/configure --prefix=~/gcc-install CFLAGS=${CFLAGS} CXXFLAGS=${CFLAGS} LDFLAGS=${LDFLAGS}
$ make && make install

在配置腳本中,我只傳遞了與所問問題相關的變數/選項。您可能希望根據您的特定需求傳遞更多選項。您可以通過執行查看所有選項和接受的變數~/gcc-src/configure --help。您還可以通過環境變數傳遞標誌,但您必須在執行配置腳本之前設置它們。

按要求回答問題。

在沒有看到的Makefile情況下,無法說出最終連結步驟中使用了哪些變數(如果有)。CFLAGS並且LDFLAGS是廣泛支持的約定,但不是必需的。OP 在評論中告訴我們這Makefile是“巨大的”並且可能是自動生成的。現在 GNU Make 有-O --trace一些選項,因此可能會找到用於執行最終連結的命令,然後手動執行該步驟並進行所需的修改,或者使用該資訊查看在 makefile 中呼叫命令的位置,以及從那裡開始工作以找到需要編輯或設置的內容以獲得所需的連結步驟。

另一種方法

的輸出readelf -d向我們顯示執行檔缺少一個RPATHRUNPATH指向所需庫。由於需要連結的庫是 glibc 的自定義版本,因此很可能(但不確定)它們將具有與實際用於連結的 glibc 相同的 API。有了這個假設,就可以編輯二進製文件以添加缺失的RUNPATH. 一個合適的程序是patchelf,它為各種 linux 發行版打包。

OP報告成功

patchelf --set-rpath ${GLIBCDIR}/lib --set-interpreter ${GLIBCDIR}/lib/ld-linux-x86-64.so.2 ${GCCDIR}/bin/gcc-9.2

引用自:https://unix.stackexchange.com/questions/565593