Googletest: Make installation optional

Created on 3 Sep 2016  路  10Comments  路  Source: google/googletest

The user may link statically and avoid overriding system libraries and headers.
Maybe via GTEST_INSTALL or some other options can be provided for optional installation.

Most helpful comment

@rakhimov Would the EXCLUDE_FROM_ALL option of the add_subdirectory command be helpful for your situation?

All 10 comments

In a linux based system, if you want to install into an alternate location to avoid clobbering a system installed version of googletest/mock, run:

mkdir build
cd build
cmake ../ -DCMAKE_INSTALL_PREFIX=~/myprefix/
make -j8
make install

You can also use ccmake .. to bring up a console UI for editing these values in your CMakeCache.txt as well. You just then need to tell your build system where to find these libraries and the path to include for finding the includes when you build with something like gcc or clang.

@gyund I mean the case when gtest is used as submodule in a project source/build.
People tend to issue make install right away without specifying targets,
and gtest targets happily move with the project binaries.

If we had an option like GTEST_INSTALL,
the root project can disable this.
Another option would be to find a way to make installation optional with CMake
so that it would install only and only if the target specified explicitly, i.e., make install gtest.

Ah ok, I see what you're saying. Because when you do an install, you don't necessarily want to install libraries or header files that are only used as part of testing.

As an alternate mechanic if you're using cmake for your project, and I've used this before, check out:
https://cmake.org/cmake/help/v3.0/module/ExternalProject.html

You can tell cmake to checkout the project and as part of the configuration, you can also provide that checkout a separate install path. So for instance, the install path could be in your build directory, which then your project could reference as a source for including to build your tests. Example:

ExternalProject_Add(googletest
   PREFIX "${CMAKE_CURRENT_BINARY_DIR}/googletest"
   GIT_REPOSITORY [email protected]:google/googletest.git
   INSTALL_DIR "${CMAKE_BINARY_DIR}"
   CMAKE_ARGS "-DCMAKE_INSTALL_PREFIX=${CMAKE_BINARY_DIR}"
   GIT_TAG release-1.8.0

Then add "googletest" as a dependency using the add_dependencies to your test executable
Not fully tested but the spirit of what's involved is there :).

If you aren't using cmake for your project, then as you were saying, you'd either need some extra build flag or some other way to tell your build system to build/install it as part of your build process but not install process. ie. don't use add_subdirectory to include your googletest project dependencies.

Thanks a lot @gyund , this is insightful!

Even though this seems to be the proper way,
add_subdirectory seems a lot easier to configure.
I am almost there with project_add,
but cannot get linking right with gtest generated static libs.
Do I need to get some special linker flags from gtest config (pthread and whatnot)?

There are only two possibilities I can think of when installation of gtest may be reasonable:
The first is when "gtest" is built by itself as the main project.

if("${CMAKE_PROJECT_NAME}" STREQUAL "gtest")
  # installation instructions
endif()

The second is gtest is built as shared as a part of another project.
For example, some projects spread over multiple repos with some main repo providing gtest libs.
BUILD_SHARED is OFF by default, so folks have to hack it themselves.

@rakhimov When I use gtest, I typically install it as part of setting up a VM for development, so the traditional install works just fine. You'll have to tweak the script a bit to search alternate paths, but I end up doing:

find_package(GTest REQUIRED)
find_library(GMOCK_LIBRARY NAMES libgmock.a)
if(GMOCK_LIBRARY-NOTFOUND)
   message(FATAL_ERROR "gmock library not found")
endif()

include_directories( 
  ${CMAKE_SOURCE_DIR}/lib/mylib
  ${GTEST_INCLUDE_DIRS}
)

file (GLOB_RECURSE TEST_SOURCE_FILES_UNIT "*.cpp")
add_executable(test-unit ${TEST_SOURCE_FILES_UNIT})
target_link_libraries(test-unit my_library_under_test ${GTEST_BOTH_LIBRARIES} ${GMOCK_LIBRARY})

Some of the mock stuff may not be necessary as this is somewhat legacy from back when gmock and google test were in different repositories with different build systems, but you get the idea. You have to tell the compiler where to find the headers and also tell it to link in the static libraries of google-test with your unit tests. my_library_under_test is whatever you're calling the library part of your application you want to link against to test. ${CMAKE_SOURCE_DIR}/lib/mylib tells cmake to look at the root of the CMake project in the directory lib/mylib, where your other header and c/cpp files may be as well.

Note, I put all my unit test code in its own subdirectory so that GLOB_RECURSE simplifies adding additional unit tests.

Well, this approach misses the point of having gtest as a part of your project
to get it built with the same compiler flags.
If I wanted gtest as an external package, I could've leveraged a package manager
without messing with the manual compilation.
For example, in your script, you have to fix the "library_prefix" and "library_suffix" per operating system.
It is not always "lib" and ".a".

I think it cannot get any simpler than the one line of CMake

add_subdirectory("${GTEST_DIR}")

P.S. Don't use GLOB please: http://stackoverflow.com/questions/32411963/why-is-cmake-file-glob-evil

@rakhimov Would the EXCLUDE_FROM_ALL option of the add_subdirectory command be helpful for your situation?

@tschijnmo Yep, it works! Big, big, big, ginormous, screaming thanks!

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Joebeazelman picture Joebeazelman  路  5Comments

cyberdecker picture cyberdecker  路  3Comments

AstralStorm picture AstralStorm  路  4Comments

robindegen picture robindegen  路  4Comments

apivovarov picture apivovarov  路  3Comments