Add option to use external GTest in CMake (#8736)

If `-Dprotobuf_USE_EXTERNAL_GTEST=ON` is passed to CMake, it will use an external Google Test copy (i.e. by calling `find_package(GTest REQUIRED)`) rather than the one provided as a submodule.

This makes sense for larger projects that might already include Google Test and want to use a more standard CMake approach.

Also updated build instructions with this information, and more idiomatic usage.

Co-authored-by: Adam Cozzette <acozzette@google.com>
pull/9105/head
Florin Crișan 3 years ago committed by GitHub
parent 18c951efb1
commit 9ebb31726c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 166
      cmake/README.md
  2. 48
      cmake/tests.cmake

@ -36,6 +36,10 @@ If *git* command is not available from *Command Prompt*, add it to system *PATH*
C:\Path\to>set PATH=%PATH%;C:\Program Files\Git\cmd
Optionally, you will want to download [ninja](https://ninja-build.org/) and add it to your *PATH* variable.
C:\Path\to>set PATH=%PATH%;C:\tools\ninja
Good. Now you are ready to continue.
Getting Sources
@ -52,29 +56,25 @@ download `protobuf-all-[VERSION].tar.gz`.
Or you can use git to clone from protobuf git repository.
C:\Path\to> git clone -b [release_tag] https://github.com/protocolbuffers/protobuf.git
C:\Path\to> mkdir src & cd src
C:\Path\to\src> git clone -b [release_tag] https://github.com/protocolbuffers/protobuf.git
Where *[release_tag]* is a git tag like *v3.0.0-beta-1* or a branch name like *master*
if you want to get the latest code.
Go to the project folder:
C:\Path\to>cd protobuf
C:\Path\to\protobuf>
C:\Path\to\src> cd protobuf
C:\Path\to\src\protobuf>
Remember to update any submodules if you are using git clone (you can skip this
step if you are using a release .tar.gz or .zip package):
```console
C:\Path\to> git submodule update --init --recursive
C:\Path\to\src\protobuf> git submodule update --init --recursive
```
Now go to *cmake* folder in protobuf sources:
C:\Path\to\protobuf>cd cmake
C:\Path\to\protobuf\cmake>
Good. Now you are ready to *CMake* configuration.
Good. Now you are ready for *CMake* configuration.
CMake Configuration
===================
@ -82,71 +82,119 @@ CMake Configuration
*CMake* supports a lot of different
[generators](http://www.cmake.org/cmake/help/latest/manual/cmake-generators.7.html)
for various native build systems.
We are only interested in
[Makefile](http://www.cmake.org/cmake/help/latest/manual/cmake-generators.7.html#makefile-generators)
and
[Visual Studio](http://www.cmake.org/cmake/help/latest/manual/cmake-generators.7.html#visual-studio-generators)
generators.
We will use shadow building to separate the temporary files from the protobuf source code.
Of most interest to Windows programmers are the following:
* [Makefile](http://www.cmake.org/cmake/help/latest/manual/cmake-generators.7.html#makefile-generators).
This generates NMake Makefiles for Visual Studio. These work, but they are rather slow.
* [Visual Studio](http://www.cmake.org/cmake/help/latest/manual/cmake-generators.7.html#visual-studio-generators)
This generates a Visual Studio solution for the project.
* [Ninja](https://cmake.org/cmake/help/latest/manual/cmake-generators.7.html#ninja-generator)
This uses the external tool [Ninja](https://ninja-build.org/) to build. It is the fastest solution available.
Note that as of Visual Studio 2015, Visual Studio includes
[support for opening directly CMake-based projects](https://docs.microsoft.com/en-us/cpp/build/cmake-projects-in-visual-studio).
It is considered good practice not to build CMake projects in the source tree but in a separate folder.
Create a temporary *build* folder and change your working directory to it:
C:\Path\to\protobuf\cmake>mkdir build & cd build
C:\Path\to\protobuf\cmake\build>
mkdir C:\Path\to\build\protobuf
cd C:\Path\to\build\protobuf
C:\Path\to\build\protobuf>
The *Makefile* generator can build the project in only one configuration, so you need to build
The *Makefile* and *Ninja* generators can build the project in only one configuration, so you need to build
a separate folder for each configuration.
To start using a *Release* configuration:
To start using a *Release* configuration via the *NMmake* generator:
C:\Path\to\protobuf\cmake\build>mkdir release & cd release
C:\Path\to\protobuf\cmake\build\release>cmake -G "NMake Makefiles" ^
C:\Path\to\build\protobuf>mkdir release & cd release
C:\Path\to\build\protobuf\release>cmake -G "NMake Makefiles" ^
-DCMAKE_BUILD_TYPE=Release ^
-DCMAKE_INSTALL_PREFIX=../../../../install ^
../..
-DCMAKE_INSTALL_PREFIX=C:\Path\to\install ^
C:\Path\to\src\protobuf
It will generate *nmake* *Makefile* in current directory.
It will generate a *NMake* *Makefile* in the current directory.
To use *Debug* configuration:
To use *Debug* configuration using *Ninja*:
C:\Path\to\protobuf\cmake\build>mkdir debug & cd debug
C:\Path\to\protobuf\cmake\build\debug>cmake -G "NMake Makefiles" ^
C:\Path\to\build\protobuf>mkdir debug & cd debug
C:\Path\to\build\protobuf\debug>cmake -G "Ninja" ^
-DCMAKE_BUILD_TYPE=Debug ^
-DCMAKE_INSTALL_PREFIX=../../../../install ^
../..
-DCMAKE_INSTALL_PREFIX=C:\Path\to\install ^
C:\Path\to\src\protobuf
It will generate *nmake* *Makefile* in current directory.
It will generate *Ninja* build scripts in current directory.
To create *Visual Studio* solution file:
The *Visual Studio* generator is multi-configuration: it will generate a single *.sln* file that can be used for both *Debug* and *Release*:
C:\Path\to\protobuf\cmake\build>mkdir solution & cd solution
C:\Path\to\protobuf\cmake\build\solution>cmake -G "Visual Studio 16 2019" ^
-DCMAKE_INSTALL_PREFIX=../../../../install ^
../..
C:\Path\to\build\protobuf>mkdir solution & cd solution
C:\Path\to\build\protobuf\solution>cmake -G "Visual Studio 16 2019" ^
-DCMAKE_INSTALL_PREFIX=C:\Path\to\install ^
C:\Path\to\src\protobuf
It will generate *Visual Studio* solution file *protobuf.sln* in current directory.
If the *gmock* directory does not exist, and you do not want to build protobuf unit tests,
you need to add *cmake* command argument `-Dprotobuf_BUILD_TESTS=OFF` to disable testing.
Unit Tests
----------
Unit tests are being built along with the rest of protobuf. The unit tests require Google Mock (now a part of Google Test).
A copy of [Google Test](https://github.com/google/googletest) is included as a Git submodule in the `third-party/googletest` folder.
(You do need to initialize the Git submodules as explained above.)
Alternately, you may want to use protobuf in a larger set-up, you may want to use that standard CMake approach where
you build and install a shared copy of Google Test.
To make a *Visual Studio* file for Visual Studio 16 2019, create the *Visual Studio*
solution file above and edit the CMakeCache file.
After you've built and installed your Google Test copy, you need add the following definition to your *cmake* command line
during the configuration step: `-Dprotobuf_USE_EXTERNAL_GTEST=ON`.
This will cause the standard CMake `find_package(GTest REQUIRED)` to be used.
C:Path\to\protobuf\cmake\build\solution\CMakeCache
[find_package](https://cmake.org/cmake/help/latest/command/find_package.html) will search in a default location,
which on Windows is *C:\Program Files*. This is most likely not what you want. You will want instead to search for
Google Test in your project's root directory (i.e. the same directory you've passed to `CMAKE_INSTALL_PREFIX` when
building Google Test). For this, you need to set the `CMAKE_PREFIX_PATH` CMake variable. (There are other ways in CMake,
see the [manual](https://cmake.org/cmake/help/latest/command/find_package.html) for details.)
Then create the *Visual Studio* solution file again
For example:
C:\Path\to\build\protobuf>mkdir solution & cd solution
C:\Path\to\build\protobuf\solution>cmake -G "Visual Studio 16 2019" ^
-DCMAKE_INSTALL_PREFIX=C:\Path\to\install ^
-DCMAKE_PREFIX_PATH=C:\Path\to\my_big_project ^
-Dprotobuf_USE_EXTERNAL_GTEST=ON ^
C:\Path\to\src\protobuf
In most cases, `CMAKE_PREFIX_PATH` and `CMAKE_INSTALL_PREFIX` will point to the same directory.
To disable testing completely, you need to add the following argument to you *cmake* command line: `-Dprotobuf_BUILD_TESTS=OFF`.
For example:
C:\Path\to\build\protobuf\solution>cmake -G "Visual Studio 16 2019" ^
-DCMAKE_INSTALL_PREFIX=C:\Path\to\install ^
-Dprotobuf_BUILD_TESTS=OFF ^
C:\Path\to\src\protobuf
Compiling
=========
To compile protobuf:
The standard way to compile a *CMake* project is `cmake --build <directory>`.
C:\Path\to\protobuf\cmake\build\release>nmake
Note that if your generator supports multiple configurations, you will probably want to specify which one to build:
cmake --build C:\Path\to\build\protobuf\solution --config Release
You can also run directly the build tool you've configured:
C:\Path\to\build\protobuf\release>nmake
or
C:\Path\to\protobuf\cmake\build\debug>nmake
C:\Path\to\build\protobuf\debug>ninja
And wait for the compilation to finish.
@ -172,7 +220,7 @@ You can also build the `check` target (not idiomatic CMake usage, though):
or
C:\Path\to\protobuf\cmake\build\debug>nmake check
C:\Path\to\build\protobuf\release>ninja check
You can also build project *check* from Visual Studio solution.
Yes, it may sound strange, but it works.
@ -189,7 +237,7 @@ You should see output similar to:
To run specific tests, you need to pass some command line arguments to the test program itself:
C:\Path\to\protobuf>cmake\build\release\tests.exe --gtest_filter=AnyTest*
C:\Path\to\build\protobuf\release>tests.exe --gtest_filter=AnyTest*
Running main() from gmock_main.cc
Note: Google Test filter = AnyTest*
[==========] Running 3 tests from 1 test case.
@ -214,13 +262,17 @@ If all tests are passed, safely continue.
Installing
==========
To install protobuf to the specified *install* folder:
To install protobuf to the *install* folder you've specified in the configuration step, you need to build the `install` target:
cmake --build C:\Path\to\build\protobuf\solution --config Release --target install
Or if you prefer:
C:\Path\to\protobuf\cmake\build\release>nmake install
C:\Path\to\build\protobuf\release>nmake install
or
C:\Path\to\protobuf\cmake\build\debug>nmake install
C:\Path\to\build\protobuf\debug>ninja install
You can also build project *INSTALL* from Visual Studio solution.
It sounds not so strange and it works.
@ -284,16 +336,16 @@ You can also compile it from source by yourself.
Getting sources:
C:\Path\to>git clone -b v1.2.8 https://github.com/madler/zlib.git
C:\Path\to>cd zlib
C:\Path\to\src>git clone -b v1.2.8 https://github.com/madler/zlib.git
C:\Path\to\src>cd zlib
Compiling and Installing:
C:\Path\to\zlib>mkdir build & cd build
C:\Path\to\zlib\build>mkdir release & cd release
C:\Path\to\zlib\build\release>cmake -G "NMake Makefiles" -DCMAKE_BUILD_TYPE=Release ^
-DCMAKE_INSTALL_PREFIX=../../../install ../..
C:\Path\to\zlib\build\release>nmake & nmake install
C:\Path\to\src\zlib>mkdir C:\Path\to\build\zlib & cd C:\Path\to\build\zlib
C:\Path\to\build\zlib>mkdir release & cd release
C:\Path\to\build\zlib\release>cmake -G "Ninja" -DCMAKE_BUILD_TYPE=Release ^
-DCMAKE_INSTALL_PREFIX=C:\Path\to\install C:\Path\to\src\zlib
C:\Path\to\src\zlib\build\release>cmake --build . --target install
You can make *debug* version or use *Visual Studio* generator also as before for the
protobuf project.

@ -1,32 +1,42 @@
if (NOT EXISTS "${PROJECT_SOURCE_DIR}/../third_party/googletest/CMakeLists.txt")
option(protobuf_USE_EXTERNAL_GTEST "Use external Google Test (i.e. not the one in third_party/googletest)" OFF)
option(protobuf_ABSOLUTE_TEST_PLUGIN_PATH
"Using absolute test_plugin path in tests" ON)
mark_as_advanced(protobuf_ABSOLUTE_TEST_PLUGIN_PATH)
if (protobuf_USE_EXTERNAL_GTEST)
find_package(GTest REQUIRED)
else()
if (NOT EXISTS "${PROJECT_SOURCE_DIR}/../third_party/googletest/CMakeLists.txt")
message(FATAL_ERROR
"Cannot find third_party/googletest directory that's needed to "
"build tests. If you use git, make sure you have cloned submodules:\n"
" git submodule update --init --recursive\n"
"If instead you want to skip tests, run cmake with:\n"
" cmake -Dprotobuf_BUILD_TESTS=OFF\n")
endif()
option(protobuf_ABSOLUTE_TEST_PLUGIN_PATH
"Using absolute test_plugin path in tests" ON)
mark_as_advanced(protobuf_ABSOLUTE_TEST_PLUGIN_PATH)
endif()
set(googlemock_source_dir "${protobuf_source_dir}/third_party/googletest/googlemock")
set(googletest_source_dir "${protobuf_source_dir}/third_party/googletest/googletest")
include_directories(
set(googlemock_source_dir "${protobuf_source_dir}/third_party/googletest/googlemock")
set(googletest_source_dir "${protobuf_source_dir}/third_party/googletest/googletest")
include_directories(
${googlemock_source_dir}
${googletest_source_dir}
${googletest_source_dir}/include
${googlemock_source_dir}/include
)
)
add_library(gmock STATIC
add_library(gmock STATIC
"${googlemock_source_dir}/src/gmock-all.cc"
"${googletest_source_dir}/src/gtest-all.cc"
)
target_link_libraries(gmock ${CMAKE_THREAD_LIBS_INIT})
add_library(gmock_main STATIC "${googlemock_source_dir}/src/gmock_main.cc")
target_link_libraries(gmock_main gmock)
)
target_link_libraries(gmock ${CMAKE_THREAD_LIBS_INIT})
add_library(gmock_main STATIC "${googlemock_source_dir}/src/gmock_main.cc")
target_link_libraries(gmock_main gmock)
add_library(GTest::gmock ALIAS gmock)
add_library(GTest::gmock_main ALIAS gmock_main)
endif()
set(lite_test_protos
google/protobuf/map_lite_unittest.proto
@ -227,7 +237,7 @@ if (MSVC)
/wd4146 # unary minus operator applied to unsigned type, result still unsigned
)
endif()
target_link_libraries(tests libprotoc libprotobuf gmock_main)
target_link_libraries(tests libprotoc libprotobuf GTest::gmock_main)
set(test_plugin_files
${protobuf_source_dir}/src/google/protobuf/compiler/mock_code_generator.cc
@ -237,19 +247,19 @@ set(test_plugin_files
)
add_executable(test_plugin ${test_plugin_files})
target_link_libraries(test_plugin libprotoc libprotobuf gmock)
target_link_libraries(test_plugin libprotoc libprotobuf GTest::gmock)
set(lite_test_files
${protobuf_source_dir}/src/google/protobuf/lite_unittest.cc
)
add_executable(lite-test ${lite_test_files} ${common_lite_test_files} ${lite_test_proto_files})
target_link_libraries(lite-test libprotobuf-lite gmock_main)
target_link_libraries(lite-test libprotobuf-lite GTest::gmock_main)
set(lite_arena_test_files
${protobuf_source_dir}/src/google/protobuf/lite_arena_unittest.cc
)
add_executable(lite-arena-test ${lite_arena_test_files} ${common_lite_test_files} ${lite_test_proto_files})
target_link_libraries(lite-arena-test libprotobuf-lite gmock_main)
target_link_libraries(lite-arena-test libprotobuf-lite GTest::gmock_main)
add_custom_target(check
COMMAND tests

Loading…
Cancel
Save