背景:
我想将一些静态库链接到一个共享库中。原因是我希望我的应用程序使用我测试过的特定 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 中。 Boost,版本 1.40,是在 ubuntu 10.04 机器上使用 apt-get 安装的。
谢谢!
最佳答案
我认为对您来说最简单的方法是使用 --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
上可能根本无法链接。
关于c++ - 将静态库链接到共享库?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13108004/