Why does CMake not find GTest (Google Test)? - c++

There is a ready project. In one of the cmake-files there is a source code:
find_package(GTest REQUIRED)
if (NOT GTest_FOUND)
message(FATAL_ERROR "Cannot find Google Test Framework!")
endif()
Gives an error: "Cannot find Google Test Framework!"
How to fix error?

The FindGTest.cmake file uses the environment variable GTEST_ROOT.
You can add this variable to your system or just add it to your CMakeLists.txt file:
set(GTEST_ROOT "c:/path/to/gtest/root" CACHE PATH "path to gtest").
This should solve your problem. It is of course possible to completely add gtest to a project (like Luis Miglietti suggested), but thats maybe not what you want to do as a first try.

This could be useful for you so you don't have to depend on a local google test install, this should work independently if you have google test installed in your machine
You can add this to your cmake file (you should take care of the proper linking / include depending on your project structure)
This will download google test, configure the installation and build it in vendor/gtm/gtest (you could always change this) inside your main build folder. Then you can link gtest to an executable so you can run your tests from there
include(ExternalProject)
find_package(Git REQUIRED)
# Build googletest
ExternalProject_Add(
googletest
PREFIX "vendor/gtm"
GIT_REPOSITORY "https://github.com/google/googletest.git"
GIT_TAG release-1.8.0
TIMEOUT 10
CONFIGURE_COMMAND ""
BUILD_COMMAND ""
INSTALL_COMMAND ""
UPDATE_COMMAND ""
)
# Build gtest
ExternalProject_Add(
gtest_src
PREFIX "vendor/gtm"
SOURCE_DIR "vendor/gtm/src/googletest/googletest"
INSTALL_DIR "vendor/gtm/gtest"
CMAKE_ARGS
-DCMAKE_INSTALL_PREFIX=${CMAKE_BINARY_DIR}/vendor/gtm/gtest
-DCMAKE_C_COMPILER=${CMAKE_C_COMPILER}
-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}
-DCMAKE_CXX_FLAGS=${CMAKE_CXX_FLAGS}
DOWNLOAD_COMMAND ""
UPDATE_COMMAND ""
)
# Prepare gtest
ExternalProject_Get_Property(gtest_src install_dir)
set(GTEST_INCLUDE_DIR ${install_dir}/include)
set(GTEST_LIBRARY_PATH ${install_dir}/lib/libgtest.a)
file(MAKE_DIRECTORY ${GTEST_INCLUDE_DIR})
add_library(gtest STATIC IMPORTED)
set_property(TARGET gtest PROPERTY IMPORTED_LOCATION ${GTEST_LIBRARY_PATH})
set_property(TARGET gtest APPEND PROPERTY INTERFACE_INCLUDE_DIRECTORIES ${GTEST_INCLUDE_DIR})
add_dependencies(gtest_src googletest)
add_dependencies(gtest gtest_src)
Then you can link gtest to an executable with something like
add_executable(tester test/tester.cc)
target_link_libraries(tester gtest)
enable_testing()
add_test(<library> tester)

While CMake provides a FindGTest.cmake module since 2009...
I prefer to incorporate googletest in your CMake project like explaining in the googletest documentation.
https://github.com/google/googletest/tree/master/googletest#incorporating-into-an-existing-cmake-project
Note: a more detailed explanation http://crascit.com/2015/07/25/cmake-gtest/

Related

CMake Error: Unable to find package GTest [duplicate]

