C++ 增压试验-';未定义的引用';错误

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

我有两个简单的文件:

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/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