Google Test sets CMAKE_DEBUG_POSTFIX which is a global user variable.
This makes it impossible to use in a simple add_subdirectory case as it will break all the library names afterwards.
Instead, it should set DEBUG_POSTFIX for the gtest/gmock targets.
Consider using ExternalProject
Indeed I could. However changing it to set_target_property(gtest DEBUG_POSTFIX "d") is a trivial fix.
@ChrisKitching Could you point to where that is explained in the case of googletest? If I understand correctly that would build the googletest without adding the CMakeLists.txt in the parent project? (hence, no pollution)
ExternalProject, in a nutshell, defines a target which builds another project completely (and in some isolation). If that target is a cmake project, that means the buildsystem generated by your cmake run will itself call cmake, then make, for that target. Since this is a recursive invocation, it has its own variable scopes and so on, and is generally more resilient than including a thirdparty package's buildsystem directly into your own. If you're a bit creative, you can then wrap the generated artefacts in IMPORTED targets (a feature cmake really ought to automate, but never mind).
Below is a thorough description of how to do this, but note that use of find_package is almost always a better idea (find_package is how I use googletest in my own work).
I've linked the manual, and there are ample examples on the internet for how to use ExternalProject. The specifics w.r.t googletest will be the same as the steps you'd take to compile googletest as normal. You'll end up with something along the lines of:
# The place we point the install step of external build systems at.
set(EXTERNAL_PROJECT_PREFIX ${CMAKE_BINARY_DIR}/externals)
ExternalProject_Add(googletest_ext
# Only build Googletest if something actually needs it...
EXCLUDE_FROM_ALL 1
INSTALL_DIR ${EXTERNAL_PROJECT_PREFIX}
# Check the manual - there are lots of other ways of specifying the source to build from.
# It can do SVN, tarballs, zipfiles, anything you're likely to want.
GIT_REPOSITORY https://github.com/google/googletest.git
GIT_TAG release-1.8.0
CMAKE_ARGS
# Add whatever cmake args you want to give googletest here
-DBUILD_GMOCK=ON
-DBUILD_GTEST=ON
-DCMAKE_INSTALL_PREFIX:PATH=<INSTALL_DIR>
)
This will create a target googletest_ext which will build and install googletest into your cmake build tree at ${EXTERNAL_PROJECT_PREFIX}. A convenient next step is to wrap that with an imported project, something like:
add_library(googletest SHARED IMPORTED GLOBAL)
set_target_properties(googletest
IMPORTED_LOCATION ${EXTERNAL_PROJECT_PREFIX}/lib/${CMAKE_SHARED_LIBRARY_PREFIX}gtest${CMAKE_SHARED_LIBRARY_SUFFIX}
)
# Actually trigger building googletest when someone links against the IMPORTED target.
add_dependencies(googletest googletest_ext)
After that, you can just target_link_libraries(my_fancy_program googletest) as normal. Doing so will cause googletest to be built. If you never do so, googletest won't be needed, and hence won't be built. Remove the EXCLUDE_FROM_ALL line if you wish to unconditionally build googletest.
If you're targeting Windows, you'll also want to set IMPORTED_IMPLIB appropriately. You might like to refer to the other IMPORT_* properties on targets, and the documentation for IMPORTED targets.
You might also like to wrap this step up in a handy function, and support executables/static libraries as well (it is hopefully obvious how to do that). You might also need to introduce an extra step to cope with the possibility that thirdparty build systems put things in ./lib64 instead of ./lib - perhaps with the INSTALL_COMMAND argument to ExternalProject_Add.
You might also like to use install(FILES ...) or install(PROGRAMS ...) to copy the artefacts yielded from external projects to your own installation tree, as appropriate.
Hope this helps.
Most helpful comment
Indeed I could. However changing it to set_target_property(gtest DEBUG_POSTFIX "d") is a trivial fix.