diff --git a/cmake/README.md b/cmake/README.md index 857d146aa0..3fee4a0414 100644 --- a/cmake/README.md +++ b/cmake/README.md @@ -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 `. + - 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= - -DZLIB_LIB= + -DZLIB_INCLUDE_DIR= + -DZLIB_LIB= Build and testing protobuf as usual. diff --git a/cmake/tests.cmake b/cmake/tests.cmake index 7a359e268a..1556838528 100644 --- a/cmake/tests.cmake +++ b/cmake/tests.cmake @@ -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