2012-10-28 282 views
4

背景:將靜態庫鏈接到共享庫?

我想將幾個靜態庫鏈接到一個共享庫。原因是我希望我的應用程序使用我測試過的特定lib版本。我不想將靜態版本作爲共享庫發佈到我的應用程序中。我已經創建了這個樣本庫和應用程序以儘可能簡化。我想在鏈接過程中繼續將共享庫鏈接到應用程序。

問:

爲什麼我得到下列錯誤信息?我究竟做錯了什麼?也許這不是在Linux上做事的常用方式,但是可以這樣做嗎?這種提升是否具體?

----庫

//example.cpp 
#include <boost/thread.hpp> 
void doit() 
{ 
    boost::thread t1; 
} 

#build script 
g++ -Wall -fPIC -I/usr/include -c example.cpp -o example.o 
g++ -shared /usr/lib/libboost_thread.a /usr/lib/libboost_system.a 
    example.o -o libexample.so 
#build OK. 

----樣品應用

//main.cpp 
#include <iostream> 
void doit(); 
int main() 
{ 
    std::cout << "main\n"; 
    doit(); 
    return 0; 
}; 

#build script. 
g++ -Wall -c main.cpp -o main.o 
g++ libexample.so main.o -o main 

#error message. 
libexample.so: undefined reference to `boost::thread::thread()' 
libexample.so: undefined reference to `boost::thread::~thread()' 
collect2: ld returned 1 exit status 

所有的源代碼位於同一目錄中。 Boost安裝在/ usr/lib和/ usr/include中。在Ubuntu 10.04機器上使用apt-get安裝Boost版本1.40。

謝謝!

+0

不要這樣做:靜態庫通常包含普通對象成員,而共享庫包含與位置無關的代碼。 –

+0

但是,如果我用-fPIC重新編譯靜態庫,該怎麼辦?這會有幫助嗎? – mantler

回答

1

我認爲最簡單的方法是使用--whole-archive鏈接器開關(關於此主題的更多SO問題,請參閱how to link static library into dynamic library in gcc)。

這樣做的缺點是共享庫將從Boost靜態庫中導出所有符號,如果您在也使用Boost的應用程序中使用.so(但是使用不同的版本或編譯爲不同的開關)。

因此,您需要使用版本腳本來隱藏從庫中導出的內容(請參閱How to hide the exported symbols name within a shared library,也適用於鏈接器版本腳本的Google),只留下doit()可見。在你的情況,這樣的版本腳本可能看起來像:

{ 
global: 
    doit*; 
local: 
    *; 
}  

你還需要確保你與鏈接的靜態庫編譯-fPIC(這是不可能的,如果你不調整自己的建立旗幟),其他明智的你會在i386有性能損失,並且可能根本不會鏈接到amd64

+0

謝謝,我會試試這個。我只需要先下載並重新編譯boost。 – mantler

+0

這個答案有點進一步解釋:http://stackoverflow.com/a/2649792/602340 – matiu