Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CMake conflict with multiple gtest

This is my first post on StackOverflow, so apologies if there's something wrong with my question.

I'm new at CMake, and I'm running into a problem trying to import gtest (Google Test) in a C++ project with an existing gtest directory used within a library.

My root CMakeLists.txt file is this (My changes are made between "Begin changes" and "End changes") :

cmake_minimum_required(VERSION 2.6)

project(nifi-minifi-cpp)
set(PROJECT_NAME "nifi-minifi-cpp")
set(PROJECT_VERSION_MAJOR 0)
set(PROJECT_VERSION_MINOR 2)
set(PROJECT_VERSION_PATCH 0)

#### Establish Project Configuration ####
# Enable usage of the VERSION specifier
# https://cmake.org/cmake/help/v3.0/policy/CMP0048.html#policy:CMP0048
IF(POLICY CMP0048)
  CMAKE_POLICY(SET CMP0048 OLD)
ENDIF(POLICY CMP0048)

include(CheckCXXCompilerFlag)
CHECK_CXX_COMPILER_FLAG("-std=c++11" COMPILER_SUPPORTS_CXX11)
CHECK_CXX_COMPILER_FLAG("-std=c++0x" COMPILER_SUPPORTS_CXX0X)
if(COMPILER_SUPPORTS_CXX11)
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
elseif(COMPILER_SUPPORTS_CXX0X)
    set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x")
else()
        message(STATUS "The compiler ${CMAKE_CXX_COMPILER} has no C++11 support. Please use a different C++ compiler.")
endif()

set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

# Search for threads
find_package(Threads REQUIRED)

# Provide custom modules for the project
list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake")

add_subdirectory(thirdparty/yaml-cpp-yaml-cpp-0.5.3)
add_subdirectory(libminifi)
add_subdirectory(main)

# Generate source assembly
set(ASSEMBLY_BASE_NAME "${CMAKE_PROJECT_NAME}-${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}")
set(CPACK_SOURCE_GENERATOR "TGZ")
set(CPACK_SOURCE_PACKAGE_FILE_NAME "${ASSEMBLY_BASE_NAME}-source")
set(CPACK_SOURCE_IGNORE_FILES "/build/;~$;${CPACK_SOURCE_IGNORE_FILES};${CMAKE_SOURCE_DIR}/.git/;${CMAKE_SOURCE_DIR}/.idea/;${CMAKE_SOURCE_DIR}/cmake-build-debug/")

# Generate binary assembly
install(FILES conf/minifi.properties conf/config.yml
        DESTINATION conf
        COMPONENT bin)

install(PROGRAMS bin/minifi.sh
        DESTINATION bin
        COMPONENT bin)

install(FILES LICENSE README.md NOTICE
        DESTINATION .
        COMPONENT bin)

set(CPACK_GENERATOR "TGZ")
set(CPACK_COMPONENT_INCLUDE_TOPLEVEL_DIRECTORY 1)
set(CPACK_PACKAGE_DESCRIPTION_SUMMARY "Apache NiFi MiNiFi C++ version ${VERSION}")
set(CPACK_PACKAGE_VENDOR "Apache NiFi")
set(CPACK_PACKAGE_DESCRIPTION_FILE "${CMAKE_CURRENT_SOURCE_DIR}/README.md")
set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE")
set(CPACK_PACKAGE_FILE_NAME "${ASSEMBLY_BASE_NAME}")
set(CPACK_BINARY_TGZ, "ON")

set(CPACK_ARCHIVE_COMPONENT_INSTALL ON)
set(CPACK_COMPONENTS_ALL bin)

include(CPack)

#### Begin changes
# Set up testing
enable_testing()
set(GTEST_ROOT "thirdparty/googletest/googletest")
add_subdirectory(thirdparty/googletest)
#
find_package(GTest REQUIRED)
include_directories(${GTEST_INCLUDE_DIRS})
add_executable(tailFileTest
        test/TailFileTest.cpp
        )
target_link_libraries(tailFileTest  ${GTEST_LIBRARY_DEBUG} ${GTEST_MAIN_LIBRARY_DEBUG})

add_test(
        NAME tailFileTest
        COMMAND tailFileTest
)


#add_dependencies(${PROJECT_TEST_NAME} googletest)

#set(PROJECT_TEST_NAME ${PROJECT_NAME}_test)
#file(GLOB TEST_SRC_FILES ${PROJECT_SOURCE_DIR}/test/*.cpp)
#
#add_executable(${PROJECT_TEST_NAME} ${TEST_SRC_FILES})
#add_dependencies(${PROJECT_TEST_NAME} googletest)
#### End changes

And output from CMake when running cmake .. (the more relevant error message - probably) is:

CMake Error at thirdparty/googletest/googletest/cmake/internal_utils.cmake:151 (add_library):
  add_library cannot create target "gtest" because another target with the
  same name already exists.  The existing target is a static library created
  in source directory
  "/home/dev/nifi-minifi-cpp/thirdparty/yaml-cpp-yaml-cpp-0.5.3/test/gmock-1.7.0/gtest".
  See documentation for policy CMP0002 for more details.

Currently, I've got a copy of googletest in:

/home/g/dev/nifi-minifi-cpp/thirdparty/googletest

And the existing googletest directory is within:

/home/g/dev/nifi-minifi-cpp/thirdparty/yaml-cpp-yaml-cpp-0.5.3/test/gmock-1.7.0

Here's a quick picture of the directory structure:

.
├── CMakeLists.txt
├── test                             [<- My directory to store and run tests]
└── thirdparty
    ├── googletest                   [<- My googletest directory]
    └── yaml-cpp-yaml-cpp-0.5.3
        ├── test
        │   ├── CMakeLists.txt
        │   ├── gmock-1.7.0          [<- The existing googletest directory]

278 directories, 2096 files

The overall goal is to have a test directory for running tests.

Any suggestions or clues to what I'm doing wrong, or what I should be doing, would be greatly appreciated. Hopefully the above explains the challenge I'm facing, and if there's a file or error message people think I'm missing that would help I can paste it in here.

like image 485
Capsicumber Avatar asked Feb 07 '17 08:02

Capsicumber


1 Answers

This is just double including 3d-party project (gtest in your case) using add_subdirectory. The first include point is

add_subdirectory(gmock-1.7.0)    

inside yaml-cpp subproject and the second include point is

add_subdirectory(thirdparty/googletest)

in your CMakeLists.txt.

Such double including doesn't work in CMake, so you need to eliminate one of add_subdirectory call.

  1. In your code, you may replace add_subdirectory approach by combination of ExternalProject_Add and execute_process. That approach will build googletest on configuration stage (so, find_package(GTest) will work), but doesn't pollute namespace of your project with targets from googletest.

  2. In other project (yaml-cpp), you may eliminate including googletest by disable testing. Just disable appropriate option

    option(YAML_CPP_BUILD_TOOLS "Enable testing and parse tools" OFF)
    

    before

    add_subdirectory(thirdparty/yaml-cpp-yaml-cpp-0.5.3)
    

    (For disabling option from CMakeLists.txt you need to reconfigure the whole project cleanly, that is with empty CMake cache).

    Note, that this option also disables some utilities under util/ subdirectory of yaml-cpp project.

  3. Similarly to the first approach, you may change inclusion of yaml-cpp subproject to ExternalProject_Add + execute_process. Such a way all its targets and targets of its subprojects will not pollute namespace of your project.

like image 150
Tsyvarev Avatar answered Sep 19 '22 05:09

Tsyvarev