2015-11-20 95 views
3

我需要創建一個共享庫,其自身的依賴包括libc/libstdC++必須靜態鏈接到它才能生成自包含的二進制文件。我試圖做到這一點獨立共享庫

g++ -c -fpic -o foo.o foo.cpp 
g++ -static -shared -o foo.so foo.o 

其失敗:

/usr/bin/ld.bfd.real: /usr/local/lib/gcc/x86_64-unknown-linux-gnu/5.2.0/crtbeginT.o: relocation R_X86_64_32 against `__TMC_END__' can not be  used when making a shared object; recompile with -fPIC 
/usr/local/lib/gcc/x86_64-unknown-linux-gnu/5.2.0/crtbeginT.o: could not read symbols: Bad value 
collect2: error: ld returned 1 exit status 

有人能告訴我什麼,我做錯了什麼?

+1

'-fPIC'可能區分大小寫。我不知道這是否是問題。 – Simple

+0

@Simple:我試着用'-fPIC',但是我仍然得到相同的錯誤。 – user10602

+1

試試'-static-libstdC++'。有關鏈接選項,請參閱https://gcc.gnu.org/onlinedocs/gcc/Link-Options.html。 – Andrew

回答

2

您可以使用-static-libstdc++選項靜態鏈接libstdc++。如果你正在製作一個動態庫,你可能不應該靜態鏈接到libc(或libgcc,如果需要,你可以靜態鏈接到-static-libgcc);你需要選擇加載共享庫的應用程序的libc版本。

控制靜態鏈接的其他選項可以在GCC manual中找到。您也可以通過將參數傳遞給鏈接器(-Wl,<argument>,或直接調用ld)來獲得所需的結果。 LD manual列出了允許的選項。


實施例:

我寫下面的代碼

#include <iostream> 

extern "C" void do_something() { 
    std::cout << "Doing something!\n"; 
} 

並將其編譯到一個.o文件如下:

g++ -fPIC -c -o tmp.o tmp.cpp 

我然後產生兩個共享庫從它。一個用-static-的libstdC++,一個沒有:

g++ -shared -o tmp-shared.so tmp.o 
g++ -shared -static-libstdc++ -o tmp-static.so tmp.o 

爲了比較,ldd tmp-shared.so

linux-vdso.so.1 => (0x00007fffc6dfd000) 
libstdc++.so.6 => /usr/lib64/libstdc++.so.6 (0x00002b708cb43000) 
libm.so.6 => /lib64/libm.so.6 (0x00002b708ce4c000) 
libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00002b708d0cf000) 
libc.so.6 => /lib64/libc.so.6 (0x00002b708d2dd000) 
/lib64/ld-linux-x86-64.so.2 (0x00000035c6c00000) 

ldd tmp-static.so

linux-vdso.so.1 => (0x00007fff99bfd000) 
libm.so.6 => /lib64/libm.so.6 (0x00002acbec030000) 
libgcc_s.so.1 => /lib64/libgcc_s.so.1 (0x00002acbec2b3000) 
libc.so.6 => /lib64/libc.so.6 (0x00002acbec4c1000) 
/lib64/ld-linux-x86-64.so.2 (0x00000035c6c00000) 
+1

您還需要'-static-libgcc'來移除'libgcc_s.so.1'依賴項。 –

+0

@MaximEgorushkin當然,如果你想刪除依賴。現在的答案提到了這一點,儘管允許從系統中獲取'libc'和'libgcc'通常更好(當然,除非在目標系統上不存在動態'libgcc')。 – Andrew

+0

@Andrew:謝謝!你是否也碰巧知道如何做一個完整的靜態鏈接(包括libc和libm)。我知道這可能不被推薦,但我需要做一個研究原型。 – user10602

2

我需要創建它的共享庫包括libc/libstdC++在內的自身依賴關係必須靜態鏈接到它才能生成自包含的二進制文件

要擁有自包含的二進制文件,您不一定需要靜態鏈接。出於不同的原因,某些庫不能編譯爲靜態庫。

許多商業應用程序使用$ORIGIN鏈接器功能。您可以將所有必需的共享庫與您的可執行文件一起復制到目錄中,並將您的可執行文件與額外的鏈接程序標誌鏈接起見man ld.so

$ ORIGIN和rpath的

ld.so在 rpath的規範(DT_RPATHDT_RUNPATH)理解字符串$ORIGIN(或等價${ORIGIN})是指包含應用程序可執行文件的目錄。因此,位於 somedir/app中的應用程序可以編譯爲gcc -Wl,-rpath,'$ORIGIN/../lib', 它在somedir/lib中找到關聯的共享庫,無論 其中somedir位於目錄層次結構中。這有助於 創建「交鑰匙」應用程序,不需要將 安裝到特殊目錄中,但可以將其解壓到 任何目錄中,仍然可以找到它們自己的共享庫。

相關問題