Categories
Development

CMake: Adding GTest to Build

I’m trying to add googletest to my build using the FetchContent module, but I’ve come across many partial answers and have been unable to get where I want. There seems to be an excess of dated examples that use the ExternalProject module, but very few helpful examples that use the FetchContent module.

Here’s an incomplete list of references I’ve gone through today:

Here’s the file structure that I want to use:

-root
    -build
        -googletest-build
        -googletest-src
        -googletest-test
        -src
        -test
    -src
        -CMakeLists.txt
        -AllOfMySourceFiles
    -test
        -CMakeLists.txt
        -testgtest.cpp
    -CMakeLists.txt

These are the commands that I’m trying to use to build:

cmake ..
cmake --build .

So far, I’m able to link all of my source files into the dll that I want and I’m fairly confident that I know how to link it with the test exe that I want to use. The main issue I’m having is using the FetchContent module to build testgtest.cpp into an executable and link it with googletest. It keeps failing to build and the specific reason why it’s failing is not obvious at all.

root/CMakeLists.txt

cmake_minimum_required(VERSION 3.0)
set(CMAKE_CXX_FLAGS_RELEASE "/MT")
set(CMAKE_CXX_FLAGS_DEBUG "/MTd")
set(CMAKE_CXX_STANDARD 11)

set(LIBNAME "WTP")
set(TESTNAME "TestRunner")

set(LIB_MAJOR_VERS "0")
set(LIB_MINOR_VERS "0")
set(LIB_PATCH_VERS "0")

#build source
project(${LIBNAME} 
    VERSION  ${LIB_MAJOR_VERS}.${LIB_MINOR_VERS}.${LIB_PATCH_VERS})
add_subdirectory(src)

#build tests
project(${TESTNAME})

add_subdirectory(test)
enable_testing()
add_test(${TESTNAME} ${TESTNAME})

src/CMakeLists.txt

# Build output setup
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/src/lib)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/src/lib)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/src/bin)

#get all of the source files
set(SRCS Export.c
    Regions/ReferenceConstants.h
    Regions/Region1.h
    Regions/Region2.h
    Regions/Region3.h
    Regions/Boundaries/RegionBoundaries/R2andR3.h
    Regions/Boundaries/SubregionBoundaries/Region3/Boundaries_vTP.h)

add_library(${LIBNAME} SHARED ${SRCS})

This one is working as I intend it to so far.

test/CMakeLists.txt

# Build output setup
set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/test/lib)
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/test/lib)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/test/bin)

################################
# GTest
################################
project(googletest-git NONE)

include(FetchContent)
FetchContent_Declare(
  googletest
  GIT_REPOSITORY https://github.com/google/googletest.git
  GIT_TAG        release-1.8.0
)

set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
set(BUILD_GMOCK OFF CACHE BOOL "" FORCE)
set(BUILD_GTEST ON CACHE BOOL "" FORCE)

FetchContent_MakeAvailable(googletest)

################################
# Tests
################################
# Add test cpp file
add_executable(${TESTNAME} testgtest.cpp)
# Link test executable against gtest & gtest_main
target_link_libraries(${TESTNAME} gtest gtest_main)

I’m unclear on what I should be doing specifically here for A) using the FetchContent module to add googletest to my build AND B) linking my test executable with googletest.

test/testgtest.cpp

#include "gtest/gtest.h"

TEST(sample_test_case, sample_test)
{
    EXPECT_EQ(1, 1);
}

It’s not obvious what I should be #includeing specifically in testgtest.cpp, but I saw that in the examples I’ve seen so I figured that this is some obtuse, arcane magic that’s just supposed to work.

Here’s an output of what I’ve been seeing:

$ cmake --build .
Microsoft (R) Build Engine version 16.2.32702+c4012a063 for .NET Framework
Copyright (C) Microsoft Corporation. All rights reserved.

  gtest-all.cc
D:\root\build\_deps\googletest-src\googletest\include\gtest/internal/gtest-port.h(996,34): error C2220:  warning treated as error - no 'object' file generated [D:\root\build\_deps\googletest-build\googletest\gtest.vcxproj]
D:\root\build\_deps\googletest-src\googletest\include\gtest/internal/gtest-port.h(996,34): warning C4996:  'std::tr1': warning STL4002: The non-Standard std::tr1 namespace and TR1-only machinery are deprecated and will be REMOVED. You can define _SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING to acknowledge that you have received this warning. [D:\root\build\_deps\googletest-build\googletest\gtest.vcxproj]

The warning C4996 will then continue to just repeat ad nauseam until it finishes.

I do want to fetch googletest from git, so what do I need to be doing differently here to successfully build and use googletest with my tests?

Thanks for reading

One reply on “CMake: Adding GTest to Build”

You can silence the tr1 deprecation warnings by adding the following after the call to FetchContent_MakeAvailable():

“`
if(MSVC)
# Googletest tries to use things from std::tr1 but VS2017 has
# deprecated that, which issues warnings and these are sometimes
# treated as errors depending on developer settings. Prevent them.
target_compile_definitions(gtest PUBLIC _SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING)
target_compile_definitions(gtest_main PUBLIC _SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING)
target_compile_definitions(gmock PUBLIC _SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING)
target_compile_definitions(gmock_main PUBLIC _SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING)
endif()
“`

I’m not sure why you get the warning about no object for the gtest-port.h file. We don’t see that in our builds. The only things noticeably different in your project compared to ours are:

* We don’t set the /MT or MTd flags
* We explicitly set the CMP0048 and CMP0063 policies to NEW before we call FetchContent_MakeAvailable()
* We also set BUILD_SHARED_LIBS to OFF before we call FetchContent_MakeAvailable()

You also don’t need to be calling project() in all the different places you do. Just the very first one in the root level of your project should be sufficient.

Leave a Reply

Your email address will not be published. Required fields are marked *