如何开始使用GTest和CMake

我最近被出售使用CMake编译我的C ++项目,现在想开始为我的代码编写一些unit testing。 我决定使用Googletesting实用程序来帮助解决这个问题,但需要一些帮助才能入门。

我一整天都在阅读各种指南,例子包括Primer , IBM的介绍以及一些关于SO( 这里和这里 )的问题以及我失去的其他来源。 我意识到有很多,但不知何故,我仍然有困难。

我目前正在尝试执行最基本的testing,以确认我编译/安装gtest的权利,它不工作。 唯一的源文件(testgtest.cpp)几乎完全取自以前的答案:

#include <iostream> #include "gtest/gtest.h" TEST(sample_test_case, sample_test) { EXPECT_EQ(1, 1); } 

和我关联的CMakeLists.txt如下:

 cmake_minimum_required(VERSION 2.6) project(basic_test) # Setup testing enable_testing() find_package(GTest REQUIRED) include_directories(${GTEST_INCLUDE_DIR}) # Add test cpp file add_executable(runUnitTests testgtest.cpp ) # Link test executable against gtest & gtest_main target_link_libraries(runUnitTests ${GTEST_LIBRARY_DEBUG} ${GTEST_MAIN_LIBRARY_DEBUG}) add_test( NAME runUnitTests COMMAND runUnitTests ) 

请注意,我select链接到gtest_main,而不是在cpp文件的末尾提供main,因为我相信这样可以使testing更容易扩展到多个文件。

在构build生成的.sln文件时(在Visual C ++ 2010 Express中),我不幸得到了一个很长的表单错误列表

 2>msvcprtd.lib(MSVCP100D.dll) : error LNK2005: "public: virtual __thiscall std::basic_iostream<char,struct std::char_traits<char> >::~basic_iostream<char,struct std::char_traits<char> >(void)" (??1?$basic_iostream@DU?$char_traits@D@std@@@std@@UAE@XZ) already defined in gtestd.lib(gtest-all.obj) 

我认为这意味着我没有成功链接到gtest库。 我已经确定,当与debugging库链接时,我已经尝试build立在debugging模式。

编辑

在做了更多的挖掘之后,我认为我的问题与我正在build立的图书馆types有关。 当使用CMake构buildgtest时,如果BUILD_SHARED_LIBS未被选中,并且将我的程序链接到这些.lib文件,则会出现上述错误。 但是,如果BUILD_SHARED_LIBS被选中,则会生成一组.lib和.dll文件。 当现在链接到这些.lib文件程序编译,但运行时抱怨,它找不到gtest.dll。

SHAREDSHARED库之间有什么区别,如果我select不共享,为什么它不起作用? 在我的项目CMakeLists.txt有没有一个选项,我失踪了?

解决scheme是将gtest源目录作为项目的子目录。 如果对任何人都有帮助,我已经包含了下面的CMakeLists.txt。

 cmake_minimum_required(VERSION 2.6) project(basic_test) ################################ # GTest ################################ ADD_SUBDIRECTORY (gtest-1.6.0) enable_testing() include_directories(${gtest_SOURCE_DIR}/include ${gtest_SOURCE_DIR}) ################################ # Unit Tests ################################ # Add test cpp file add_executable( runUnitTests testgtest.cpp ) # Link test executable against gtest & gtest_main target_link_libraries(runUnitTests gtest gtest_main) add_test( runUnitTests runUnitTests ) 

testing二进制文件和Googletesting库之间编译器选项的差异很可能是导致这种错误的原因。 这就是为什么build议在源代码表单中引入Google Test并将其与testing一起构build的原因。 在CMake中很容易做到。 你只要用gtest根目录的path调用ADD_SUBDIRECTORY ,然后你就可以使用在那里定义的公共库目标( gtestgtest_main )。 在googletestframework组中,这个CMake线程中有更多的背景信息。

BUILD_SHARED_LIBS选项现在只在Windows上有效。 它指定了您希望CMake构build的库的types。 如果将其设置为ON ,CMake会将它们构build为DLL而不是静态库。 在这种情况下,您必须使用-DGTEST_LINKED_AS_SHARED_LIBRARY = 1构buildtesting,并将CMake生成的DLL文件复制到包含testing二进制文件的目录中(CMake默认将它们放在单独的输出目录中)。 除非静态库中的gtest不适用于你,否则更容易不设置该选项。

