使用Boost时出现奇怪的MinGW链接器错误?

4

我已经在做这个项目有一段时间了,但似乎无法理解情况——部分原因是我没有完全理解正在发生的事情(这也是我来这里的原因)。

我正在进行一种如下的boost hello world:

#include <boost/thread/thread.hpp>
#include <cstdio>


void helloworld() {
    std::printf("HELLO FROM A BOOST THREAD!");
}

int main(int argc, char **argv) {
    boost::thread t(&helloworld);
    t.join();
}

这是在Windows平台下的操作。我将Boost目录存储在C:\Boost路径下。我运行了bootstrap和bjam命令,现在有一个stage/lib文件夹,其中包含所有的.lib文件。与boost/thread库相关的lib文件如下:

libboost_thread-vc100-mt.lib
libboost_thread-vc100-mt-1_46_1.lib
libboost_thread-vc100-mt-gd.lib
libboost_thread-vc100-mt-gd-1_46_1.lib

现在我进行编译:
g++ -c main.cpp -I/Boost

那一行工作得很好,我得到了main.o文件。然后:

g++ -o test.exe main.o -L/Boost/stage/lib -llibboost_thread-vc100-mt

这就是问题所在。首先,如果我没有像我现在这样输入-l参数,MinGW甚至无法找到文件。也就是说,如果我尝试:

-lboost_thread-vc100-mt

与我之前输入的方式(以及我认为应该这样做的方式)不同,如果使用这种方式,ld命令会因为找不到文件而退出。无论如何,这是我从那行代码中得到的输出结果:

main.o:main.cpp:(.text+0x47): undefined reference to `_imp___ZN5boost6thread4joinEv'
main.o:main.cpp:(.text+0x55): undefined reference to `_imp___ZN5boost6threadD1Ev'
main.o:main.cpp:(.text+0x70): undefined reference to `_imp___ZN5boost6threadD1Ev'
main.o:main.cpp:(.text$_ZN5boost6threadC1IPFvvEEET_NS_10disable_ifINS_14is_convertibleIRS4_NS_6detail13thread_move_tIS4_EEEEPNS0_5dummyEE4typeE[boost::thread::thread<void (*)()>(void (*)(), boost::disable_if<boost::is_convertible<void (*&)(), boost::detail::thread_move_t<void (*)()> >, boost::thread::dummy*>::type)]+0x23): undefined reference to `_imp___ZN5boost6thread12start_threadEv'
collect2: ld returned 1 exit status

现在我可以看出,这些显然是我应该从boost/thread中获取的函数,而且它似乎找到了lib文件,那么为什么它没有正确链接呢?
非常感谢您的帮助!
编辑:
我已经使用bjam的“stage”选项重新构建了boost。
bjam toolset=gcc stage

现在,在构建完成后,我剩下一个stage/lib文件夹,其中包含.a文件,这是预期的结果。这些是与boost/thread相关的库:

libboost_thread-mgw45-mt-1_46_1.a
libboost_thread-mgw45-mt-d-1_46_1.a

然而,如下链接:

g++ -o test.exe main.o -L/Boost/stage/lib -lboost_thread-mgw45-mt-1_46_1

输出完全相同的错误。也尝试过:

g++ -o test.exe main.o -L/Boost/stage/lib -lboost_thread-mgw45-mt-1_46_1 -static

我仍然不知所措。

指定 toolset=gcc 是不够的,你还需要 target-os=windows 来使用 MinGW。 - ildjarn
2个回答

5
解决了这个问题。Boost的头文件被配置为动态链接,但是如果你不指定,动态库(dll)就不会被构建出来:
--build-type=complete

在调用bjam时,请将适当的dll复制到您的应用程序目录中,但仍使用原始HTML标签。
-L/BOOST_DIR/stage/lib -lname

连接时。

谢谢,这个解决方案可行。我尝试了很多次让 Boost-Thread 的 "Hello world" 程序运行,但是直到我在编译 Boost-Thread 库时添加了 --build-type=complete 标志后程序才能编译通过。Trung - TrungTN

5

这套库文件:

libboost_thread-vc100-mt.lib
libboost_thread-vc100-mt-1_46_1.lib
libboost_thread-vc100-mt-gd.lib
libboost_thread-vc100-mt-gd-1_46_1.lib

这些库是为Visual Studio 2010编译器设计的,不能与GCC一起使用。如果要使用gcc/MinGW,则需要为该编译器下载/构建一组boost库。或者,您可以安装VS 2010并使用该编译器(如果成本是问题,则免费的VC++ 2010 Express版本应该可以正常工作)。
您可以从http://nuwen.net/mingw.html获取已经包含Boost的MinGW发行版(仅32位目标)。
回答有关使用MinGW libs时出现错误的问题:
符号上的“_imp_”前缀表示“g++”正在寻找链接到dll /共享库。您拥有的.lib文件是用于静态库的(这也是我在直接进行bjam库构建时得到的内容)。如果您查看boost/thread/detail/config.hpp,您会发现对于Win32构建,默认情况下会构建针对DLL库,除非正在使用MSVC或Intel编译器。
我甚至不确定如何构建DLL库-我将不得不查找它。同时,您可以使用以下命令构建示例,以便它将链接到静态库。BOOST_THREAD_USE_LIB宏构建.cpp文件,使其期望链接到静态库:
g++ -I/Boost -DBOOST_THREAD_USE_LIB -c main.cpp

谢谢,这就是我得出的同样答案。另外,如果您不想静态链接,可以使用“--build-type=complete”选项来构建dll文件。 - cemulate
@user48998:我注意到你已经得出了相同的结论,但是这是在我编辑答案之后。顺便说一下,我通过使用link=shared runtime-link=shared选项运行bjam来获得DLL。我想象这是--build-type=complete所做的另一个子集。然而,现在我实际上无法编译静态库链接(即使我指定了-DBOOST_THREAD_USE_LIB),这让我感到惊讶。我需要深入挖掘一下看看情况如何。 - Michael Burr

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