This question already has answers here:
How to start working with GTest and CMake
(11 answers)
Closed 2 years ago.
I am developing a C/C++ app using CMake. I want to use GTest in my project for unit testing. For this I have decided to use GTest as a git submodule in my repository.
My directory hierarchy is as follows:
/
--include
--lib
--GoogleTest
--src
--Tests
The GoogleTest subdirectory in lib contains the source code of GTest from their official repository.
But I am unable to use it to test my source. The CMakeLists.txt file at the root of my repository is as follows:
OPTION (BUILD_UNIT_TESTS "Build unit tests" ON)
if (BUILD_UNIT_TESTS)
enable_testing ()
find_package (GTest REQUIRED)
add_subdirectory (Tests)
endif ()
But I receive the error:
Error:Could NOT find GTest (missing: GTEST_LIBRARY GTEST_INCLUDE_DIR
GTEST_MAIN_LIBRARY)
When I searched for this, there were many questions similar to mine, but none of them addressed my problem. And their manual is very limited and does not tell much about its usage properly.
CMake is successfully able to build the target GTest but fails to recognise it when I try to use it as an external package.
You don't have to manually download the Gtest git. Just add the following lines to your CMakeLists.txt
# -------- GOOGLE TEST ----------
# Download and unpack googletest at configure time
configure_file(CMakeLists.txt.in googletest-download/CMakeLists.txt)
execute_process(COMMAND ${CMAKE_COMMAND} -G "${CMAKE_GENERATOR}" .
RESULT_VARIABLE result
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/googletest-download )
if(result)
message(FATAL_ERROR "CMake step for googletest failed: ${result}")
endif()
execute_process(COMMAND ${CMAKE_COMMAND} --build .
RESULT_VARIABLE result
WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/googletest-download )
if(result)
message(FATAL_ERROR "Build step for googletest failed: ${result}")
endif()
# Prevent overriding the parent project's compiler/linker
# settings on Windows
set(gtest_force_shared_crt ON CACHE BOOL "" FORCE)
# Add googletest directly to our build. This defines
# the gtest and gtest_main targets.
add_subdirectory(${CMAKE_CURRENT_BINARY_DIR}/googletest-src
${CMAKE_CURRENT_BINARY_DIR}/googletest-build
EXCLUDE_FROM_ALL)
# The gtest/gtest_main targets carry header search path
# dependencies automatically when using CMake 2.8.11 or
# later. Otherwise we have to add them here ourselves.
if (CMAKE_VERSION VERSION_LESS 2.8.11)
include_directories("${gtest_SOURCE_DIR}/include")
endif()
# -------------------------------------------------------------------------
enable_testing()
include_directories("${gtest_SOURCE_DIR}/include")
And add the following lines to another file, named CMakeLists.txt.in, in the same directory your CMakeLists.txt file is
cmake_minimum_required(VERSION 2.8.2)
project(googletest-download NONE)
include(ExternalProject)
ExternalProject_Add(googletest
GIT_REPOSITORY https://github.com/google/googletest.git
GIT_TAG release-1.10.0
SOURCE_DIR "${CMAKE_CURRENT_BINARY_DIR}/googletest-src"
BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/googletest-build"
CONFIGURE_COMMAND ""
BUILD_COMMAND ""
INSTALL_COMMAND ""
TEST_COMMAND ""
)
What does it do ?
The things you added to your main CMakeLists will download GTest and GMock git projects at the version specified in the CMakeLists.txt.in file. Then it will build these, and include the build path in your main project.
Source : GoogleTest Git

Building mongo-cxx-driver using CMake ExternalProject_Add

