将静态库链接到共享库?

man*_*ler 6 c++ linux static shared g++

背景:

我想将一些静态库链接到共享库中。原因是我希望我的应用程序使用我已经测试过的特定库版本。我不想将静态版本作为共享库与我的应用程序一起提供。我创建了这个示例库和应用程序以尽可能简化。我想在链接期间继续将共享库链接到应用程序。

问题:

为什么我会收到下面列出的错误消息?我究竟做错了什么?也许这不是 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. 
Run Code Online (Sandbox Code Playgroud)

---- 申请样本

//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
Run Code Online (Sandbox Code Playgroud)

所有源代码都位于同一目录中。Boost 安装在 /usr/lib 和 /usr/include 中。Boost 版本 1.40 是使用 apt-get 在 ubuntu 10.04 计算机上安装的。

谢谢你!

Unk*_*own 2

我认为对你来说最简单的方法是使用--whole-archive链接器开关(关于这个主题还有更多SO问题,请参阅此处如何将静态库链接到 gcc 中的动态库)。

这样做的缺点是你的共享库将从 Boost 静态库中导出所有符号,如果你在.so也使用 Boost 的应用程序中使用你的符号(但版本不同或使用不同的开关编译),你可能会遇到奇怪的问题。

因此,您需要使用版本脚本来隐藏从库中导出的内容(请参阅如何在共享库中隐藏导出的符号名称,也可以通过谷歌搜索链接器版本脚本),仅保留doit()可见的内容。在您的情况下,这样的版本脚本可能如下所示:

{
global:
    doit*;
local:
    *;
}      
Run Code Online (Sandbox Code Playgroud)

您还需要确保您链接的静态库已编译-fPIC(如果您没有调整它们的构建标志,则不太可能),否则您将受到性能损失i386,并且可能根本无法链接在amd64