2013-04-16 171 views
3

我的編譯環境是的CentOS 5。我有一個名爲libcunit的第三方庫。我使用自動工具安裝它,它會生成libcunit.alibcunit.so。我有我自己的應用程序,鏈接到一堆共享庫。 libcunit.a在當前目錄中,libcunit.so和其他共享庫在/usr/local/lib/。當我編譯這樣的:GCC靜態庫鏈接VS動態鏈接

gcc -o test test.c -L. libcunit.a -L/usr/local/lib -labc -lyz 

我得到一個鏈接錯誤:

libcunit.a(Util.o): In function `CU_trim_left': 
Util.c:(.text+0x346): undefined reference to `__ctype_b' 
libcunit.a(Util.o): In function `CU_trim_right': 
Util.c:(.text+0x3fd): undefined reference to `__ctype_b' 

但是,當我與.so編譯,如:

gcc -o test test.c -L/usr/local/lib -lcunit -labc -lyz 

它編譯罰款和運行正常了。

爲什麼與libcunit.a靜態連接時,它給錯誤?

回答

3

沒注意到libcunit.a在你的情況下,居然發現與linakge問題而在庫尼特庫本身。就職俄語是絕對正確的,他不是在討論預編譯二進制文件。我們知道您已經自己構建了它。但是,CUinit本身似乎依賴於glibc中的符號,該符號不再可用於靜態鏈接。因此,您只有兩種選擇:

  1. 向CUnit的開發人員報告此問題並要求他們修復此問題;
  2. 使用動態鏈接。

儘管如此,我對你的靜態鏈接的風格建議仍然適用。 -L.一般不好的做法。 CUnit是第三方庫,不應放入包含項目源文件的目錄中。它的安裝方式應與動態版本相同,即您可以使用libcunit.so/usr/local/lib。如果您在CUnit的配置階段向自動工具提供prefix,則Autotools會正確安裝所有內容。所以,如果你想與CUNIT靜態鏈接,請考慮以下形式做:

gcc -o test test.c -L/usr/local/lib -Wl,-Bstatic -lcunit -Wl,-Bdynamic -labc -lyz 
+0

這個答案是不正確的問題有*不*做與庫順序。 –

+0

@僱傭俄羅斯:你在哪裏看到我的答案是解決_「圖書館訂購」_的問題?建議的命令行只是OP命令行的一個複製粘貼,帶有一些編輯/添加的標誌,但沒有改變鏈接順序。 –

+0

如果直接列出libcunit.a,則不需要'-Wl,-Bstatic'(如同OP一樣)。 –

6

Why is it giving error when linked statically with libcunit.a

的問題是,你的libcunit.a建一個古老的Linux系統上,並依賴於已符號從libc刪除(這些符號用於glibc-2.2,並在10年前從glibc-2.3中刪除)。更確切地說,這些符號已被hidden。它們可用於動態鏈接到舊的二進制文件(例如libcunit.so),但沒有新的代碼可以靜態鏈接到它們(您不能創建引用它們的新可執行文件或共享庫)。

你可以像這樣觀察的:

readelf -Ws /lib/x86_64-linux-gnu/libc.so.6 | egrep '\W__ctype_b\W' 
    769: 00000000003b9130  8 OBJECT GLOBAL DEFAULT 31 [email protected]_2.2.5 

readelf -Ws /usr/lib/x86_64-linux-gnu/libc.a | egrep '\W__ctype_b\W' 
# no output 
+0

嗨,我實際上是從源代碼編譯cunit項目(http://cunit.sourceforge.net/)。這不是給我的預編譯二進制文件。我使用autotools來安裝它。還有一個問題,libc.a沒有ctype_b符號。但我並沒有要求libc靜態鏈接到我的測試應用程序。所以它應該動態鏈接到libc.so.6,對吧? – bala1486