GCC C++创建库时链接boost

3
我想知道当我在创建存档时,如何正确地静态链接到Boost,当Boost只是编译并存储在我的主目录中,而不是系统中?将我的程序作为库创建的想法是,我将能够重新分发库文件,以供他人在他们的程序中链接。
我想在Linux上制作一个可以链接的C++库文件。我不介意它是静态的还是动态的,但静态可能会更容易些。
我遇到的问题是,我找到的示例没有告诉您如何在库中链接其他库。我的库使用Boost,并已构建Boost,但我没有权限将其移动到我的用户区域之外。
我尝试像这样创建静态存档:
编译cpp文件:
g++ -O3 -ffast-math -Wall -Wextra -g -I./ -I../../boost/ -c BuddyManager.cpp -o build/BuddyManager.o
创建静态存档:
ar rcs build/libppmi.a ../../boost/lib/libboost_system.a build/Application.o build/DataBlock.o (等等,在所有对象文件之后列出)
但是当我稍后链接到我创建的.a文件时,它会出现未定义的引用错误。
我成功地通过在Mac上构建共享库SO文件来创建我的库,但是在该系统上,Boost安装在标准系统位置。当我在Linux上构建共享库时,我收到错误“hidden symbol `__dso_handle' in /usr/lib/crtbegin.o is referenced by DSO”,并且我经常遇到无法找到Boost .SO文件的问题。因此,我决定改为静态链接。
该系统正在运行Scientific Linux SL release 5.3(Boron),我正在使用gcc-4.6.2。但是,我希望这可以在几乎所有版本的GCC中移植。
谢谢。如果有什么不清楚或您需要更多详细信息,请询问。
一些缺失的引用如下: undefined reference to `boost::thread::interrupt()'
boost/boost/thread/pthread/thread_data.hpp:247: undefined reference to `boost::this_thread::hiden::sleep_until(timespec const&)'
boost/boost/archive/detail/iserializer.hpp:158: undefined reference to `boost::archive::detail::basic_iserializer::~basic_iserializer()'
它们似乎都在Boost中。它找不到应该在Boost存档中的引用。
有关更多信息,这就是我正在编译的内容:

ar rcs build/libppmi.a ../../boost/lib/libboost_system.a ../../boost/lib/libboost_iostreams.a ../../boost/lib/libboost_serialization.a ../../boost/lib/libboost_thread.a build/Application.o build/DataBlock.o build/Iteration.o build/Launcher.o build/Message.o build/Network.o build/Processes.o build/DataBlockManager.o build/Communicator.o build/NetworkServer.o build/NetworkClientSession.o build/NetworkMessage.o build/NetworkConnection.o build/Threadable.o build/BuddyManager.o

这段代码运行正常。但当我使用档案库时它会出问题。我也试过从boost库中提取.o文件,但这会导致链接器报告关于pthread库的其他错误。


缺少哪些符号?是来自您的代码、boost库还是看似不相关的符号?您能给出一些符号名称吗?您很可能只是在存档中缺少一些文件。 - us2012
感谢您的回复。我已经更新了问题,展示了一些符号。为了明确起见,在创建我的归档时,我还将链接到Boost线程和序列化以及系统。 - rpamely
那么,你至少缺少 libboost_thread.a 和其他一些库。为什么不先构建你的项目,然后使用 ldd 检查它使用了哪些库呢?然后你可以将它们打包到你的归档文件中(确保遵守相关许可证条款)。 - us2012
我的档案的实际编译行如下:ar rcs build/libppmi.a ../../boost/lib/libboost_system.a ../../boost/lib/libboost_iostreams.a ../../boost/lib/libboost_serialization.a ../../boost/lib/libboost_thread.a build/Application.o build/DataBlock.o build/Iteration.o build/Launcher.o build/Message.o build/Network.o build/Processes.o build/DataBlockManager.o build/Communicator.o build/NetworkServer.o build/NetworkClientSession.o build/NetworkMessage.o build/NetworkConnection.o build/Threadable.o build/BuddyManager.o这个可以正常工作,但是当我使用我的档案时,引用错误会出现。 - rpamely
@rpamely,请编辑您的问题并添加这些信息,以便未来的读者不必扫描评论。 - Sam Miller
1个回答

1

您正在创建一个存档的归档,但是当链接器查找存档时,它期望找到目标文件。链接器将查找libppmi.a并跳过所有非目标文件,包括libboost_system.a,因为它不知道该怎么处理它们,因此不会找到任何Boost符号。您可以通过使用-t进行链接来确认(如果您正在使用gccg++进行链接,则可以使用-Wl,-t-t传递给链接器),这将打印链接器处理每个文件的名称,并且您将看到它不会处理嵌套的存档。

如果您想在您的存档中包含所有的Boost代码,那么您需要列出各个对象(可以直接引用构建Boost时的对象,或者从Boost存档中提取它们再添加到您的新存档中)。

这很奇怪,在我使用存档文件时它会出现问题。

当然,所有这些只是创建一个包含您列出的文件的存档。创建存档只涉及将许多单独的文件放入一个大文件中,您可以在其中放置几乎任何文件类型。它不可能出错,但这并不意味着结果是正确或可用的。
我也尝试过从boost库中提取.o文件,但这会导致关于pthread库的其他链接器错误。
这是正确的方法,但您遇到了不同的问题,请解决该问题,而不是放弃该方法。如果您正在使用Boost.Thread,则需要使用-pthread进行编译和链接。

谢谢你的回答。有趣的是,最好的方法是将boost档案提取到.o文件中,然后重新链接它们。很遗憾这是最好的方法,因为现在我必须将所有boost链接库显式地添加到我的存档链接命令中。然而,这似乎是正确的做法,所以我会接受你的答案。只是不幸的是,GCC不能使这个过程更友好,并在我尝试链接档案时自动执行它。谢谢。 - rpamely
如果您想创建一个静态存档文件,那么这是唯一的方法,因为这就是存档文件的工作方式以及链接器(而不是GCC)的工作方式。如果您创建一个动态库,您可以将其链接到现有的存档文件中,而无需从中提取对象。 - Jonathan Wakely

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接