提高测试 - “未定义引用”错误 [英] boost test - 'undefined reference' errors
问题描述
我有两个简单的文件:
runner.cpp:
的#define BOOST_TEST_DYN_LINK
#定义BOOST_TEST_MODULE主
#包括LT&;升压/测试/ unit_test.hpp>
和test1.cpp:
的#define BOOST_TEST_DYN_LINK
#IFDEF STAND_ALONE
#定义BOOST_TEST_MODULE主
#万一
#包括LT&;升压/测试/ unit_test.hpp>BOOST_AUTO_TEST_SUITE(美孚)BOOST_AUTO_TEST_CASE(TestSomething)
{
BOOST_CHECK(真);
}BOOST_AUTO_TEST_SUITE_END()
要编译,我使用的是:
$ G ++ -I / E / code / boost_1_52_0 -o亚军-lboost_unit_test_framework runner.cpp test1.cpp
我收到以下错误:
C:\\ DOCUME〜1 \\ ADMINI〜1 \\ LOCALS〜1 \\ TEMP \\ ccU0cDSz.o:runner.cpp :(文字+ 0x8c):多重定义'主'
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):首先这里定义
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):未定义的引用`init_unit_test_suite(INT,CHAR **)
C:\\ DOCUME〜1 \\ ADMINI〜1 \\ LOCALS〜1 \\ TEMP \\ ccU0cDSz.o:runner.cpp :(文字+ 0×52):未定义的参考`_imp___ZN5boost9unit_test9framework17master_test_suiteEv
C:\\ DOCUME〜1 \\ ADMINI〜1 \\ LOCALS〜1 \\ TEMP \\ ccU0cDSz.o:runner.cpp :(文字+ 0XB0):未定义的参考`_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):未定义的引用`_imp___ZTVN5boost9unit_test13test_observerE
C:\\DOCUME~1\\ADMINI~1\\LOCALS~1\\Temp\\ccU0cDSz.o:runner.cpp:(.text$_ZN5boost9unit_test13test_observerC2Ev[__ZN5boost9unit_test13test_observerC2Ev]+0xe):未定义的引用`_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):未定义的引用`_imp___ZTVN5boost9unit_test15unit_test_log_tE
C:\\ DOCUME〜1 \\ ADMINI〜1 \\ LOCALS〜1 \\ TEMP \\ cciSdkmB.o:test1.cpp :(文字+均为0x88):未定义的参考`_imp___ZN5boost9unit_test15unit_test_log_t14set_checkpointENS0_13basic_cstringIKcEEjS4_
C:\\ DOCUME〜1 \\ ADMINI〜1 \\ LOCALS〜1 \\ TEMP \\ cciSdkmB.o:test1.cpp :(文字+ 0x136):未定义引用`_imp___ZN5boost10test_tools9tt_detail10check_implERKNS0_16$p$pdicate_resultERKNS_9unit_test12lazy_ostreamENS5_13basic_cstringIKcEEjNS1_10tool_levelENS1_10check_typeEjz'
C:\\ DOCUME〜1 \\ ADMINI〜1 \\ LOCALS〜1 \\ TEMP \\ cciSdkmB.o:test1.cpp :(文字+ 0x21d):未定义的参考`_imp___ZN5boost9unit_test9ut_detail24auto_test_unit_registrarC1ENS0_13basic_cstringIKcEE
C:\\ DOCUME〜1 \\ ADMINI〜1 \\ LOCALS〜1 \\ TEMP \\ cciSdkmB.o:test1.cpp :(文字+量0x284):未定义的参考`_imp___ZN5boost9unit_test9ut_detail24auto_test_unit_registrarC1EPNS0_9test_caseEm
C:\\ DOCUME〜1 \\ ADMINI〜1 \\ LOCALS〜1 \\ TEMP \\ cciSdkmB.o:test1.cpp :(文字+ 0x2a4):未定义的参考`_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):未定义的引用`_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):未定义的引用`_imp___ZN5boost9unit_test9test_caseC1ENS0_13basic_cstringIKcEERKNS0_9callback0INS0_9ut_detail6unusedEEE'
collect2.exe:错误:LD返回1退出状态
我使用MinGW的G ++ 4.7.2,用升压1.52.0。
我得到同样的错误时,只试图编译 test1.cpp
- 除多个主要定义一
仔细端详了好一阵子的官方文档,但其对有关链接选项的详细信息很少。当我编译升压库,除了 unit_test_framework
,我也得到了 prg_exec_monitor
和 test_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
从 @llonesmiz ,一些帮助问题被确定。
1。图书馆需要指定的之后使用它们的对象和来源。
如上所述这里:
接头的传统行为是搜索来自外部功能
从左到右在命令行上指定的库。这意味着
包含函数的定义库应任何信号源后出现
文件或使用它的目标文件。这包括与指定的库
短切-l选项,如图下面的命令:
$ GCC -Wall calc.c -lm -o计算(正确的顺序)
的对于某些链接器相反的顺序(放置-lm选项文件之前
它使用它)将导致一个错误,的
$ CC -Wall -lm calc.c -o计算(不正确的顺序)
结果
main.o中:在函数'主':
结果
main.o中(的.text + 0xF的):未定义引用'开方'
由于存在含有calc.c后开方没有图书馆或目标文件。该
该文件后,选项-lm应该出现'calc.c
块引用>2。库路径应当明确规定。
如果没有指定的lib路径,链接器可能会寻找在一系列库
默认文件夹,从而加载不同的库,然后打算。这是什么
在我的情况发生了 - 我想链接boost_unit_test_framework
,但没有
因为我认为连接器看起来在当前文件夹指定的路径。
这是在运行时会发生什么,毕竟 - 如果DLL
是在同一文件夹
与exe文件
,它会找到它。我觉得有点怪怪的连接器将发现的lib,因为它是
名为ibboost_unit_test_framework-mgw47-MT-1_52.dll
。当我试图链接
不存在lib目录,链接器虽然抱怨,所以我认为这不是一个
问题,的MinGW
的链接器会忽略这些后缀。在一些更多的研究,我发现<一个href=\"http://www.mingw.org/wiki/HOWTO_Specify_the_Location_of_External_Libraries_for_use_with_MinGW\">this关于MinGW的库路径文章。
MinGW的搜索库中的文件夹可以在的输出中找到的gcc -print-搜索迪尔斯
。
文章还包含一些庆典
魔法使该输出感:的gcc -print-搜索迪尔斯| SED'/ ^ LIB / B 1,D,:; [^ /] 1秒,/ [^ /] * / \\ \\ ./,/ ,;牛逼1; S,:[^ =] * =, :;; S,;; ,G'| TR \\; \\\\ 012 | grep的-v'^ * /
这将打印这些文件夹的一个很好的列表。
GCC
将的不的,默认情况下,
看在库的当前目录。我看着在他们每个人,并发现
当时正在加载LIB -libboost_unit_test_framework.a
,静态库这将带来光的另一个问题值得一提的:
3。静态与动态链接
我没有指定我是否要
boost_unit_test_framework
静态或动态链接。
在这种情况下,GCC
prefers动态链接:
由于这些优点GCC编译使用由共享库的程序
默认在大多数系统上,如果他们都可用。每当一个静态库
将用于与选项联'libName.a的'-lname编译器
对于具有相同名称和。所以'替代共享库首先检查
扩展。
块引用>(
所以
是在Unix动态库的扩展 - 在Windows上,相当于是DLL
)那么,什么情况是,
GCC
看了libboost_unit_test_framework.dll
在所有它的默认文件夹,但无法找到它。然后找libboost_unit_test_framework.a
和静态链接的。这导致
链接错误,因为源有的#define BOOST_TEST_DYN_LINK
,和
因此,期望有下的lib动态链接。要执行静态或动态链接时,
-Wl,-Bstatic
和轮候册,-Bdynamic
链接选项开始发挥作用,可谓 href=\"http://stackoverflow.com/q/6578484/447661\">。如果我告诉大家,我要动态链接的链接:
$ G ++ -I / E / code / boost_1_52_0 runner.cpp test1.cpp -o亚军轮候册,Bdynamic -lboost_unit_test_framework
这将失败,因为链接器将无法找到
DLL
。4.Summary
的问题是:
- 凡用他们的来源之前指定的库
- 未指定库路径
- 未指定连接的类型
- 库的名称不正确
最后,工作命令:
$ G ++ -I / E / code / boost_1_52_0 -o亚军runner.cpp test1.cpp -L。轮候册,-Bdynamic -lboost_unit_test_framework-mgw47-MT-1_52
I have two simple files:
runner.cpp:
#define BOOST_TEST_DYN_LINK #define BOOST_TEST_MODULE Main #include <boost/test/unit_test.hpp>
and 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()
To compile, I'm using:
$ g++ -I/e/code/boost_1_52_0 -o runner -lboost_unit_test_framework runner.cpp test1.cpp
I get the following error:
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
I'm using g++ 4.7.2 on MinGW, with boost 1.52.0.
I get the same errors when only trying to compile
test1.cpp
- except the "multiple main definition" one.I perused the official documentation for quite a while, but its scarce on details regarding linking options. When I compiled the boost libs, besides
unit_test_framework
, I also gotprg_exec_monitor
andtest_exec_monitor
; perhaps I should link these somehow ? I tried many combinations, but all resulted in some kind of undefined reference linker error.Complete list of boost generated libraries - I have them all in the project root:
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
解决方案With help from @llonesmiz, a number of issues were identified.
1. Libraries need to be specified after objects and sources which use them.
As described 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. Library paths should be explicitly specified.
If no lib paths are specified, the linker might look for the libs in a series of default folders, thus loading a different library then intended. This is what happened in my case - I wanted to link
boost_unit_test_framework
, but did not specify a path because I assumed the linker would look in the current folder. That's what happens at runtime, after all - if thedll
is in the same folder with theexe
, it will find it.I found it a little bit strange the linker would find the lib, since it was named
ibboost_unit_test_framework-mgw47-mt-1_52.dll
. When I tried to link to a non-existing lib, the linker complained though, so I assumed this isn't an issue, andMinGW
's linker ignores those suffixes.After some more research, I found this article about MinGW library paths. The folders MinGW searches for libs can be found in the output of
gcc -print-search-dirs
. The article also contains somebash
magic to make sense of that output:gcc -print-search-dirs | sed '/^lib/b 1;d;:1;s,/[^/.][^/]*/\.\./,/,;t 1;s,:[^=]*=,:;,;s,;,; ,g' | tr \; \\012 | grep -v '^ */'
This will print a nice list of those folders.
gcc
will not, by default, look in the current directory for libs. I looked in each of them, and found the lib that was being loaded -libboost_unit_test_framework.a
, a static lib.This brings into light another issue worth mentioning:
3. Static versus dynamic linking
I did not specify whether I want
boost_unit_test_framework
linked statically or dynamically. In this case,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
is the extension for dynamic libraries on Unix - on Windows, the equivalent isdll
.)So, what happened is that
gcc
looked forlibboost_unit_test_framework.dll
in all it's default folders, but couldn't find it. Then it looked forlibboost_unit_test_framework.a
, and statically linked that. This resulted in linking errors because the sources have#define BOOST_TEST_DYN_LINK
, and therefore expect to have the lib dynamically linked.To enforce static or dynamic linking, the
-Wl,-Bstatic
and-Wl,-Bdynamic
linker options come into play, described here.If I tell the linker that I want dynamic linking:
$ g++ -I/e/code/boost_1_52_0 runner.cpp test1.cpp -o runner -Wl,Bdynamic -lboost_unit_test_framework
This will fail, because the linker will not be able to find the
dll
.4.Summary
The issues were:
- libraries where specified before the sources which used them
- the lib path wasn't specified
- the type of linking wasn't specified
- the name of the library was not correct
Final, working command:
$ 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
这篇关于提高测试 - “未定义引用”错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!