我正在尝试从我的TEST中调用静态方法,但是却遇到了无法解析的外部符号。
到目前为止,我所做的是:
创建了3个项目:
将GoogleTest项目作为静态库-编译了gtest-all.cc和gtest_main.cc
MyProject-我保存.h和.cpp文件的位置
UnitTest项目-我保存测试的地方
我已经设置了UnitTest的其他目录,lib目录,并引用了GoogleTest和MyProject。测试运行良好,直到我从一个类中调用静态方法为止。
链接器选项:
/OUT:"D:\SkyDrive\Projekti\Visual Studio 2010\Projects\File System\Debug\Unit Test.exe" /INCREMENTAL /NOLOGO "..\lib\part.lib" "kernel32.lib" "user32.lib" "gdi32.lib" "winspool.lib" "comdlg32.lib" "advapi32.lib" "shell32.lib" "ole32.lib" "oleaut32.lib" "uuid.lib" "odbc32.lib" "odbccp32.lib" "D:\SkyDrive\Projekti\Visual Studio 2010\Projects\File System\Debug\Google Test.lib" /MANIFEST /ManifestFile:"Debug\Unit Test.exe.intermediate.manifest" /ALLOWISOLATION /MANIFESTUAC:"level='asInvoker' uiAccess='false'" /DEBUG /PDB:"D:\SkyDrive\Projekti\Visual Studio 2010\Projects\File System\Debug\Unit Test.pdb" /SUBSYSTEM:CONSOLE /PGD:"D:\SkyDrive\Projekti\Visual Studio 2010\Projects\File System\Debug\Unit Test.pgd" /TLBID:1 /DYNAMICBASE /NXCOMPAT /MACHINE:X86 /ERRORREPORT:QUEUE
错误:
error LNK2019: unresolved external symbol "public: static char __cdecl FS::mount(class Partition *)" (?mount@FS@@SADPAVPartition@@@Z) referenced in function "private: virtual void __thiscall Cluster_KernelFS_mountPartition_Test::TestBody(void)" (?TestBody@Cluster_KernelFS_mountPartition_Test@@EAEXXZ) D:\SkyDrive\Projekti\Visual Studio 2010\Projects\File System\Unit Test\cluster.obj
最佳答案
从我们的意见交流中可以明显看出,您与您的联系
googletest单元测试项目(Unit Test
)不包含由应该测试的项目(MyProject
)生成的必要对象文件。 fs.obj
和kernelfs.obj
至少有两个缺失,并且通过检查
链接器命令行失败时,似乎您没有链接任何目标文件
实现您要测试的类或函数(如果还有)
您似乎相信,将对MyProject
的Visual Studio项目引用添加到Unit Test
会自动为Unit Test
提供缺少的目标文件依赖关系,但不会。
消除链接错误的最快方法是将MyProject
生成的缺少的目标文件添加到Unit Test
项目的配置属性->链接器->输入->其他依赖项中。
您可以通过一个完全限定的路径名来添加每个丢失的.obj
文件
放在Debug
的MyProject
输出目录中。或者更容易地,您可以将Debug
目录的路径添加到“配置属性”->“链接器”->“输入”->“其他目录”,然后只需将缺少的.obj
文件的标准名称添加到“其他依赖项”。
但这将是一个有缺陷的解决方案,因为您当然希望Unit Test
始终
基于最新版本的MyProject
,而不仅仅是任何MyProject
对象
文件恰好在当时存在。在这种情况下,您有两种选择:
a)您可以将生成丢失的.obj
文件的源文件以及Unit Test
添加到MyProject
项目。在Unit Test
的“解决方案资源管理器”视图中,右键单击“源文件”,然后导航“添加”->“现有项”。在这种情况下,您必须注意,每当将新的源文件添加到MyProject
时,也要将其添加到Unit Test
。
b)此选项假定两个项目都在同一解决方案中。如果不是你
可以使它们如此。然后,您可以首先执行快速但有缺陷的解决方案(并对其进行测试)。然后,为了修复该缺陷,可以使Unit Test
依赖于MyProject
,这样,无论何时构建Unit Test
,如果过时了,将自动首先构建MyProject
。要创建此依赖关系,请在“解决方案资源管理器”窗格中右键单击Unit Test
,浏览“构建依赖关系”->“项目依赖关系”->“依赖关系”,然后选中复选框,以使Unit Test
依赖于MyProject
。在这种情况下,必须注意,每当.obj
生成新的MyProject
文件时,都应将其添加到Unit Test
的其他链接程序依赖项中。
(b)是更好的做法。
以上所有假设均已正确配置Unit Test
,以便编译器搜索MyProject
的包含目录并正确定位其头文件。您似乎对该分数没有任何构建错误。
后续问题1
您能否向我解释为什么链接程序不链接MyProject中的任何对象文件(我必须手动添加它们)。
就Visual Studio而言,MyProject
和Unit Test
只是两个项目
包含在构建不同可执行文件的相同解决方案中。它并不“知道” Unit Test
的目的是对MyProject
进行单元测试,因此需要链接MyProject
生成的所有包含Unit Test
要测试功能的目标文件。那么,为什么它会自动将MyProject
的目标文件添加到Unit Test
的链接中?
即使Visual Studio确实以某种方式知道Unit Test
的目的是对MyProject
进行单元测试,它如何知道应该在MyProject
中链接哪个Unit Test
对象文件?其中一个可能包含main()
函数-实际上,如果MyProject
构建控制台应用程序就是这种情况-但Unit Test
还在其目标文件之一中生成main()
函数;因此,不可能链接MyProject
中的所有Unit Test
对象文件:这将导致multiply defined symbol
错误。
我指出,给Unit Test
一个对My Project
的项目引用不会将所有My Project
的目标文件添加到Unit Test
的链接中。您现在看到一个
之所以不能产生这种效果的原因。
这就是一个更普遍的原因:当您链接目标文件以构建可执行文件时,同一符号在多个目标文件中可见是一种链接错误。应该连接哪一个?但是,当然,在不同的可执行文件的链接中看到相同的符号并不是任何错误。这意味着您不能简单地从一个可执行文件的链接中搜出一堆目标文件,然后将它们添加到另一个可执行文件的链接中,并期望它起作用。如果要将目标文件从一个可执行文件添加到另一个可执行文件的链接中,则必须知道可以链接某些此类混合文件以及所需的混合文件。您必须知道要从哪个目标文件链接哪些符号,以使第二个可执行文件生效,然后选择
目标文件。正如您所说,这是“手动”练习。
如果MyProject
生成了库而不是可执行文件,Visual Studio的项目参考功能将为您提供帮助。在这种情况下,创建从Unit Test
到MyProject
的引用(除其他事项外)将告诉Visual Studio默认情况下,MyProject
库将添加到Unit Test
的链接中。与普通对象文件不同,创建库的目的是与不同的可执行文件链接,因此,MS Project参考功能很自然地支持库依赖关系的自动化。当然也可以假设,如果一个项目生成一个可执行文件,而不是一个库,那么它的目标文件只是一个副产品,并不打算与其他可执行文件链接。
组织工作的教科书方式将在三个项目中进行:MyLib
,生成包含要进行单元测试的所有功能的库。MyProject
,生成与当前相同的可执行文件,但链接MyLib
Unit Test
,生成对MyLib
进行单元测试的可执行文件,也链接MyLib
后续问题2
向我解释如何配置链接器以从MyProject的调试文件夹链接.objs?
我已经有了。第4段,“或更容易...”等。您无法避免
指定要链接的单个.obj
文件。您不能指示链接器“仅链接在/path/to/MyProject/Debug
中找到的任何目标文件”,因为基于我已解释的原因,链接器的工作并不那么草率。
关于c++ - googletest测试框架c++:静态方法链接器错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23042424/