我有两个简单的文件:
运行者.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,boost 1.52.0。
我在尝试编译 test1.cpp
时遇到了同样的错误 - 除了“多个主要定义”。
我仔细阅读了官方文档很长一段时间,但关于链接选项的细节很少。当我编译boost libs时,除了unit_test_framework
,我还得到了prg_exec_monitor
和test_exec_monitor
;也许我应该以某种方式链接这些?我尝试了很多组合,但都导致了某种 undefined reference 链接器错误。
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
最佳答案
在 @llonesmiz 的帮助下,发现了一些问题。
<强>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。应明确指定库路径。
如果没有指定库路径,链接器可能会在一个系列中查找库
默认文件夹,从而加载一个不同的库然后打算。这是什么
发生在我的案例中 - 我想链接 boost_unit_test_framework
,但没有
指定一个路径,因为我假设链接器会在当前文件夹中查找。
毕竟,这就是运行时发生的事情 - 如果 dll
在同一个文件夹中
使用 exe
,它会找到它。
我发现链接器会找到库有点奇怪,因为它是
名为 ibboost_unit_test_framework-mgw47-mt-1_52.dll
。当我试图链接到
一个不存在的库,尽管链接器提示了,所以我认为这不是
问题,MinGW
的链接器会忽略这些后缀。
经过更多研究,我找到了 this article about MinGW library paths .
MinGW 搜索 libs 的文件夹可以在 gcc -print-search-dirs
的输出中找到。
这篇文章还包含一些 bash
魔术来理解该输出:
gcc -print-search-dirs | sed '/^lib/b 1;d;:1;s,/[^/.][^/]*/\.\./,/,;t 1;s,:[^=]*=,:;,;s,;,; ,g' | tr \; \\012 | grep -v '^ */'
这将打印出这些文件夹的一个很好的列表。 gcc
将不会,默认情况下,
在当前目录中查找 libs。我查看了他们每个人,发现
正在加载的库 - 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.
(so
是 Unix 上动态库的扩展 - 在 Windows 上,等同于 dll
。)
所以,发生的事情是 gcc
寻找 libboost_unit_test_framework.dll
在所有它的默认文件夹中,但找不到它。然后它寻找
libboost_unit_test_framework.a
,并对其进行静态链接。这导致
链接错误,因为来源有 #define BOOST_TEST_DYN_LINK
,并且
因此期望动态链接库。
要强制执行静态或动态链接,-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.总结
问题是:
- 在使用它们的来源之前指定的库
- 未指定库路径
- 未指定链接类型
- 图书馆的名字不正确
最后,工作命令:
$ 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
关于c++ - boost 测试 - 'undefined reference' 错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13767699/