runner.cpp:
#define BOOST_TEST_DYN_LINK #define BOOST_TEST_MODULE Main #include <boost/test/unit_test.hpp>
和test1.cpp:
#define BOOST_TEST_DYN_LINK #ifdef STAND_ALONE # define BOOST_TEST_MODULE Main #endif #include <boost/test/unit_test.hpp> BOOST_AUTO_TEST_SUITE( Foo) BOOST_AUTO_TEST_CASE( TestSomething ) { BOOST_CHECK( true ); } BOOST_AUTO_TEST_SUITE_END()
要编译,我正在使用:
$g++ -I/e/code/boost_1_52_0 -o runner -lboost_unit_test_framework runner.cpp test1.cpp
我收到以下错误:
C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\ccU0cDSz.o:runner.cpp:(.text+0x8c): multiple definition of `main' c:/pdev/mingw/bin/../lib/gcc/i686-pc-mingw32/4.7.2/../../../libboost_unit_test_framework.a(unit_test_main.o):unit_test_main.cpp:(.text.startup+0x0): first defined here c:/pdev/mingw/bin/../lib/gcc/i686-pc-mingw32/4.7.2/../../../libboost_unit_test_framework.a(unit_test_main.o):unit_test_main.cpp:(.text.startup+0x14): undefined reference to `init_unit_test_suite(int,char**)' C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\ccU0cDSz.o:runner.cpp:(.text+0x52): undefined reference to `_imp___ZN5boost9unit_test9framework17master_test_suiteEv' C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\ccU0cDSz.o:runner.cpp:(.text+0xb0): undefined reference to `_imp___ZN5boost9unit_test14unit_test_mainEPFbvEiPPc' C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\ccU0cDSz.o:runner.cpp:(.text$_ZN5boost9unit_test13test_observerD2Ev[__ZN5boost9unit_test13test_observerD2Ev]+0xe): undefined reference to `_imp___ZTVN5boost9unit_test13test_observerE' C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\ccU0cDSz.o:runner.cpp:(.text$_ZN5boost9unit_test13test_observerC2Ev[__ZN5boost9unit_test13test_observerC2Ev]+0xe): undefined reference to `_imp___ZTVN5boost9unit_test13test_observerE' C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\ccU0cDSz.o:runner.cpp:(.text$_ZN5boost9unit_test15unit_test_log_tC1Ev[__ZN5boost9unit_test15unit_test_log_tC1Ev]+0x22): undefined reference to `_imp___ZTVN5boost9unit_test15unit_test_log_tE' C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\cciSdkmB.o:test1.cpp:(.text+0x88): undefined reference to `_imp___ZN5boost9unit_test15unit_test_log_t14set_checkpointENS0_13basic_cstringIKcEEjS4_' C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\cciSdkmB.o:test1.cpp:(.text+0x136): undefined reference to `_imp___ZN5boost10test_tools9tt_detail10check_implERKNS0_16predicate_resultERKNS_9unit_test12lazy_ostreamENS5_13basic_cstringIKcEEjNS1_10tool_levelENS1_10check_typeEjz' C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\cciSdkmB.o:test1.cpp:(.text+0x21d): undefined reference to `_imp___ZN5boost9unit_test9ut_detail24auto_test_unit_registrarC1ENS0_13basic_cstringIKcEE' C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\cciSdkmB.o:test1.cpp:(.text+0x284): undefined reference to `_imp___ZN5boost9unit_test9ut_detail24auto_test_unit_registrarC1EPNS0_9test_caseEm' C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\cciSdkmB.o:test1.cpp:(.text+0x2a4): undefined reference to `_imp___ZN5boost9unit_test9ut_detail24auto_test_unit_registrarC1Ei' C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\cciSdkmB.o:test1.cpp:(.text$_ZN5boost9unit_test14make_test_caseERKNS0_9callback0INS0_9ut_detail6unusedEEENS0_13basic_cstringIKcEE[__ZN5boost9unit_test14make_test_caseERKNS0_9callback0INS0_9ut_detail6unusedEEENS0_13basic_cstringIKcEE]+0x1d): undefined reference to `_imp___ZN5boost9unit_test9ut_detail24normalize_test_case_nameENS0_13basic_cstringIKcEE' C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\cciSdkmB.o:test1.cpp:(.text$_ZN5boost9unit_test14make_test_caseERKNS0_9callback0INS0_9ut_detail6unusedEEENS0_13basic_cstringIKcEE[__ZN5boost9unit_test14make_test_caseERKNS0_9callback0INS0_9ut_detail6unusedEEENS0_13basic_cstringIKcEE]+0x5b): undefined reference to `_imp___ZN5boost9unit_test9test_caseC1ENS0_13basic_cstringIKcEERKNS0_9callback0INS0_9ut_detail6unusedEEE' collect2.exe: error: ld returned 1 exit status
我在MinGW上使用g 4.7.2,增强1.52.0.
我只是在尝试编译test1.cpp时遇到了同样的错误 – 除了“多主要定义”之外.
我仔细阅读了官方文档很长一段时间,但关于链接选项的细节很少.当我编译boost libs时,除了unit_test_framework之外,我还得到了prg_exec_monitor和test_exec_monitor;或许我应该以某种方式链接这些?我尝试了很多组合,但都导致了某种未定义的引用链接器错误.
boost生成库的完整列表 – 我在项目根目录中都有它们:
libboost_prg_exec_monitor-mgw47-mt-1_52.a libboost_prg_exec_monitor-mgw47-mt-1_52.dll libboost_prg_exec_monitor-mgw47-mt-1_52.dll.a libboost_prg_exec_monitor-mgw47-mt-d-1_52.a libboost_prg_exec_monitor-mgw47-mt-d-1_52.dll libboost_prg_exec_monitor-mgw47-mt-d-1_52.dll.a libboost_test_exec_monitor-mgw47-mt-1_52.a libboost_test_exec_monitor-mgw47-mt-d-1_52.a libboost_unit_test_framework-mgw47-mt-1_52.a libboost_unit_test_framework-mgw47-mt-1_52.dll libboost_unit_test_framework-mgw47-mt-1_52.dll.a libboost_unit_test_framework-mgw47-mt-d-1_52.a libboost_unit_test_framework-mgw47-mt-d-1_52.dll libboost_unit_test_framework-mgw47-mt-d-1_52.dll.a
解决方法
1.需要在使用它们的对象和源之后指定库.
如here所述:
The traditional behavior of linkers is to search for external functions from
left to right in the libraries specified on the command line. This means that a
library containing the definition of a function should appear after any source
files or object files which use it. This includes libraries specified with the
short-cut -l option,as shown in the following command:
$gcc -Wall calc.c -lm -o calc (correct order)
With some linkers the opposite ordering (placing the -lm option before the file
which uses it) would result in an error,
$cc -Wall -lm calc.c -o calc (incorrect order)
main.o: In function 'main':
main.o(.text+0xf): undefined reference to 'sqrt'
because there is no library or object file containing sqrt after ‘calc.c’. The
option -lm should appear after the file ‘calc.c’
2.应明确指定库路径.
如果未指定lib路径,则链接器可能会查找系列中的lib
默认文件夹,因此加载一个不同的库然后打算.这是什么
发生在我的情况 – 我想链接boost_unit_test_framework,但没有
指定路径,因为我假设链接器将在当前文件夹中查找.
毕竟,这就是运行时发生的事情 – 如果dll在同一个文件夹中
使用exe,它会找到它.
我发现链接器找到lib有点奇怪,因为它是
名为ibboost_unit_test_framework-mgw47-mt-1_52.dll.当我试图链接到
一个不存在的lib,链接器虽然抱怨,所以我认为这不是一个
问题,MinGW的链接器忽略了那些后缀.
经过一些研究,我找到了this article about MinGW library paths.
可以在gcc -print-search-dirs的输出中找到MinGW搜索libs的文件夹.
这篇文章还包含一些bash魔法来理解输出:
gcc -print-search-dirs | sed '/^lib/b 1;d;:1;s,/[^/.][^/]*/\.\./,/,;t 1;s,:[^=]*=,:;,;s,;,g' | tr \; \\012 | grep -v '^ */'
这将打印这些文件夹的一个很好的列表.默认情况下,gcc不会
查看libs的当前目录.我看着他们每个人,发现了
正在加载的lib – libboost_unit_test_framework.a,一个静态库.
这揭示了另一个值得一提的问题:
3.静态与动态链接
我没有指定是否要静态或动态链接boost_unit_test_framework.
在这种情况下,gcc
prefers dynamic linking:
Because of these advantages gcc compiles programs to use shared libraries by
default on most systems,if they are available. Whenever a static library
‘libNAME.a’ would be used for linking with the option -lNAME the compiler
first checks for an alternative shared library with the same name and a ‘.so’
extension.
(在Unix上动态库的扩展也是如此 – 在Windows上,相当于dll.)
所以,发生了什么是gcc寻找libboost_unit_test_framework.dll
在所有它的默认文件夹中,但找不到它.然后它寻找
libboost_unit_test_framework.a,并静态链接.这导致了
链接错误,因为源有#define BOOST_TEST_DYN_LINK,和
因此期望将lib动态链接.
要强制执行静态或动态链接,请使用-Wl,-Bstatic和-Wl,-Bdynamic
链接器选项起作用,描述here.
$g++ -I/e/code/boost_1_52_0 runner.cpp test1.cpp -o runner -Wl,Bdynamic -lboost_unit_test_framework
这将失败,因为链接器将无法找到dll.
4.Summary
问题是:
>在使用它们的源之前指定的库
>未指定lib路径
>未指定链接类型
>图书馆的名称不正确
最后的工作指令:
$g++ -I/e/code/boost_1_52_0 -o runner runner.cpp test1.cpp -L. -Wl,-Bdynamic -lboost_unit_test_framework-mgw47-mt-1_52