【问题标题】:How to pass all variables to separate CMake instance?如何将所有变量传递给单独的 CMake 实例?
【发布时间】:2014-03-13 04:21:02
【问题描述】:

我想弄清楚如何有效地将所有 CMake 变量传递到 CMake 的另一个执行步骤。 get all the variables 有一种方法,但我希望有一个有效的选择,而不是循环遍历每个变量并将字符串与 set() 一起附加如下:

 get_cmake_property(_variableNames VARIABLES)
 foreach (_variableName ${_variableNames})
    if(NOT ${_variablename} STREQUAL BASIS_PROPERTIES_ON_TESTS_RE)
      set(ALL_VARIABLES_COMMAND_LINE "${ALL_VARIABLES_COMMAND_LINE} -D ${_variableName}=\"${${_variableName}}\"\n")
    endif()
 endforeach()

 execute_process (
    COMMAND "${CMAKE_COMMAND}" ${COMMON_ARGS}
            -D "PROJECT_INCLUDE_DIRS=${INCLUDE_DIRS}"
            -D "BINARY_INCLUDE_DIR=${BINARY_INCLUDE_DIR}"
            -D "EXTENSIONS=${EXTENSIONS}"
            ${ALL_VARIABLES_COMMAND_LINE}
            -D "CMAKE_FILE=${CMAKE_FILE}"
            -P "${BASIS_MODULE_PATH}/ConfigureIncludeFiles.cmake"
    RESULT_VARIABLE RT
  )

该方法的问题是它会混淆转义字符,并且在某些情况下无法执行程序。

注意:我目前将所有变量写入磁盘并从那里重新加载它们,但该操作需要 1/2 秒。因为我需要为超过 100 个独立的包运行这个脚本,所以该技术的额外配置时间太长了。

【问题讨论】:

    标签: variables cmake parameter-passing execution


    【解决方案1】:

    好吧,我不会将整个变量列表作为命令行参数传递,而是会形成一个新的(临时)CMake 脚本(使用file(WRITE...))来设置所有必需的变量,然后使用另一个 CMAke 实例执行该脚本(execute_process(COMMAND ${CMAKE_COMMAND} -P /path/to/script...))。因此,您将避免与 bash 转义作斗争的必要性。

    当然,在编写文件时,您也需要转义变量值,但对于 CMake,这是一项简单得多的任务。看来基本的转义应该是这样的:

     set(VAR "A String with \" and \\ ")
     message(STATUS "VAR=[${VAR}]")
    
     string(REPLACE "\\" "\\\\" VAR_ ${VAR}) # escape \
     string(REPLACE "\"" "\\\"" VAR_ ${VAR_}) # escape "
    
     file(WRITE file.cmake "SET(VAR \"${VAR_}\")\n" )
     file(APPEND file.cmake "message(STATUS \"VAR=[\${VAR}]\")\n")
    

    这个 cmake 脚本创建另一个名为 file.cmake 的 cmake 脚本,它打印与第一个脚本相同的变量。

    【讨论】:

    • 我们目前使用这个,它增加了1/2秒的配置时间。由于我需要为 100 多个独立软件包执行此操作,因此我需要一个更快的解决方案。
    • 那么,你不能创建一次文件然后重新使用它吗?
    • 每个模块作为或多或少独立的子项目存在于其自己的子目录树中。因此,必须考虑不同的依赖关系和模块属性以及构建设置。因此,您需要为每个模块编写一次这样的文件。
    【解决方案2】:

    我假设您正在使用来自CMake BASIS 项目的ConfigureIncludeFiles 模块。缩短项目配置时间的一种方法是将ConfigureIncludeFiles 作为包含脚本运行。

    不要在以execute_process 开头的CMake 子进程中运行ConfigureIncludeFiles,而是将主CMake 进程中的模块作为CMake 脚本运行,并针对需要配置的每个包使用include 命令,即:

    # set up parameters for package 1
    set (PROJECT_INCLUDE_DIRS ${PACKAGE1_INCLUDE_DIRS})
    set (BINARY_INCLUDE_DIR ${PACKAGE1_BINARY_INCLUDE_DIR})
    set (EXTENSIONS ${PACKAGE1_EXTENSIONS})
    set (CMAKE_FILE ${PACKAGE1_CMAKE_FILE})
    include(ConfigureIncludeFiles)
    ...
    # set up parameters for package 2
    set (PROJECT_INCLUDE_DIRS ${PACKAGE2_INCLUDE_DIRS})
    set (BINARY_INCLUDE_DIR ${PACKAGE2_BINARY_INCLUDE_DIR})
    set (EXTENSIONS ${PACKAGE2_EXTENSIONS})
    set (CMAKE_FILE ${PACKAGE2_CMAKE_FILE})
    include(ConfigureIncludeFiles)
    

    由于模块在 CMake 主进程中运行,它会隐式访问所有定义的 CMake 变量,无需显式传递变量。

    【讨论】:

    • 没错。然而,其目的是将配置推迟到构建步骤,这样配置步骤就不需要在每次编辑配置的头文件时重新运行。最初 CMake BASIS 配置(或复制)所有头文件,以便在构建树中以与在安装中组织它们相同的方式组织它们。由于这会带来很多问题,例如编译器警告/错误引用副本而不是原始文件,这可能会导致更改丢失,因此现在只有真正需要配置的文件。通常只是 config.h.in.
    • 也就是说,由于现在通常最多只配置一个头文件,因此在配置步骤中直接执行此操作再次是合理的,而无需其他所需的所有复杂逻辑。这就是 Andrew 最终实施的解决方案,以缩短配置步骤所需的时间。
    猜你喜欢
    • 2013-01-25
    • 2020-07-05
    • 1970-01-01
    • 1970-01-01
    • 2014-10-21
    • 2021-05-09
    • 2014-07-12
    • 2012-09-28
    • 1970-01-01
    相关资源
    最近更新 更多