Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CMake + GoogleTest

I just downloaded googletest, generated its makefile with CMake and built it. Now, I need to use it in my testing project.

With CMake, I have been advised not pointing to gtest libraries directly (using include _directories or link_directories) but use find_package() instead.

The problem is, there is no install target for the gtest makefile generated. I cannot understand how find_package(GTest REQUIRED) could work without some kind of installation. Also, putting the gtest folder as a subfolder in my project is not possible.

Thanks for any help.

like image 447
Korchkidu Avatar asked Mar 13 '12 17:03

Korchkidu


People also ask

How do I check my version of Google?

Installation Queries: ... --version the version of the Google Test installation Version Queries: --min-version=VERSION return 0 if the version is at least VERSION --exact-version=VERSION return 0 if the version is exactly VERSION --max-version=VERSION return 0 if the version is at most VERSION ...


2 Answers

This is an unusual case; most projects specify install rules.

CMake's ExternalProject_Add module is maybe the best tool for this job. This allows you to download, configure and build gtest from within your project, and then link to the gtest libraries.

I've tested the following CMakeLists.txt on Windows with Visual Studio 10 and 11, and on Ubuntu using GCC 4.8 and Clang 3.2 - it might need adjusted for other platforms/compilers:

cmake_minimum_required(VERSION 2.8.7 FATAL_ERROR) project(Test)  # Create main.cpp which uses gtest file(WRITE src/main.cpp "#include \"gtest/gtest.h\"\n\n") file(APPEND src/main.cpp "TEST(A, B) { SUCCEED(); }\n") file(APPEND src/main.cpp "int main(int argc, char **argv) {\n") file(APPEND src/main.cpp "  testing::InitGoogleTest(&argc, argv);\n") file(APPEND src/main.cpp "  return RUN_ALL_TESTS();\n") file(APPEND src/main.cpp "}\n")  # Create patch file for gtest with MSVC 2012 if(MSVC_VERSION EQUAL 1700)   file(WRITE gtest.patch "Index: cmake/internal_utils.cmake\n")   file(APPEND gtest.patch "===================================================================\n")   file(APPEND gtest.patch "--- cmake/internal_utils.cmake   (revision 660)\n")   file(APPEND gtest.patch "+++ cmake/internal_utils.cmake   (working copy)\n")   file(APPEND gtest.patch "@@ -66,6 +66,9 @@\n")   file(APPEND gtest.patch "       # Resolved overload was found by argument-dependent lookup.\n")   file(APPEND gtest.patch "       set(cxx_base_flags \"\${cxx_base_flags} -wd4675\")\n")   file(APPEND gtest.patch "     endif()\n")   file(APPEND gtest.patch "+    if (MSVC_VERSION EQUAL 1700)\n")   file(APPEND gtest.patch "+      set(cxx_base_flags \"\${cxx_base_flags} -D_VARIADIC_MAX=10\")\n")   file(APPEND gtest.patch "+    endif ()\n")   file(APPEND gtest.patch "     set(cxx_base_flags \"\${cxx_base_flags} -D_UNICODE -DUNICODE -DWIN32 -D_WIN32\")\n")   file(APPEND gtest.patch "     set(cxx_base_flags \"\${cxx_base_flags} -DSTRICT -DWIN32_LEAN_AND_MEAN\")\n")   file(APPEND gtest.patch "     set(cxx_exception_flags \"-EHsc -D_HAS_EXCEPTIONS=1\")\n") else()   file(WRITE gtest.patch "") endif()  # Enable ExternalProject CMake module include(ExternalProject)  # Set the build type if it isn't already if(NOT CMAKE_BUILD_TYPE)   set(CMAKE_BUILD_TYPE Release) endif()  # Set default ExternalProject root directory set_directory_properties(PROPERTIES EP_PREFIX ${CMAKE_BINARY_DIR}/ThirdParty)  # Add gtest ExternalProject_Add(     googletest     SVN_REPOSITORY http://googletest.googlecode.com/svn/trunk/     SVN_REVISION -r 660     TIMEOUT 10     PATCH_COMMAND svn patch ${CMAKE_SOURCE_DIR}/gtest.patch ${CMAKE_BINARY_DIR}/ThirdParty/src/googletest     # Force separate output paths for debug and release builds to allow easy     # identification of correct lib in subsequent TARGET_LINK_LIBRARIES commands     CMAKE_ARGS -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}                -DCMAKE_ARCHIVE_OUTPUT_DIRECTORY_DEBUG:PATH=DebugLibs                -DCMAKE_ARCHIVE_OUTPUT_DIRECTORY_RELEASE:PATH=ReleaseLibs                -Dgtest_force_shared_crt=ON     # Disable install step     INSTALL_COMMAND ""     # Wrap download, configure and build steps in a script to log output     LOG_DOWNLOAD ON     LOG_CONFIGURE ON     LOG_BUILD ON)  # Specify include dir ExternalProject_Get_Property(googletest source_dir) include_directories(${source_dir}/include)  # Add compiler flag for MSVC 2012 if(MSVC_VERSION EQUAL 1700)   add_definitions(-D_VARIADIC_MAX=10) endif()  # Add test executable target add_executable(MainTest ${PROJECT_SOURCE_DIR}/src/main.cpp)  # Create dependency of MainTest on googletest add_dependencies(MainTest googletest)  # Specify MainTest's link libraries ExternalProject_Get_Property(googletest binary_dir) if(MSVC)   set(Suffix ".lib") else()   set(Suffix ".a")   set(Pthread "-pthread") endif() target_link_libraries(     MainTest     debug ${binary_dir}/DebugLibs/${CMAKE_FIND_LIBRARY_PREFIXES}gtest${Suffix}     optimized ${binary_dir}/ReleaseLibs/${CMAKE_FIND_LIBRARY_PREFIXES}gtest${Suffix}     ${Pthread}) 

If you create this as CMakeLists.txt in an empty directory (say MyTest), then:

cd MyTest mkdir build cd build cmake .. 

This should create a basic main.cpp in MyTest/src and create a project file (MyTest/build/Test.sln on Windows)

When you build the project, it should download the gtest sources to MyTest/build/ThirdParty/src/googletest, and build them in MyTest/build/ThirdParty/src/googletest-build. You should then be able to run the MainTest target successfully.

like image 188
Fraser Avatar answered Sep 19 '22 21:09

Fraser


It is long past when the original question being asked, but for the benefit of others, 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 doesn't need to be installed anywhere.
  • 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. 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 it here:

https://crascit.com/2015/07/25/cmake-gtest/

Update: The approach described above is now also part of the googletest documentation.

like image 32
Craig Scott Avatar answered Sep 16 '22 21:09

Craig Scott