首页 文章

如何开始使用GTest和CMake

提问于
浏览
96

我最近因使用CMake编译我的C项目而被出售,现在我想开始为我的代码编写一些单元测试 . 我决定使用Google Test实用程序来帮助解决这个问题,但在入门时需要一些帮助 .

我一直在阅读各种指南和例子,包括Primerintroduction at IBM以及关于SO(herehere)以及其他来源的一些问题,但我仍然遇到困难 .

我'm currently trying to implement the most basic test, to confirm I'已经编译/安装了gtest,它不起作用 . 唯一的源文件(testgtest.cpp)几乎完全取自this上一个答案:

#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
)

请注意,我选择链接gtest_main而不是在cpp文件的末尾提供main,因为我相信这将允许我更容易地将测试扩展到多个文件 .

构建生成的.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库 . 我确保在链接调试库时,我已经尝试在调试模式下构建 .

EDIT

做了一些挖掘之后,我认为我的问题与我正在构建gtest的库的类型有关 . 使用CMake构建gtest时,如果未检查 BUILD_SHARED_LIBS ,并且我将程序与这些.lib文件链接,则会出现上述错误 . 但是,如果选中了 BUILD_SHARED_LIBS ,那么我会生成一组.lib和.dll文件 . 当现在链接这些.lib文件时程序编译,但运行时抱怨它找不到gtest.dll .

SHARED 和非 SHARED 库之间有什么区别,如果我选择不共享,为什么它不起作用? CMakeLists.txt中是否有我错过的项目选项?

7 回答

  • 20

    解决方案涉及将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 )
    
  • 9

    这是我刚刚测试过的一个完整的工作示例 . 它直接从Web下载,可以是固定的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)
    
  • 0

    最有可能的是,测试二进制文件和Google测试库之间编译器选项的差异应该归咎于此类错误 . 's why it'建议在源代码表单中引入Google Test并将其与测试一起构建 . 在CMake中很容易做到 . 您只需使用gtest根目录调用 ADD_SUBDIRECTORY ,然后就可以使用在那里定义的公共库目标( gtestgtest_main ) . googletest框架组中的CMake thread中有更多背景信息 .

    [编辑] BUILD_SHARED_LIBS 选项仅在Windows上有效 . 它指定了您希望CMake构建的库的类型 . 如果将其设置为 ON ,则CMake会将它们构建为DLL而不是静态库 . 在这种情况下,您必须使用-DGTEST_LINKED_AS_SHARED_LIBRARY = 1构建测试,并将CMake生成的DLL文件复制到包含测试二进制文件的目录中(默认情况下,CMake将它们放在单独的输出目录中) . 除非在静态库中使用gtest,否则不容易设置该选项 .

  • 2

    你可以充分利用这两个世界 . 可以使用 ExternalProject 下载gtest源,然后使用 add_subdirectory() 将其添加到您的构建中 . 这具有以下优点:

    • gtest是作为主构建的一部分构建的,因此它使用相同的编译器标志等,因此避免了问题中描述的问题 .

    • 无需将gtest源添加到您自己的源代码树中 .

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

    Update: 这种方法现在也是part of the googletest documentation .

  • -1

    做了一些挖掘,我认为我的问题与我正在构建gtest的库的类型有关 . 使用CMake构建gtest时,如果未检查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作为源的想法 . :)

  • 61

    你和VladLosevs的解决方案可能比我的好 . 但是,如果你想要一个暴力解决方案,试试这个:

    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)
    
  • 13

    最简单的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应该已经安装在您的系统上 .

相关问题