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. 170
      cmake/README.md
  2. 64
      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.
@ -312,8 +364,8 @@ the headers or the .lib file in the right directory.
If you already have ZLIB library and headers at some other location on your system then alternatively you can define following configuration flags to locate them:
-DZLIB_INCLUDE_DIR=<path to dir containing zlib headers>
-DZLIB_LIB=<path to dir containing zlib>
-DZLIB_INCLUDE_DIR=<path to dir containing zlib headers>
-DZLIB_LIB=<path to dir containing zlib>
Build and testing protobuf as usual.

@ -1,32 +1,42 @@
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_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)
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
)
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()
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
"${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)
add_library(GTest::gmock ALIAS gmock)
add_library(GTest::gmock_main ALIAS gmock_main)
endif()
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)
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