4

我試圖建立使用靜態庫中的項目,以便二進制即使沒有安裝庫中使用。不過,當我嘗試這樣做時,我會收到很多關於未定義符號的錯誤。gcc - 具有未定義符號的靜態庫?

望着圖書館,我看到它有噸未定義的符號,儘管這是一個.a靜態庫:

nm - u /usr/local/lib/libthis.a 
.... 
U EVP_DigestFinal_ex 
U EVP_DigestInit_ex 
U EVP_DigestUpdate 
U EVP_MD_CTX_cleanup 
U EVP_MD_CTX_init 

那些似乎是從OpenSSL的;其他人似乎來自libbzip2;等等。

問題: 1.靜態(.a)lib爲什麼依賴於未靜態編譯的共享對象(例如libopenssl)? 2.我該如何解決這個問題?嘗試手動添加-lssl似乎不起作用。我如何獲得二進制編譯並且沒有外部依賴?

+2

靜態庫應該有大量未定義的符號(它們畢竟只是一堆.o文件,沒有額外的東西)。這些不是對共享對象的依賴,它們只是未定義的符號。這是當你建立最終的可執行文件,你將不得不鏈接到一個巨大的庫來解析所有的符號。 –

回答

9

爲什麼靜態(.a)中的lib對共享對象的依賴關係(例如libopenssl)未靜態編譯?

剛想,你可以建立將有未解決的符號,例如每靜態庫

int my_open_for_read(const char *filename) 
{ 
    return open(filename, O_RDONLY); // unresolved reference to open 
} 

正如馬克Glisse指出的那樣,這是一個普通的未解析的符號,不libc.so的依賴性。

  1. 我該如何解決這個問題?

這裏沒有問題要解決。當你鏈接你的二進制文件時,你可以決定靜態鏈接哪些庫,以及動態鏈接哪些庫。

嘗試手動添加-lssl似乎不起作用。

這應該工作:

gcc main.o -lthis -lssl 

也許你不喜歡的東西

gcc main.o -lssl -lthis 

這是錯誤的:在鏈接行matters庫的順序。

如何獲得二進制編譯並且沒有外部依賴?

大多數操作系統支持使用完全靜態的二進制文件。一般來說,這應該是你的目標:它使便攜式的二進制文件,以及它們的使用是強烈反對。

如果你確實想產生一個完全靜態的二進制,-static標誌聯繫起來。

你爲什麼說全靜少便攜式?

因爲they are

如果用戶沒有完全相同的lib版本,那麼二進制文件將不能與共享庫一起移植,但是可以通過靜態方式移植。

這是不正確的:最共享庫支持向後兼容,例如libc.so.6版本2.22將愉快地運行,從10年前的鏈接的是2.3.6版本的可執行文件。

如果你的firefox ldd的

你需要注意你在做什麼:

file -L `which /usr/bin/firefox` 
/usr/bin/firefox: POSIX shell script, ASCII text executable 

如果你看看shell腳本里面,你會發現,它調用/usr/lib/firefox/firefox,並且該二進制文件是動態鏈接的:

ldd /usr/lib/firefox/firefox 
    linux-vdso.so.1 => (0x00007ffca278d000) 
    libpthread.so.0 => /lib/x86_64-linux-gnu/libpthread.so.0 (0x00007f511731b000) 
    libdl.so.2 => /lib/x86_64-linux-gnu/libdl.so.2 (0x00007f5117117000) 
    libstdc++.so.6 => /usr/lib/x86_64-linux-gnu/libstdc++.so.6 (0x00007f5116e13000) 
    libm.so.6 => /lib/x86_64-linux-gnu/libm.so.6 (0x00007f5116b0d000) 
    libgcc_s.so.1 => /lib/x86_64-linux-gnu/libgcc_s.so.1 (0x00007f51168f7000) 
    libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f5116532000) 
    /lib64/ld-linux-x86-64.so.2 (0x00007f5117757000) 
+0

謝謝。你爲什麼說完全靜態是無用的?由於Linux使用.so而不是DLL,因此如果用戶沒有完全相同的版本庫,那麼二進制文件將不能與共享庫一起使用,但是可以通過靜態方式進行移植。例如,如果你使用'ldd firefox',你會發現它完全是靜態的 - 你還可以在Linux上使用可移植二進制文件嗎? – SRobertJames

+0

不錯的更新,尤其是捕捉Firefox腳本!但庫ldd的節目是所有的系統庫,這是我知道)不能是靜態的和b)通常是向後兼容的。我的觀點仍然代表非系統庫(例如zlib ssl和數十種);注意firefox使用那些靜態的,我認爲這是唯一的便攜方式 – SRobertJames

+1

@SRobertJames我只是反對完全靜態的二進制文件。只要您繼續動態使用系統庫,靜態鏈接到非系統庫就很好。一個*文字*閱讀你的問題:「如何...沒有外部依賴」意味着全靜態鏈接。 –

相關問題