这是我刚刚testing的一个完整的工作示例。 它直接从网上下载,一个固定的tarball或最新的subversion目录。

 cmake_minimum_required (VERSION 3.1) project (registerer) ################################## # Download and install GoogleTest include(ExternalProject) ExternalProject_Add(gtest URL https://googletest.googlecode.com/files/gtest-1.7.0.zip # Comment above line, and uncomment line below to use subversion. # SVN_REPOSITORY http://googletest.googlecode.com/svn/trunk/ # Uncomment line below to freeze a revision (here the one for 1.7.0) # SVN_REVISION -r700 PREFIX ${CMAKE_CURRENT_BINARY_DIR}/gtest INSTALL_COMMAND "" ) ExternalProject_Get_Property(gtest source_dir binary_dir) ################ # Define a test add_executable(registerer_test registerer_test.cc) ###################################### # Configure the test to use GoogleTest # # If used often, could be made a macro. add_dependencies(registerer_test gtest) include_directories(${source_dir}/include) target_link_libraries(registerer_test ${binary_dir}/libgtest.a) target_link_libraries(registerer_test ${binary_dir}/libgtest_main.a) ################################## # Just make the test runnable with # $ make test enable_testing() add_test(NAME registerer_test COMMAND registerer_test) 

你可以得到两全其美的。 可以使用ExternalProject下载gtest源代码,然后使用add_subdirectory()将其添加到您的构build中。 这具有以下优点:

  • gtest是作为你的主要构build的一部分而构build的,所以它使用相同的编译器标志等,从而避免了问题中所描述的问题。
  • 不需要将gtest源添加到您自己的源代码树中。

以正常的方式使用,ExternalProject不会在configuration时(即运行CMake的时候)下载和解包,但是只需要一点点工作就可以完成。 我写了一篇关于如何做到这一点的博客文章,其中还包括一个通用的实现,它适用于任何使用CMake作为构build系统的外部项目,而不仅仅是gtest。 你可以在这里find他们:

更新:这种方法现在也是googletest文档的一部分 。

在做了更多的挖掘之后,我认为我的问题与我正在build立的图书馆types有关。 当使用CMake构buildgtest时,如果BUILD_SHARED_LIBS未被选中,并且将我的程序链接到这些.lib文件,则会出现上述错误。 但是,如果BUILD_SHARED_LIBS被选中,则会生成一组.lib和.dll文件。 当现在链接到这些.lib文件程序编译,但运行时抱怨,它找不到gtest.dll。

这是因为如果要将gtest用作共享库,则必须将-DGTEST_LINKED_AS_SHARED_LIBRARY = 1添加到项目中的编译器定义。

你也可以使用静态库,只要你用gtest_force_shared_crt选项编译它就可以消除你所看到的错误。

我喜欢图书馆,但将其添加到项目中是一个真正的痛苦。 除非你深入gtest cmake文件,否则你没有机会做正确的事情。 耻辱。 特别是我不喜欢把gtest作为源代码的想法。 🙂

你和VladLosevs的解决scheme可能比我的更好。 如果你想要一个蛮力的解决scheme,但是,试试这个:

 SET(CMAKE_EXE_LINKER_FLAGS /NODEFAULTLIB:\"msvcprtd.lib;MSVCRTD.lib\") FOREACH(flag_var CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO) if(${flag_var} MATCHES "/MD") string(REGEX REPLACE "/MD" "/MT" ${flag_var} "${${flag_var}}") endif(${flag_var} MATCHES "/MD") ENDFOREACH(flag_var) 

我从这个线程的答案中提取的最简单的CMakeLists.txt,以及一些试验和错误是:

 project(test CXX C) cmake_minimum_required(VERSION 2.6.2) #include folder contains current project's header filed include_directories("include") #test folder contains test files set (PROJECT_SOURCE_DIR test) add_executable(hex2base64 ${PROJECT_SOURCE_DIR}/hex2base64.cpp) # Link test executable against gtest nothing else required target_link_libraries(hex2base64 gtest pthread) 

Gtest应该已经安装在你的系统上。