升压试验 - '未定义的参考' 错误

问题描述:

我有两个简单的文件:升压试验 - '未定义的参考' 错误

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,boost 1.52.0。

仅在尝试编译test1.cpp时出现同样的错误 - “多主定义”除外。

我在官方文档中阅读了很长一段时间,但在关于链接选项的细节上很少见。当我编译提升库时,除了unit_test_framework,我也得到了prg_exec_monitortest_exec_monitor;也许我应该连接这些莫名其妙?我尝试了很多组合,但都导致了某种未定义的参考链接器错误。

完成升压产生的库列表 - 我把它们都在项目的根:

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

使用g ++,你需要把你的库(-lwhatever)源后或目标文件(即'g ++ -I/e/code/boost_1_52_0 -o runner runner.cpp test1.cpp -lboost_unit_test_framework')。链接[here](http://www.network-theory.co.uk/docs/gccintro/gccintro_18.html)。有可能你还需要为你的'-I/e/code/boost_1_52_0'增加一个'-L/path/to/libraries'。 – 2012-12-07 18:18:05

+1

[This answer](http:// *。com/a/2907582/1252091)似乎与你所做的非常相似。 – 2012-12-07 18:33:06

+0

@llonesmiz确实,把对象工作后的lib。 '-L.'也是需要的,并且lib需要作为'-lboost_unit_test_framework-mgw47-mt-1_52'传递。将它作为'-lboost_unit_test_framework'传递会导致链接错误。但是,当我怀疑它可能找不到lib时,我给了'-lfoo'之类的东西,它抱怨没有这样的lib存在。在查阅了[这个页面](http://www.mingw.org/wiki/HOWTO_Specify_the_Location_of_External_Libraries_for_use_with_MinGW)关于默认的MinGW lib路径之后,我发现在这些文件夹中有一个'libboost_unit_test_framework.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.资源库路径应该被明确指定。

如果未指定lib路径,则链接程序可能会查找默认文件夹的一系列 中的库,从而加载预期的不同库。这是我的情况发生了什么 - 我想链接boost_unit_test_framework,但没有 指定一个路径,因为我认为链接器会查看当前文件夹。 这就是运行时发生的情况,毕竟如果dllexe位于相同的文件夹 中,它会找到它。

我发现它有点奇怪,链接器会找到lib,因为它是 ,名称为ibboost_unit_test_framework-mgw47-mt-1_52.dll。当我试图链接到 一个不存在的lib时,链接器抱怨,所以我认为这不是 问题,并且MinGW的链接器忽略这些后缀。

经过一番研究,我找到了this article about MinGW library paths。 MinGW搜索库的文件夹可以在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不是,默认情况下, 查看当前目录中的库。我查看了其中的每一个,并发现正在加载的 库 - 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.Summary

的问题是:其中其中用它们

  • 的lib路径未指定
  • 联WASN的类型来源前指定

    1. 库没有指定
    2. 库的名称不正确

    最后,工作命令:

    $ 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 
    
  • +0

    优秀的答案。主要的多重定义问题是否也解决了这个问题?我打算在不久的将来使用类似的东西,我相信这会有很大的帮助。 – 2012-12-08 13:41:58

    +0

    @llonesmiz,是的。我仍然不确定它为什么发生;无法用新的库文件重现。 –

    +0

    你的目录显示每个库的两个版本。一个在名称中间有一个“-d-”,另一个没有。例如,'libboost_unit_test_framework-mgw47-mt-1_52.a'和'libboost_unit_test_framework-mgw47-mt-d-1_52.a'。你是怎么知道使用哪些的? – Brick