如何获取通过add_subdirectory添加的CMake项目版本?
Great question! When you bring in Google Test using add_subdirectory (whether directly or paired with ExternalProject_Add), the gtest_VERSION and gmock_VERSION variables don’t automatically become available in your project’s CMake scope—they’re locked within the subdirectory’s own context. But there are a few solid ways to retrieve those version numbers:
Method 1: Read version directly from source headers (most reliable for ExternalProject_Add)
Google Test hardcodes its version in header files that are always present in the source tree. You can parse these files directly in your CMake script to extract the version components:
# First, define the path to your Google Test source root # Adjust this to match where ExternalProject_Add downloaded the code set(GOOGLETEST_SOURCE_DIR "${CMAKE_CURRENT_BINARY_DIR}/googletest-src") # Extract GTest version file(READ "${GOOGLETEST_SOURCE_DIR}/googletest/include/gtest/gtest.h" GTEST_HEADER_CONTENTS) string(REGEX MATCH "#define GTEST_VERSION_MAJOR ([0-9]+)" _ ${GTEST_HEADER_CONTENTS}) set(GTEST_VERSION_MAJOR ${CMAKE_MATCH_1}) string(REGEX MATCH "#define GTEST_VERSION_MINOR ([0-9]+)" _ ${GTEST_HEADER_CONTENTS}) set(GTEST_VERSION_MINOR ${CMAKE_MATCH_1}) string(REGEX MATCH "#define GTEST_VERSION_PATCH ([0-9]+)" _ ${GTEST_HEADER_CONTENTS}) set(GTEST_VERSION_PATCH ${CMAKE_MATCH_1}) set(GTEST_VERSION "${GTEST_VERSION_MAJOR}.${GTEST_VERSION_MINOR}.${GTEST_VERSION_PATCH}") # Extract GMock version (same pattern) file(READ "${GOOGLETEST_SOURCE_DIR}/googlemock/include/gmock/gmock.h" GMOCK_HEADER_CONTENTS) string(REGEX MATCH "#define GMOCK_VERSION_MAJOR ([0-9]+)" _ ${GMOCK_HEADER_CONTENTS}) set(GMOCK_VERSION_MAJOR ${CMAKE_MATCH_1}) string(REGEX MATCH "#define GMOCK_VERSION_MINOR ([0-9]+)" _ ${GMOCK_HEADER_CONTENTS}) set(GMOCK_VERSION_MINOR ${CMAKE_MATCH_1}) string(REGEX MATCH "#define GMOCK_VERSION_PATCH ([0-9]+)" _ ${GMOCK_HEADER_CONTENTS}) set(GMOCK_VERSION_PATCH ${CMAKE_MATCH_1}) set(GMOCK_VERSION "${GMOCK_VERSION_MAJOR}.${GMOCK_VERSION_MINOR}.${GMOCK_VERSION_PATCH}") # Verify the result message(STATUS "Detected GTest version: ${GTEST_VERSION}") message(STATUS "Detected GMock version: ${GMOCK_VERSION}")
Just make sure GOOGLETEST_SOURCE_DIR points to the root of the downloaded Google Test code (this path is typically set by ExternalProject_Add—check your setup for the correct directory).
Method 2: Expose variables from the subdirectory (maintenance-heavy)
If you’re willing to modify the Google Test source code, you can add lines to its CMakeLists.txt files to push the version variables up to your project’s scope:
- In
googletest/CMakeLists.txt, add this at the end:set(gtest_VERSION "${GTEST_VERSION_MAJOR}.${GTEST_VERSION_MINOR}.${GTEST_VERSION_PATCH}" PARENT_SCOPE) - In
googlemock/CMakeLists.txt, add this at the end:set(gmock_VERSION "${GMOCK_VERSION_MAJOR}.${GMOCK_VERSION_MINOR}.${GMOCK_VERSION_PATCH}" PARENT_SCOPE)
This will make gtest_VERSION and gmock_VERSION available after you call add_subdirectory. The big downside here is that you’ll have to reapply these changes every time you update Google Test, so it’s not ideal for long-term maintenance.
Method 3: Switch to FetchContent (cleanest, official-recommended approach)
If you can replace ExternalProject_Add with CMake’s FetchContent module (which is now the preferred way to include Google Test per official docs), you’ll get the version variables automatically:
include(FetchContent) FetchContent_Declare( googletest # Replace with the tag/URL for your desired GTest version URL https://github.com/google/googletest/archive/refs/tags/v1.14.0.zip ) # Make GTest available to your project FetchContent_MakeAvailable(googletest) # Now you can directly access the version variables! message(STATUS "GTest version: ${gtest_VERSION}") message(STATUS "GMock version: ${gmock_VERSION}")
FetchContent handles downloading and configuring the subproject during your project’s configuration phase, so all variables defined in Google Test’s CMake scripts become available in your project’s scope.
A quick note on ExternalProject_Add: Since it runs the subproject’s build in a separate phase (after your project’s configuration), you can’t access variables from the subproject during your main project’s configuration step. That’s why Method 1 is the only feasible option if you stick with ExternalProject_Add.
内容的提问来源于stack exchange,提问作者Kamil Zaripov

