How to start working with GTest and CMake

僤鯓⒐⒋嵵緔 提交于 2019-11-26 23:24:47

The solution involved putting the gtest source directory as a subdirectory of your project. I've included the working CMakeLists.txt below if it is helpful to anyone.

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 )

Here is a complete working example that I just tested. It downloads directly from the web, either a fixed tarball, or the latest subversion directory.

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)

Most likely, the difference in compiler options between your test binary and the Google Test library is to blame on such errors. That's why it's recommended to bring in Google Test in the source form and build it along with your tests. It's very easy to do in CMake. You just invoke ADD_SUBDIRECTORY with the path to the gtest root and then you can use public library targets (gtest and gtest_main) defined there. There is more background information in this CMake thread in the googletestframework group.

[edit] The BUILD_SHARED_LIBS option is only effective on Windows for now. It specifies the type of libraries that you want CMake to build. If you set it to ON, CMake will build them as DLLs as opposed to static libs. In that case you have to build your tests with -DGTEST_LINKED_AS_SHARED_LIBRARY=1 and copy the DLL files produced by the CMake to the directory with your test binary (CMake places them in a separate output directory by default). Unless gtest in static lib doesn't work for you, it's easier not to set that option.

You can get the best of both worlds. It is possible to use ExternalProject to download the gtest source and then use add_subdirectory() to add it to your build. This has the following advantages:

  • gtest is built as part of your main build, so it uses the same compiler flags, etc. and hence avoids problems like the ones described in the question.
  • There's no need to add the gtest sources to your own source tree.

Used in the normal way, ExternalProject won't do the download and unpacking at configure time (i.e. when CMake is run), but you can get it to do so with just a little bit of work. I've written a blog post on how to do this which also includes a generalised implementation which works for any external project which uses CMake as its build system, not just gtest. You can find them here:

Update: This approach is now also part of the googletest documentation.

Having done some more digging, I think my issue is something to do with the type of library I am building gtest into. When building gtest with CMake, if BUILD_SHARED_LIBS is un-checked, and I link my program against these .lib files I get the errors mentioned above. However, if BUILD_SHARED_LIBS is checked then I produce a set of .lib and .dll files. When now linking against these .lib files the program compiles, but when run complains that it can't find gtest.dll.

That is because you have to add -DGTEST_LINKED_AS_SHARED_LIBRARY=1 to compiler definitions in your project if you want to use gtest as a shared library.

You could also use the static libraries, provided you compiled it with gtest_force_shared_crt option on to eliminate errors you have seen.

I like the library but adding it to the project is a real pain. And you have no chance to do it right unless you dig (and hack) into the gtest cmake files. Shame. In particular I do not like the idea of adding gtest as a source. :)

Yours and VladLosevs' solutions are probably better than mine. If you want a brute-force solution, however, try this:

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)

The simplest CMakeLists.txt I distilled from answers in this thread and some trial and error is:

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 should already be installed on your system.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!