-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Add support for GTest based unit tests. #485
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
As Dominic and I have previously discussed, there is some need/desire to improve the testing situation in Google Benchmark. One step to fixing this problem is to make it easier to write unit tests by adding support for GTest, which is what this patch does. By default it looks for an installed version of GTest. However the user can specify -DBENCHMARK_BUILD_EXTERNAL_GTEST=ON to instead download, build, and use copy of gtest from source. This is quite useful when Benchmark is being built in non-standard configurations, such as against libc++ or in 32 bit mode.
❌ Build benchmark 848 failed (commit 6cd3b8eda5 by @EricWF) |
cmake/HandleGTest.cmake
Outdated
add_library(gtest UNKNOWN IMPORTED) | ||
add_library(gtest_main UNKNOWN IMPORTED) | ||
set_target_properties(gtest PROPERTIES | ||
IMPORTED_LOCATION ${install_dir}/lib/libgtest.a |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+ INTERFACE_SYSTEM_INCLUDE_DIRECTORIES ${CMAKE_BINARY_DIR}/googletest/include
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ack.
cmake/HandleGTest.cmake
Outdated
IMPORTED_LOCATION ${install_dir}/lib/libgtest.a | ||
) | ||
set_target_properties(gtest_main PROPERTIES | ||
IMPORTED_LOCATION ${install_dir}/lib/libgtest_main.a |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
+ INTERFACE_SYSTEM_INCLUDE_DIRECTORIES ${CMAKE_BINARY_DIR}/googletest/include
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ack.
cmake/HandleGTest.cmake
Outdated
) | ||
add_dependencies(gtest googletest) | ||
add_dependencies(gtest_main googletest) | ||
set(GTEST_INCLUDE_DIRS ${CMAKE_BINARY_DIR}/googletest/include) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- set(GTEST_INCLUDE_DIRS ${CMAKE_BINARY_DIR}/googletest/include)
test/CMakeLists.txt
Outdated
|
||
if (BENCHMARK_ENABLE_GTEST_TESTS) | ||
include(HandleGTest) | ||
include_directories(SYSTEM ${GTEST_INCLUDE_DIRS}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- include_directories(SYSTEM ${GTEST_INCLUDE_DIRS})
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This line still needs to stay for when out-of-tree GTest installations are used. However the SYSTEM can be removed, since it seems to be implicitly specified after adding the INTERFACE_SYSTEM_INCLUDE_DIRECTORIES
line.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nevermind... You're right.
test/CMakeLists.txt
Outdated
add_dependencies(${name} googletest) | ||
endif() | ||
target_link_libraries(${name} benchmark | ||
${GTEST_BOTH_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT}) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
so now ${GTEST_BOTH_LIBRARIES}
will properly add gtest include dirs.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
${}
when not wrapped into ""
will likely break when spaces are present.
❌ Build benchmark 849 failed (commit 9d0bacadd0 by @EricWF) |
❌ Build benchmark 850 failed (commit 497ff83244 by @EricWF) |
❌ Build benchmark 851 failed (commit dbdcb0b7c4 by @EricWF) |
❌ Build benchmark 852 failed (commit f8f8985666 by @EricWF) |
❌ Build benchmark 853 failed (commit 647665d819 by @EricWF) |
❌ Build benchmark 854 failed (commit 0c90eb3b8b by @EricWF) |
❌ Build benchmark 855 failed (commit 7813239f2e by @EricWF) |
❌ Build benchmark 857 failed (commit decddf1fe5 by @EricWF) |
✅ Build benchmark 858 completed (commit c32affa913 by @EricWF) |
❌ Build benchmark 859 failed (commit 8b1aed6a5b by @EricWF) |
CMakeLists.txt
Outdated
|
||
# This option is useful when building Benchmark in odd configurations, such as 32bit mode | ||
# or against libc++. | ||
option(BENCHMARK_BUILD_GTEST_INTREE "Download and build a custom copy of GTest to use" ON) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should be two options:
- build gtest
- if build gtest, is downloading allowed? this really really should default to false.
build systems downloading stuff from internet is such a disgrace :/
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
SGTM. Thanks for the feedback.
```bash | ||
$ git clone https://github.com/google/benchmark.git | ||
# Benchmark requires GTest as a dependency. Add the source tree as a subdirectory. | ||
$ git clone https://github.com/google/googletest.git benchmark/googletest |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd highly recommend
- providing an option specifying the path to the gtest sources
- defaulting to
/usr/src/googletest/
, since that is the natural location, and is where debian puts it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
First, I don't really care to allow users to specify random/arbirtrary out-of-tree GTest source directories. We already have a mechanism to allow users to specify arbitrary GTest installation using CMAKE_MODULE_PATH
to influence find_package(GTest)
.
I've changed the build, as you've suggested, to only download dependencies if -DBENCHMARK_DOWNLOAD_DEPENDENCIES=ON
is specified. So GTest installations among /usr/
and /usr/local/
should work by default.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
why not git submodules?
PREFIX "${CMAKE_BINARY_DIR}/googletest" | ||
INSTALL_DIR "${CMAKE_BINARY_DIR}/googletest" | ||
CMAKE_CACHE_ARGS | ||
-DCMAKE_BUILD_TYPE:STRING=${GTEST_BUILD_TYPE} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Since all this is just to propagate the current params, maybe it would be simpler to just use 2-step approach?
Here is how it looks in practice: [0] [1]
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've looked into 2 step approaches, but I think that they're less idiomatic CMake.
If CMake meant for you to download and load subdirectories during configuration time, they would have provided an actually supported way to do so.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some more thoughts since the small project i maintain has already had gone through the similar gtest integration.
❌ Build benchmark 860 failed (commit eb4cebbe3a by @EricWF) |
✅ Build benchmark 861 completed (commit 670f5304d8 by @EricWF) |
This reverts commit 0806e80.
✅ Build benchmark 862 completed (commit ec5d73f757 by @EricWF) |
✅ Build benchmark 865 completed (commit e1d1cd3986 by @EricWF) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As the first step looks great!
* Otherwise, if `-DBENCHMARK_DOWNLOAD_DEPENDENCIES=ON` is specified during | ||
configuration, the library will automatically download and build any required | ||
dependencies. | ||
* Otherwise, if nothing is done, CMake will use `find_package(GTest REQUIRED)` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this should be the default, no? ie, why do we have it required to have it in-tree instead of just letting cmake do the right thing?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
/usr/share/doc/googletest/README.Debian
:
Use of precompiled libgtest Not Recommended
-------------------------------------------
The Google C++ Testing Framework uses conditional compilation for some
things. Because of the C++ "One Definition Rule", gtest and gmock
must be compiled with exactly the same flags as your C++ code under
test. Because this is hard to manage, upstream no longer recommends
using precompiled libraries [1].
Using GTest with your project
-----------------------------
See the upstream README for instructions on using gtest with your
project. The sources for libgtest are installed into
/usr/src/googletest/googletest along with CMakeLists.txt for use with
cmake.
If your build system uses CMake, the ExternalProject command can be
used to build gtest, then FindGTest can be used to find the built
library.
Using gmock with your project
-----------------------------
See the upstream README for instructions on using gmock with your
project. The sources for libgmock are installed into
/usr/src/googletest/googlemock along with CMakeLists.txt for use with
cmake.
With this Debian package something like the following should be enough to build
a static library (which also includes gtest):
g++ -I/usr/src/googletest/googlemock -c /usr/src/googletest/googlemock/src/gmock-all.cc
g++ -I/usr/src/googletest/googletest -c /usr/src/googletest/googletest/src/gtest-all.cc
ar -rv libgmock.a gmock-all.o gtest-all.o
[1] http://groups.google.com/group/googletestframework/browse_thread/thread/668eff1cebf5309d
-- Steve M. Robbins <[email protected]>, Sat, 19 Nov 2016 21:58:04 -0600
* Add support for GTest based unit tests. As Dominic and I have previously discussed, there is some need/desire to improve the testing situation in Google Benchmark. One step to fixing this problem is to make it easier to write unit tests by adding support for GTest, which is what this patch does. By default it looks for an installed version of GTest. However the user can specify -DBENCHMARK_BUILD_EXTERNAL_GTEST=ON to instead download, build, and use copy of gtest from source. This is quite useful when Benchmark is being built in non-standard configurations, such as against libc++ or in 32 bit mode.
As Dominic and I have previously discussed, there is some
need/desire to improve the testing situation in Google Benchmark.
One step to fixing this problem is to make it easier to write
unit tests by adding support for GTest, which is what this patch does.
By default it looks for an installed version of GTest. However the
user can specify -DBENCHMARK_BUILD_EXTERNAL_GTEST=ON to instead
download, build, and use copy of gtest from source. This is
quite useful when Benchmark is being built in non-standard configurations,
such as against libc++ or in 32 bit mode.