C++ 增压试验-';未定义的引用';错误
我有两个简单的文件: runner.cpp:C++ 增压试验-';未定义的引用';错误,c++,unit-testing,boost,mingw,boost-test,C++,Unit Testing,Boost,Mingw,Boost Test,我有两个简单的文件: runner.cpp: #define BOOST_TEST_DYN_LINK #define BOOST_TEST_MODULE Main #include <boost/test/unit_test.hpp> 我得到以下错误: C:\DOCUME~1\ADMINI~1\LOCALS~1\Temp\ccU0cDSz.o:runner.cpp:(.text+0x8c): multiple definition of `main' c:/pdev/mingw/b
#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MODULE Main
#include <boost/test/unit_test.hpp>
我得到以下错误:
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和boost 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。需要在使用库的对象和源之后指定库。
如上所述:
链接器的传统行为是从
在命令行上指定的库中从左到右。这意味着
包含函数定义的库应出现在任何源之后
使用它的文件或对象文件。这包括使用
shortcut-l选项,如以下命令所示:
$ 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
$gcc-Wall calc.c-lm-o calc(正确顺序)
对于某些链接器,顺序相反(将-lm选项放在文件之前)
会导致错误
$cc-Wall-lm calc.c-o calc(顺序不正确)
main.o:在函数“main”中:
main.o(.text+0xf):对“sqrt”的未定义引用
因为在“calc.c”之后没有包含sqrt的库或对象文件。这个
选项-lm应出现在文件“calc.c”之后
2。应明确指定库路径。
如果未指定库路径,则链接器可能会在序列中查找库
默认文件夹的类型,从而加载不同的库。这是什么
发生在我的案例中-我想链接boost\u unit\u test\u框架
,但没有
指定路径,因为我假设链接器将在当前文件夹中查找。
毕竟,如果dll
位于同一文件夹中,那么在运行时就会发生这种情况
使用exe
,它将找到它
我发现链接器会找到lib有点奇怪,因为它是
命名为ibboost\u unit\u test\u framework-mgw47-mt-1\u 52.dll
。当我试图链接到
链接器抱怨说,这是一个不存在的库,所以我认为这不是一个
问题,而MinGW
的链接器将忽略这些后缀
经过进一步的研究,我发现。
MinGW搜索libs的文件夹可以在gcc-print search dirs
的输出中找到。
本文还包含了一些bash
magic来理解该输出:
gcc -print-search-dirs | sed '/^lib/b 1;d;:1;s,/[^/.][^/]*/\.\./,/,;t 1;s,:[^=]*=,:;,;s,;,; ,g' | tr \; \\012 | grep -v '^ */'
这将打印这些文件夹的良好列表<默认情况下,代码>gcc不会,
在当前目录中查找libs。我查看了每一个,发现了
正在加载的库-libboost\u unit\u test\u framework.a
,一个静态库
这揭示了另一个值得一提的问题:
3。静态链接与动态链接
我没有指定是静态链接还是动态链接boost\u unit\u test\u框架。
在这种情况下,:
由于这些优点,gcc编译程序以使用共享库
大多数系统上的默认值(如果可用)。当一个静态库
“libNAME.a”将用于链接选项-lNAME编译器
首先检查具有相同名称和“.so”的替代共享库
分机
(so
是Unix上动态库的扩展-在Windows上,等效于dll
)
所以,发生的事情是,gcc
查找libboost\u unit\u test\u framework.dll
在所有它的默认文件夹中,但找不到它。然后它寻找
libboost\u unit\u test\u framework.a
,并将其静态链接。这导致了
链接错误,因为源具有#define BOOST\u TEST\u DYN\u LINK
,以及
因此,希望能够动态链接库
若要强制执行静态或动态链接,请使用-Wl,-Bstatic
和-Wl,-Bdynamic
链接器选项开始发挥作用,如上所述
如果我告诉链接器我想要动态链接:
$ g++ -I/e/code/boost_1_52_0 runner.cpp test1.cpp -o runner -Wl,Bdynamic -lboost_unit_test_framework
这将失败,因为链接器将无法找到dll
4.总结
这些问题是:
在使用它们的源之前指定的库
未指定库路径
未指定链接的类型
库的名称不正确
最后,工作指令:
$ 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
使用g++时,您需要将库(-lwhatever)放在源文件或目标文件之后(即g++-i/e/code/boost\u 1\u 52\u 0-o runner.cpp test1.cpp-lboost\u unit\u test\u framework
)。链接您可能还需要添加一个类似于-I/e/code/boost\u 1\u 52\u 0的-L/path/to/libraries
。看起来与您正在做的非常相似。@llonesmiz确实,将库放在对象之后工作<代码>-L.
也是必需的,并且lib需要作为-lboost\u unit\u test\u framework-mgw47-mt-1\u 52
通过。将其作为-lboost\u unit\u test\u框架传递会导致链接错误。然而,当我怀疑它可能找不到lib时,我给出了类似于-lfoo
的东西,它抱怨没有这样的lib存在。在咨询了默认的MinGW lib路径后,我发现在其中一个文件夹中有另一个libboost\u unit\u test\u framework.a
。@llonesmiz如果你能在回答中总结这些问题,我会很乐意接受。我的建议只花了你一小时
$ 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