获取add_subdirectory添加的CMake项目版本

时间:2018-03-28 09:36:49

标签: cmake

我有一个依赖于Google Test库的CMake项目。 我已使用ExternalProject_Addadd_subdirectory添加了Google测试,如此处所述(https://github.com/google/googletest/tree/master/googletest部分Incorporating Into An Existing CMake Project)。

现在,在命令add_subdirectory之后我想检查包含的项目gtestgmock的版本,但是gtest_VERSIONgmock_VERSION变量是未定义的。是否可以通过add_subdirectory添加项目版本?

2 个答案:

答案 0 :(得分:1)

变量<PROJECT-NAME>_VERSION具有本地范围。因此,由子项目定义的版本变量不会被主项目看到。

假设子项目CMakeLists.txt执行project()调用

project(<project-name> VERSION <version-string> ...)

版本字符串可以使用正则表达式轻松提取:

# subproject_version(<subproject-name> <result-variable>)
#
# Extract version of a sub-project, which was previously included with add_subdirectory().
function(subproject_version subproject_name VERSION_VAR)
    # Read CMakeLists.txt for subproject and extract project() call(s) from it.
    file(STRINGS "${${subproject_name}_SOURCE_DIR}/CMakeLists.txt" project_calls REGEX "[ \t]*project\\(")
    # For every project() call try to extract its VERSION option
    foreach(project_call ${project_calls})
        string(REGEX MATCH "VERSION[ ]+([^ )]+)" version_param "${project_call}")
        if(version_param)
            set(version_value "${CMAKE_MATCH_1}")
        endif()
    endforeach()
    if(version_value)
        set(${VERSION_VAR} "${version_value}" PARENT_SCOPE)
    else()
        message("WARNING: Cannot extract version for subproject '${subproject_name}'")
    endif()

endfunction(subproject_version)

# The function's usage:    
subproject_version(gtest gtest_version)
message("VERSION for gtest: ${gtest_version}")

上面的实现使用变量<PROJECT-NAME>_SOURCE_DIR,它包含子项目的源目录。与<PROJECT-NAME>_VERSION变量不同,带有源目录的变量具有全局可见性(实际上它是 CACHED ),因此它可以在子项目之外使用。

答案 1 :(得分:0)

由于您无法直接访问子目录本地变量,因此我想添加我的变体gtest_VERSION变量CACHED,因此可以全局访问:

  1. CMAKE_PROJECT_<PROJECT-NAME>_INCLUDE

      

    project()命令要包含的CMake语言文件或模块。这用于将自定义代码注入到项目构建中,而无需修改其源代码。

    file(
        WRITE "${CMAKE_BINARY_DIR}/SetProjectVersion.cmake"
        [=[
            set(${PROJECT_NAME}_VERSION "${${PROJECT_NAME}_VERSION}" CACHE INTERNAL "")
        ]=]
    )
    set(
        CMAKE_PROJECT_gtest_INCLUDE
        "${CMAKE_BINARY_DIR}/SetProjectVersion.cmake"
    )
    
  2. 覆盖project()命令

    cmake_policy(SET CMP0048 NEW)    
    
    macro(project)
        _project(${ARGN})
        set(${PROJECT_NAME}_VERSION "${${PROJECT_NAME}_VERSION}" CACHE INTERNAL "")
    endmacro()