I am trying to build mongo-cxx-driver in a CMake based project. This project is supposed to build on Windows, macOS and in an ubuntu container and I want to ensure that my software on all these platforms will use the same driver version so I cannot afford installing the driver and its dependencies via apt-get, brew etc. So I am left with one option: ExternalProject_Add. But I am having difficulty making that work given how libmongoc is setup.
Below is the CMake module I currently have.
include(ExternalProject)
set(libmongoc_CMAKE_ARGS
"-DCMAKE_BUILD_TYPE:STRIING=${CMAKE_BUILD_TYPE}"
"-DENABLE_TESTS:BOOL=OFF"
"-DENABLE_STATIC:BOOL=OFF"
"-DENABLE_EXAMPLES:BOOL=OFF"
"-DENABLE_EXTRA_ALIGNMENT:BOOL=OFF"
)
set(mongocxx_CMAKE_ARGS
"-DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER}"
"-DCMAKE_BUILD_TYPE:STRIING=${CMAKE_BUILD_TYPE}"
"-DBUILD_SHARED_LIBS:BOOL=ON"
"-DENABLE_TESTS:BOOL=OFF"
"-DENABLE_EXAMPLES:BOOL=OFF"
"-DBSONCXX_POLY_USE_BOOST:BOOL=ON"
"-DBSONCXX_POLY_USE_MNMLSTC:BOOL=OFF"
"-Dlibbson-1.0_DIR:PATH=${OTS_DEPDENDENCIES_DIR}/libmongoc/src/libbson"
)
if (NOT TARGET libmongoc)
ExternalProject_Add(
libmongoc
GIT_REPOSITORY "https://github.com/mongodb/mongo-c-driver.git"
GIT_TAG "1.12.0"
SOURCE_DIR "${OTS_DEPDENDENCIES_DIR}/libmongoc"
BINARY_DIR "${OTS_DEPDENDENCIES_DIR}/libmongoc"
CMAKE_ARGS "${libmongoc_CMAKE_ARGS}"
INSTALL_COMMAND ""
)
endif()
if (NOT TARGET mongocxx)
ExternalProject_Add(
mongocxx
GIT_REPOSITORY "https://github.com/mongodb/mongo-cxx-driver.git"
GIT_TAG "r3.3.1"
SOURCE_DIR "${OTS_DEPDENDENCIES_DIR}/mongocxx"
BINARY_DIR "${OTS_DEPDENDENCIES_DIR}/mongocxx"
CMAKE_ARGS "${mongocxx_CMAKE_ARGS}"
INSTALL_COMMAND ""
DEPENDS libmongoc
)
endif()
Note the CMAKE option libbson-1.0_DIR given as one of the CMAKE_ARGS for mongo-cxx-driver. I am skeptic about it and I believe that may be the culprit. With it I get the following error:
CMake Error at ${OTS_DEPENDENCIES_DIR}/libmongoc/src/libbson/libbson-1.0-config.cmake:30 (message):
File or directory
${OTS_DEPENDENCIES_DIR}/include/libbson-1.0
referenced by variable BSON_INCLUDE_DIRS does not exist !
Call Stack (most recent call first):
${OTS_DEPENDENCIES_DIR}/libmongoc/src/libbson/libbson-1.0-config.cmake:46 (set_and_check)
src/bsoncxx/CMakeLists.txt:81 (find_package)
which kind of makes sense because src/bsoncxx/CMakeLists.txt:81 reads:
get_filename_component(PACKAGE_PREFIX_DIR "${CMAKE_CURRENT_LIST_DIR}/../../../" ABSOLUTE)
set_and_check (BSON_INCLUDE_DIRS "${PACKAGE_PREFIX_DIR}/include/libbson-1.0")
which makes CMake end up looking for libbson-1.0 in ${OTS_DEPDENDENCIES_DIR}/include that does not exist. If only, I could tell cmake, "hey don't run this find_package" I can give you the path to INCLUDE_DIR, LIBRARIES and DEFINITIONS myself.
If I remove this option, I get the following error:
CMake Error at src/bsoncxx/CMakeLists.txt:81 (find_package):
By not providing "Findlibbson-1.0.cmake" in CMAKE_MODULE_PATH this project
has asked CMake to find a package configuration file provided by
"libbson-1.0", but CMake did not find one.
Could not find a package configuration file provided by "libbson-1.0"
(requested version 1.10.0) with any of the following names:
libbson-1.0Config.cmake
libbson-1.0-config.cmake
Add the installation prefix of "libbson-1.0" to CMAKE_PREFIX_PATH or set
"libbson-1.0_DIR" to a directory containing one of the above files. If
"libbson-1.0" provides a separate development package or SDK, be sure it
has been installed.
which is not very odd either because CMake tries to find_package libbson-1.0 but cannot figure out where it is installed.
preliminary remarks
While looking at the details, here are few preliminary comments:
Use different directory for SOURCE_DIR and BINARY_DIR
Instead of CMAKE_ARG, prefer CMAKE_CACHE_ARGS
libbson-1.0_DIR should NOT be set to a source directory, instead if should be set to a build directory containing a config-file package (link below provide more details about this concept)
Make sure to always specify the type of CMake argument (-DCMAKE_CXX_COMPILER:PATH=${CMAKE_CXX_COMPILER} instead of -DCMAKE_CXX_COMPILER=${CMAKE_CXX_COMPILER})
Do not set CMAKE_BUILD_TYPE for multi-configuration generator
Regarding this last point, this means that you should do the following:
set(EXTERNAL_PROJECT_OPTIONAL_CMAKE_CACHE_ARGS)
if(NOT DEFINED CMAKE_CONFIGURATION_TYPES)
list(APPEND EXTERNAL_PROJECT_OPTIONAL_CMAKE_CACHE_ARGS
-DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE}
)
endif()
In this post, you can learn how you could structure your project: Correct way to use third-party libraries in cmake project
working project allowing to compile the mongocxx "test.cpp"
Below is the content of CMakeLists.txt and test.cpp allowing to build an executable named <build-dir>/Test-build/test_mongocxx :
CMakeLists.txt:
cmake_minimum_required(VERSION 3.12)
set(CMAKE_CXX_STANDARD 11)
project(Test)
option(${PROJECT_NAME}_SUPERBUILD "Build ${PROJECT_NAME} and the projects it depends on." ON)
if(${PROJECT_NAME}_SUPERBUILD)
include(ExternalProject)
set(common_cmake_cache_args
-DCMAKE_CXX_COMPILER:PATH=${CMAKE_CXX_COMPILER}
)
if(NOT DEFINED CMAKE_CONFIGURATION_TYPES)
list(APPEND common_cmake_cache_args
-DCMAKE_BUILD_TYPE:STRING=${CMAKE_BUILD_TYPE}
)
endif()
ExternalProject_Add(libmongoc
GIT_REPOSITORY "https://github.com/mongodb/mongo-c-driver.git"
GIT_TAG "1.12.0"
GIT_PROGRESS 1
GIT_SHALLOW 1
SOURCE_DIR "${CMAKE_BINARY_DIR}/libmongoc"
BINARY_DIR "${CMAKE_BINARY_DIR}/libmongoc-build"
INSTALL_DIR "${CMAKE_BINARY_DIR}/libmongoc-install"
CMAKE_CACHE_ARGS
${common_cmake_cache_args}
-DCMAKE_INSTALL_PREFIX:PATH=${CMAKE_BINARY_DIR}/libmongoc-install
-DENABLE_TESTS:BOOL=OFF
-DENABLE_STATIC:BOOL=OFF
-DENABLE_EXAMPLES:BOOL=OFF
-DENABLE_EXTRA_ALIGNMENT:BOOL=OFF
#INSTALL_COMMAND ""
)
set(libmongoc-1.0_DIR "${CMAKE_BINARY_DIR}/libmongoc-install/lib/cmake/libmongoc-1.0/")
set(libbson-1.0_DIR "${CMAKE_BINARY_DIR}/libmongoc-install/lib/cmake/libbson-1.0/")
ExternalProject_Add(libmongocxx
GIT_REPOSITORY "https://github.com/mongodb/mongo-cxx-driver.git"
GIT_TAG "r3.3.1"
GIT_PROGRESS 1
GIT_SHALLOW 1
SOURCE_DIR "${CMAKE_BINARY_DIR}/libmongocxx"
BINARY_DIR "${CMAKE_BINARY_DIR}/libmongocxx-build"
INSTALL_DIR "${CMAKE_BINARY_DIR}/libmongocxx-install"
CMAKE_CACHE_ARGS
${common_cmake_cache_args}
-DCMAKE_INSTALL_PREFIX:PATH=${CMAKE_BINARY_DIR}/libmongocxx-install
-DBUILD_SHARED_LIBS:BOOL=ON
-DENABLE_TESTS:BOOL=OFF
-DENABLE_EXAMPLES:BOOL=OFF
-DBSONCXX_POLY_USE_BOOST:BOOL=OFF
-DBSONCXX_POLY_USE_MNMLSTC:BOOL=ON
-DBSONCXX_POLY_USE_STD:BOOL=OFF
-Dlibmongoc-1.0_DIR:PATH=${libmongoc-1.0_DIR}
-Dlibbson-1.0_DIR:PATH=${libbson-1.0_DIR}
DEPENDS
libmongoc
)
set(libmongocxx_DIR "${CMAKE_BINARY_DIR}/libmongocxx-install/lib/cmake/libmongocxx-3.3.1/")
set(libbsoncxx_DIR "${CMAKE_BINARY_DIR}/libmongocxx-install//lib/cmake/libbsoncxx-3.3.1/")
function(ExternalProject_AlwaysConfigure proj)
# This custom external project step forces the configure and later
# steps to run.
_ep_get_step_stampfile(${proj} "configure" stampfile)
ExternalProject_Add_Step(${proj} forceconfigure
COMMAND ${CMAKE_COMMAND} -E remove ${stampfile}
COMMENT "Forcing configure step for '${proj}'"
DEPENDEES build
ALWAYS 1
)
endfunction()
ExternalProject_Add(${PROJECT_NAME}
SOURCE_DIR "${CMAKE_SOURCE_DIR}"
BINARY_DIR "${CMAKE_BINARY_DIR}/${PROJECT_NAME}-build"
DOWNLOAD_COMMAND ""
UPDATE_COMMAND ""
CMAKE_CACHE_ARGS
${common_cmake_cache_args}
-D${PROJECT_NAME}_SUPERBUILD:BOOL=OFF
-Dlibbsoncxx_DIR:PATH=${libbsoncxx_DIR}
-Dlibmongocxx_DIR:PATH=${libmongocxx_DIR}
INSTALL_COMMAND ""
DEPENDS
libmongocxx
)
ExternalProject_AlwaysConfigure(${PROJECT_NAME})
return()
endif()
message(STATUS "Configuring inner-build")
find_package(libmongocxx REQUIRED)
add_executable(test_mongocxx test.cpp)
target_link_libraries(test_mongocxx PUBLIC ${LIBMONGOCXX_LIBRARIES})
target_include_directories(test_mongocxx PUBLIC ${LIBMONGOCXX_INCLUDE_DIRS})
target_compile_definitions(test_mongocxx PUBLIC ${LIBMONGOCXX_DEFINITIONS})
test.cpp (copied from https://mongodb.github.io/mongo-cxx-driver/mongocxx-v3/installation/#step-6-test-your-installation):
#include <iostream>
#include <bsoncxx/builder/stream/document.hpp>
#include <bsoncxx/json.hpp>
#include <mongocxx/client.hpp>
#include <mongocxx/instance.hpp>
int main(int, char**) {
mongocxx::instance inst{};
mongocxx::client conn{mongocxx::uri{}};
bsoncxx::builder::stream::document document{};
auto collection = conn["testdb"]["testcollection"];
document << "hello" << "world";
collection.insert_one(document.view());
auto cursor = collection.find({});
for (auto&& doc : cursor) {
std::cout << bsoncxx::to_json(doc) << std::endl;
}
}

CMake: rebuild external project

I have a project that uses an external library. The project's CMakeLists.txt looks like this:
cmake_minimum_required(VERSION 3.6.0)
project(my-project)
set(CMAKE_CXX_STANDARD 14)
include(ExternalProject)
find_package(Git REQUIRED)
ExternalProject_Add(library
PREFIX ${my-project_SOURCE_DIR}/lib/library
GIT_REPOSITORY https://github.com/vendor/library
GIT_TAG master
UPDATE_COMMAND ""
INSTALL_COMMAND ""
)
link_directories(${my-project_SOURCE_DIR}/lib/library/src/library-build/src)
add_subdirectory(src)
And src/CMakeLists.txt like this:
include_directories(../lib/library/src/library/include)
add_executable(my-project
main.cpp
)
add_dependencies(my-project library)
target_link_libraries(my-project liblibrary.a)
It pulls the library from Git and builds it for the first time without any problems.
I want to edit source code of the library and have the library .a file be recompiled automatically. What is the cleanest way I can achieve that? It currently ignores any updates to the source code, because it already has .a file of the library.
When I try to add
add_subdirectory(lib/library/src/library/src)
to my main CMakeLists.txt, I get the following error:
CMake Error at lib/library/src/library/src/CMakeLists.txt:55 (add_library): add_library cannot create target "library" because another target with the same name already exists. The existing target is a custom target created in source directory "/cygdrive/c/Code/my-project". See documentation for policy CMP0002 for more details.
I guess it's caused by calling
add_library(gram STATIC ${SOURCE_FILES})
in the library CMakeLists.txt and then calling
ExternalProject_Add(library ...)
in the project CMakeLists.txt.
Any ideas?
As your main goal for using ExternalProject_Add is to download the dependency from an external source without configuring and building it, you could define the CMAKE_COMMAND, CONFIGURE_COMMAND and BUILD_COMMAND as empty strings. Same as you already did for the UPDATE_COMMAND and INSTALL_COMMAND. That way, ExternalProject_Add will only clone the repository once.
To overcome the name clash, just use a different one for the first argument of ExternalProject_Add, e.g. library_src:
ExternalProject_Add(library_src
PREFIX ${my-project_SOURCE_DIR}/lib/library
GIT_REPOSITORY https://github.com/vendor/library
GIT_TAG master
UPDATE_COMMAND ""
CONFIGURE_COMMAND ""
CMAKE_COMMAND ""
BUILD_COMMAND ""
INSTALL_COMMAND ""
)
ExternalProject_Get_Property(library_src SOURCE_DIR)
add_subdirectory(${SOURCE_DIR})
The second command (ExternalProject_Get_Property) will give you the named properties for the given external project. The output variables are of the same name as the properties. That way, you are immune against changes in the behaviour of ExternalProject_Add where it places the actual source tree.
add this command in ExternalProject_Add maybe help you:
UPDATE_COMMAND ""
https://gitlab.kitware.com/cmake/cmake/issues/16419

How to clone and integrate external (from git) cmake project into local one

I faced with a problem when I was trying to use Google Test.
There are lot of manuals on how to use ExternalProject_Add for the adding gtest into the project, however most of these describe a method based on downloading zip archive with gtest and build it.
As we know gtest is github-hosted and cmake-based project. So I'd like to find native cmake way.
If this would be a header-only project, I'd write something like:
cmake_minimum_required(VERSION 2.8.8)
include(ExternalProject)
find_package(Git REQUIRED)
ExternalProject_Add(
gtest
PREFIX ${CMAKE_CURRENT_SOURCE_DIR}/ext
GIT_REPOSITORY https://github.com/google/googletest.git
TIMEOUT 10
UPDATE_COMMAND ${GIT_EXECUTABLE} pull
CONFIGURE_COMMAND ""
BUILD_COMMAND ""
INSTALL_COMMAND ""
LOG_DOWNLOAD ON
)
ExternalProject_Get_Property(gtest source_dir)
set(GTEST_INCLUDE_DIR ${source_dir}/googletest/include CACHE INTERNAL "Path to include folder for GTest")
set(GTEST_ROOT_DIR ${source_dir}/googletest CACHE INTERNAL "Path to source folder for GTest")
include_directories(${INCLUDE_DIRECTORIES} ${GTEST_INCLUDE_DIR} ${GTEST_ROOT_DIR})
message(${GTEST_INCLUDE_DIR})
and add this script from my cmake project like:
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake.modules/")
include(AddGTest)
....
add_dependencies(${PROJECT_NAME} gtest)
However this requires a build step.
How should this be implemented?
By adding BUILD_COMMAND into ExternaProject_Add and linking with produced libs?
Or by including gtest's cmakelists into my project, something like this:
add_subdirectory (${CMAKE_SOURCE_DIR}\ext\src\gtest\googletest\CMakeLists.txt)
this is not correct way because on the moment of the project load the folder does not exist.
Any other ways?
What is a correct/prefer way?
I would go with the first approach. You don't need to specify a build command because cmake is used by default. This could look like:
cmake_minimum_required(VERSION 3.0)
project(GTestProject)
include(ExternalProject)
set(EXTERNAL_INSTALL_LOCATION ${CMAKE_BINARY_DIR}/external)
ExternalProject_Add(googletest
GIT_REPOSITORY https://github.com/google/googletest
CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${EXTERNAL_INSTALL_LOCATION}
)
include_directories(${EXTERNAL_INSTALL_LOCATION}/include)
link_directories(${EXTERNAL_INSTALL_LOCATION}/lib)
add_executable(FirstTest main.cpp)
add_dependencies(FirstTest googletest)
target_link_libraries(FirstTest gtest gtest_main pthread)
I don't know if this is the correct/preferred way if there even is one. If you wanted to implement your second approach you would have to download the code with execute_process first.

CMake ExternalProject_Add and parallel builds

With the following CMakeLists.txt build script:
include( ExternalProject )
ExternalProject_Add( framework SOURCE_DIR ${framework_SOURCE}
PREFIX framework_build
INSTALL_DIR ${framework_DISTRIBUTION} )
...
add_library( ${PROJECT_NAME} SHARED ${BUILD_MANIFEST} )
add_dependencies( ${PROJECT_NAME} framework )
When I attempt to perform a parallel build (make -j5) it will occasionally fail due to a build artefact from the framework not being present. The order of the build, fixed by add_dependencies, is not being adhered to.
Have I misunderstood the documentation around add_dependencies?
Output from cmake --graphviz=graph.dot
Ok, so an updated version of CMake has warned me that the framework dependency is not present. ExternalProject_Add and add_dependencies can not be used with each other, as ExternalProject_Add has not actually built and therefore registered the framework as a high-level target.
Note:
Anyone encountering this problem in future. I've found another SO post by #matiu that resolved my issue.
Maybe ExternalProject_Add_StepDependencies could solve that and create a dependency between the externalproject_add and the imported target?
This is a minimal working example adding Google test as a dependency.
cmake_minimum_required(VERSION 2.8)
project(ExampleProject)
# Set the build type if it isn't already
if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Debug)
endif()
include(ExternalProject)
set(GOOGLE_TEST GoogleTest)
set(GTEST_PREFIX "${CMAKE_CURRENT_BINARY_DIR}/${GOOGLE_TEST}")
ExternalProject_Add(${GOOGLE_TEST}
GIT_REPOSITORY https://chromium.googlesource.com/external/googletest
PREFIX ${GTEST_PREFIX}
CMAKE_ARGS -DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}
INSTALL_COMMAND ""
)
# Specify include directory
ExternalProject_Get_Property(${GOOGLE_TEST} source_dir)
include_directories(${source_dir}/include)
set(LIBPREFIX "${CMAKE_STATIC_LIBRARY_PREFIX}")
set(LIBSUFFIX "${CMAKE_STATIC_LIBRARY_SUFFIX}")
set(GTEST_LOCATION "${GTEST_PREFIX}/src/${GOOGLE_TEST}-build")
set(GTEST_LIBRARY "${GTEST_LOCATION}/${LIBPREFIX}gtest${LIBSUFFIX}")
set(EXECUTABLE_NAME ${CMAKE_PROJECT_NAME})
add_executable(${EXECUTABLE_NAME} main.cpp)
add_dependencies(${EXECUTABLE_NAME} ${GOOGLE_TEST})
target_link_libraries(
${EXECUTABLE_NAME}
${GTEST_LIBRARY}
-lpthread
)
enable_testing()
set(TEST_NAME ${EXECUTABLE_NAME})
add_test(${EXECUTABLE_NAME} ${TEST_NAME})
And this is the dependency graph:
In this case without add_dependencies a parallel build will always fail, because of missing the dependency.