install() 命令的生成器表达式
Generator Expression for install() commands
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 发出错误 Target 'foo' exported more than once in 'fooConfig'.
如果不更新 CMake 缓存并重新运行 构建,我无法在此处使用 CMAKE_BUILD_TYPE
。而不是那样,我想使用 Visual Studio 批量构建功能,它为我构建多个配置。
我也尝试了一些技巧。我注意到 CMake 生成的 INSTALL
项目只是使用参数 -DBUILD_TYPE=$(Configuration)
调用 CMake 脚本 ${CMAKE_BINARY_DIR}/cmake_install.cmake
。所以我尝试了以下方法:
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}
,这在用户包含该脚本时未设置...
如果有人知道实现我的目标的其他方法,请告诉我。
我正在从事一个需要使用不同配置进行构建的项目。我实现这一目标的方法是使用 "ExternalProject"。
我创建了一个示例存储库来向您展示这个想法:
https://github.com/mpaluru/cmake_multiple_build_configs_example
(Linux 是我最常使用的环境,无法访问 Visual Studio。)
如果你在顶层 CMakeLists.txt 中传递 -G 标志,你应该能够生成你的 VS 文件。我已经在 Linux 上测试过了,"make -j" 工作正常。调试和发布配置并行构建。
总结:
您创建一个新的超级构建项目,它使用 ExternalProject_Add 和不同的 CMAKE_BUILD_TYPE.
调用您的项目
并且根据构建类型,您传递不同的定义,或者进行不同的安装。
不幸的是,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(EXPORT ...
:
之后添加 install(SCRIPT ...
调用
install(EXPORT fooConfig DESTINATION .)
...
install(SCRIPT patch_export_files.cmake)
补丁脚本首先从其 header 注释中解析生成的导出脚本对其有效的配置,然后将每次使用的 ${CMAKE_INSTALL_CONFIG_NAME}
替换为配置名称。
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 发出错误 Target 'foo' exported more than once in 'fooConfig'.
如果不更新 CMake 缓存并重新运行 构建,我无法在此处使用 CMAKE_BUILD_TYPE
。而不是那样,我想使用 Visual Studio 批量构建功能,它为我构建多个配置。
我也尝试了一些技巧。我注意到 CMake 生成的 INSTALL
项目只是使用参数 -DBUILD_TYPE=$(Configuration)
调用 CMake 脚本 ${CMAKE_BINARY_DIR}/cmake_install.cmake
。所以我尝试了以下方法:
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}
,这在用户包含该脚本时未设置...
如果有人知道实现我的目标的其他方法,请告诉我。
我正在从事一个需要使用不同配置进行构建的项目。我实现这一目标的方法是使用 "ExternalProject"。
我创建了一个示例存储库来向您展示这个想法: https://github.com/mpaluru/cmake_multiple_build_configs_example
(Linux 是我最常使用的环境,无法访问 Visual Studio。) 如果你在顶层 CMakeLists.txt 中传递 -G 标志,你应该能够生成你的 VS 文件。我已经在 Linux 上测试过了,"make -j" 工作正常。调试和发布配置并行构建。
总结: 您创建一个新的超级构建项目,它使用 ExternalProject_Add 和不同的 CMAKE_BUILD_TYPE.
调用您的项目并且根据构建类型,您传递不同的定义,或者进行不同的安装。
不幸的是,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(EXPORT ...
:
install(SCRIPT ...
调用
install(EXPORT fooConfig DESTINATION .)
...
install(SCRIPT patch_export_files.cmake)
补丁脚本首先从其 header 注释中解析生成的导出脚本对其有效的配置,然后将每次使用的 ${CMAKE_INSTALL_CONFIG_NAME}
替换为配置名称。