用于install()命令的Generator Expression

时间:2015-04-30 14:55:46

标签: cmake

CMake 3.2.2的文档表明,可以使用install(<FILES|PROGRAMS> ...)签名的生成器表达式。我试图在install()的其他签名中使用生成器表达式,但显然它不起作用。我想做这样的事情:

install(TARGETS foo EXPORT fooConfig
        RUNTIME DESTINATION "Bin/$<CONFIG>"
        LIBRARY DESTINATION "Lib/$<CONFIG>"
        ARCHIVE DESTINATION "Lib/$<CONFIG>"

我也尝试多次调用install()

install(TARGETS foo EXPORT fooConfig
        RUNTIME DESTINATION "Bin/Debug" CONFIGURATIONS Debug
        LIBRARY DESTINATION "Lib/Debug" CONFIGURATIONS Debug
        ARCHIVE DESTINATION "Lib/Debug" CONFIGURATIONS Debug
install(TARGETS foo EXPORT fooConfig
        RUNTIME DESTINATION "Bin/Release" CONFIGURATIONS Release
        LIBRARY DESTINATION "Lib/Release" CONFIGURATIONS Release
        ARCHIVE DESTINATION "Lib/Release" CONFIGURATIONS Release
install(TARGETS foo EXPORT fooConfig
        RUNTIME DESTINATION "Bin/MinSizeRel" CONFIGURATIONS MinSizeRel
        LIBRARY DESTINATION "Lib/MinSizeRel" CONFIGURATIONS MinSizeRel
        ARCHIVE DESTINATION "Lib/MinSizeRel" CONFIGURATIONS MinSizeRel
install(TARGETS foo EXPORT fooConfig
        RUNTIME DESTINATION "Bin/RelWithDebInfo" CONFIGURATIONS RelWithDebInfo
        LIBRARY DESTINATION "Lib/RelWithDebInfo" CONFIGURATIONS RelWithDebInfo
        ARCHIVE DESTINATION "Lib/RelWithDebInfo" CONFIGURATIONS RelWithDebInfo

这导致CMake在'fooConfig'中多次导出 Target'foo'的行发出错误。

我不能在这里使用CMAKE_BUILD_TYPE而不更新CMake缓存并重新运行构建。而不是那样,我想使用Visual Studio批量构建功能,它为我构建多个配置。

我也尝试过一点点黑客攻击。我注意到CMake生成的INSTALL项目只是调用带有参数${CMAKE_BINARY_DIR}/cmake_install.cmake的CMake脚本-DBUILD_TYPE=$(Configuration)。所以我尝试了以下内容:

install(TARGETS foo EXPORT fooConfig
        RUNTIME DESTINATION "Bin/\${BUILD_TYPE}"
        LIBRARY DESTINATION "Lib/\${BUILD_TYPE}"
        ARCHIVE DESTINATION "Lib/\${BUILD_TYPE}"

这实际上适用于安装。但是,已安装的导出脚本(即install(EXPORT fooConfig DESTINATION .)的输出)现在也尝试使用${BUILD_TYPE},这在用户包含该脚本时未设置...

如果有人知道另一种方法来实现我的目标,请告诉我。

2 个答案:

答案 0 :(得分:8)

不幸的是,install命令仅支持要安装的文件列表的生成器表达式,但不支持目标目录。

我建议坚持你的小黑客,但使用CMAKE_INSTALL_CONFIG_NAME代替CMAKE_BUILD_TYPE,即:

install(TARGETS foo EXPORT fooConfig
        RUNTIME DESTINATION "Bin/\${CMAKE_INSTALL_CONFIG_NAME}"
        LIBRARY DESTINATION "Lib/\${CMAKE_INSTALL_CONFIG_NAME}"
        ARCHIVE DESTINATION "Lib/\${CMAKE_INSTALL_CONFIG_NAME}"

CMAKE_INSTALL_CONFIG_NAME设置为用于在生成的cmake_install.cmake脚本中安装的实际构建配置。

通过向安装过程添加补丁脚本,可以自动修复生成的导出脚本(例如fooConfig-debug.cmake)。使用源目录中的以下内容生成文件patch_export_files.cmake

file(GLOB_RECURSE _configFiles "$ENV{DESTDIR}${CMAKE_INSTALL_PREFIX}/fooConfig-*.cmake")
foreach(_configFile ${_configFiles})
    file (READ "${_configFile}" _contents)
    string (REGEX MATCH "configuration \"[A-Za-z]+\"" _configName "${_contents}")
    if (_configName MATCHES "\"([A-Za-z]+)\"")
        message(STATUS "Patching: ${_configFile}")
        string (REPLACE "\${CMAKE_INSTALL_CONFIG_NAME}" "${CMAKE_MATCH_1}" _patchedContents "${_contents}")
        file (WRITE "${_configFile}" "${_patchedContents}")
    endif()
endforeach()

install(SCRIPT ...之后添加install(EXPORT ...来电,需要在安装时运行补丁脚本:

install(EXPORT fooConfig DESTINATION .)
...
install(SCRIPT patch_export_files.cmake)

补丁脚本首先从其标题注释中解析生成的导出脚本对其有效的配置,然后将${CMAKE_INSTALL_CONFIG_NAME}的每次使用替换为配置名称。

答案 1 :(得分:2)

我正在开发一个需要使用不同配置构建的项目。我实现这一目标的方法是使用&#34; ExternalProject&#34;。

我已经创建了一个示例存储库来向您展示这个想法: https://github.com/mpaluru/cmake_multiple_build_configs_example

(Linux是我主要使用的环境,无法访问Visual Studio。) 如果你传递顶级CMakeLists.txt中的-G标志,你应该能够生成你的VS文件。我已经在Linux上测试了这个并且&#34; make -j&#34;工作良好。 Debug和Release配置都是并行构建的。

要点: 您创建一个新的superbuild项目,该项目使用具有不同CMAKE_BUILD_TYPE的ExternalProject_Add调用您的项目。

根据构建类型,您可以传递不同的定义,或者以不同的方式安装。