0

First, I need to claim that I have been going around Stack Overflow and arrive answers of how to use ExternalProject to build Google Test within a project, for example here.

Now let's say what I have in my project is something like this

+-- CMakeLists.txt (the big CMake File for the entire project)
+-- tests
|    +-- CMakeLists.txt (contain of all the small project in the tests)
|    +-- Test1
|        +-- CMakeLists.txt (test file for Test1 program)
|        +-- test_1.cpp
|        +-- test_1.h
|    +-- Test2
|        +-- CMakeLists.txt (test file for Test2 program)
|        +-- test_2.cpp
|        +-- test_2.h
|    +-- Test3
|        +-- CMakeLists.txt (test file for Test3 program)
|        +-- test_3.cpp
|        +-- test_3.h

Now, is there anyway that I can configure and build Google Test using ExternalProject in the big CMakeLists.txt file (at the root folder), and then use those library to build each separate tests in their corresponding folder. At the moment I can only download-built-link an entire new set of GTest libraries in each of the sub folder Test1, Test2, Test3 which is very inefficient. Is there an alternative way to get around this?

Community
  • 1
  • 1

2 Answers2

0

It is unclear without seeing your actual CMakeLists.txt files what's happening in your case. That said, used in the normal way, ExternalProject doesn't give you the CMake targets to link to directly, you have to do more manual work to get something you can add to the linked library list of your targets needing to use GTest. So depending on how you've manually defined those things, that could be why you are finding you need to build GTest in each TestX subdirectory.

In the other SO question you linked to, my answer there and the linked article therein mentions how to download and build GTest as part of the CMake stage rather than at build time. This gives you the CMake targets which you can then link against directly without having to define them manually. If you follow that method to download and build GTest in your top level CMakeLists.txt file, then the gtest and gtest main targets will be visible to all subdirectories. Furthermore, you won't have to go figure out the name of the library for each platform, etc. since the CMake target already handles that for you. Thus, in your various Test1, Test2 and Test3 subdirectories, all you'd have to do is to add gtest or gtest_main to the list of libraries each test program linked against.

Community
  • 1
  • 1
Craig Scott
  • 9,238
  • 5
  • 56
  • 85
0

My approach is to create a directory at the same level of your test projects:

+-- CMakeLists.txt (the big CMake File for the entire project)
+-- tests
|    +-- CMakeLists.txt (contain of all the small project in the tests)
|    +-- gtest
|        +-- CMakeLists.txt (use ExternalProject_Add to import GTest)
|    +-- Test1
|        +-- CMakeLists.txt (test file for Test1 program)
|        +-- test_1.cpp
|        +-- test_1.h
|    +-- Test2
|        ...

In the CMakeLists.txt for gtest I define the gtest target and export the variables for the include dir and library path for the other projects to use.

It works for me and I get gtest built only once so all test projects can link against it. But I'll try to give a shot to Craig Scott's approach to build gtest during Makefile generation instead of at build time.

The CMakeLists.txt file under the gtest folder looks like this:

cmake_minimum_required(VERSION 2.8.11)

include(ExternalProject)

set(GMOCK_VERSION "1.7.0")
set(GMOCK_DIR "${CMAKE_CURRENT_BINARY_DIR}/gmock-${GMOCK_VERSION}")
ExternalProject_Add(project_gmock
    SVN_REPOSITORY http://googlemock.googlecode.com/svn/tags/release-${GMOCK_VERSION}
    PREFIX ${GMOCK_DIR}
    CMAKE_ARGS -DCMAKE_C_COMPILER:PATH=${CMAKE_C_COMPILER} -DCMAKE_CXX_COMPILER:PATH=${CMAKE_CXX_COMPILER}
    # Disable update step
    UPDATE_COMMAND ""
    # Disable install step
    INSTALL_COMMAND ""
)
ExternalProject_Get_Property(project_gmock source_dir)
ExternalProject_Get_Property(project_gmock binary_dir)

include_directories(${source_dir}/gtest/include)
add_library(gtest STATIC IMPORTED GLOBAL)
set_target_properties(gtest PROPERTIES IMPORTED_LOCATION ${binary_dir}/gtest/libgtest.a)
set_target_properties(gtest PROPERTIES INCLUDE_DIRECTORIES ${source_dir}/gtest/include)
add_dependencies(gtest project_gmock)
get_property(GTEST_INCLUDE_DIR TARGET gtest PROPERTY INCLUDE_DIRECTORIES)
set(GTEST_INCLUDE_DIR "${GTEST_INCLUDE_DIR}" PARENT_SCOPE)

add_library(gtest_main STATIC IMPORTED GLOBAL)
set_target_properties(gtest_main PROPERTIES IMPORTED_LOCATION ${binary_dir}/gtest/libgtest_main.a)
add_dependencies(gtest_main project_gmock)

include_directories(${source_dir}/include)
add_library(gmock STATIC IMPORTED GLOBAL)
set_target_properties(gmock PROPERTIES IMPORTED_LOCATION ${binary_dir}/libgmock.a)
set_target_properties(gmock PROPERTIES INCLUDE_DIRECTORIES ${source_dir}/include)
add_dependencies(gmock project_gmock)
get_property(GMOCK_INCLUDE_DIR TARGET gmock PROPERTY INCLUDE_DIRECTORIES)
set(GMOCK_INCLUDE_DIR "${GMOCK_INCLUDE_DIR}" PARENT_SCOPE)

add_library(gmock_main STATIC IMPORTED GLOBAL)
set_target_properties(gmock_main PROPERTIES IMPORTED_LOCATION ${binary_dir}/libgmock_main.a)
add_dependencies(gmock_main project_gmock)
Antonio Pérez
  • 6,702
  • 4
  • 36
  • 61