CMake: Adding GTest to Build
Asked Answered
P

2

6

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

Pension answered 3/11, 2019 at 6:10 Comment(3)
Does this solve your problem? Also, more discussion on this problem, and even more. Long story short: it seems like it was fixed before, but never merged.Larrylars
So it was fixed, you just had the wrong release? Anyway, glad it's working for you. You might want to put it in an answer, but you don't have to.Larrylars
Yeah, it was pretty comical how that ended up fixing the issue. I can't believe I didn't think of that yesterday! Thanks for the helpPension
P
6

This is what solved the issue for me.

Thanks to Chipster for doing more research into the issue and ultimately pushing me into the right direction.

Since the issue seemed to stem from release-1.8.0 containing some bugs that weren't merged into some other release, I figured that there must be a more recent release of googletest that I could reference in my CMake file that would have this issue resolved.

Lo and behold, only changing this to release-1.10.0 (latest at the time of writing this) from release-1.8.0 solved this specific issue for me:

test/CMakeLists.txt

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

For those of you wondering if removing the following lines will work with this solution and scenario so that you may build googlemock & googletest:

test/CMakeLists.txt

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

I tested this out also and I was able to build my test runner with these lines removed.

Pension answered 3/11, 2019 at 15:42 Comment(1)
For the sake of completeness: this solution works with CMake version 3.14 onwards (documentation of FetchContent module also describes an alternative compatible with CMake version 3.11). Have a look at my blog post for a step-by-step guide.Towboat
L
1

Your problem seems to not be with cmake itself, but rather you seem to be running into a warning getting treated as an error (instructions for Visual Studio. Could be different on another platform). You could turn off this setting, but obviously that's not always possible, and might not even be a good solution for your situation.

As to the warning itself, it appears to be known, and even fixed, but possibly never merged properly (though the thread may point to them trying to merge it, but the error still seems to remain).

Anyway, another possible workaround is to define the macro as the warning says:

#define _SILENCE_TR1_NAMESPACE_DEPRECATION_WARNING  1

But again, that's just a workaround. It still ultimately needs to get fixed, but that's obviously up to them to fix it.

Larrylars answered 3/11, 2019 at 6:37 Comment(2)
Thanks for the info. I'm going to use what you've given me when I have more time today.Pension
I think I was able to fix the issue I was seeing, but this answer wasn't what solved it. However, it did push me in the right direction, so you definitely deserve an upvote for that. I'll update my OP to include what solved the issue for me since it was comical and I expect that others will run into the same issue thanks to outdated tutorials.Pension

© 2022 - 2024 — McMap. All rights reserved.