9

有没有办法以编程方式(在 CMake 中)知道如果COMPONENT安装了 a (类似于get_property组件)将安装哪些文件?

目前,我正在安装一个COMPONENT临时位置进行打包(不使用CPack进行打包),然后使用自定义命令进行打包。我在 CMake 打包期间调用以下命令。

cmake -DCOMPONENT=my_test_component 
-DCMAKE_INSTALL_PREFIX=${TMP_PACKAGING_ROOT}
-P ${CMAKE_BINARY_DIR}/cmake_install.cmake

我想知道是否可以获得文件列表,以便我只能在包中明确包含这些文件?或者可能将它们作为输出添加到自定义命令?

4

2 回答 2

6

知道它的唯一方法似乎是阅读install_manifest_${component}.txt其中将包含我们安装 CMake 组件时将安装的所有文件列表。

于 2014-10-17T09:41:28.667 回答
3

CMake 没有描述符的get_property()函数(或类似的等效函数) ;COMPONENTCMake 属性保留用于目标、目录、源文件等(此处为完整列表)。但是,有一些方法可以以编程方式列出与COMPONENT.

通常,该COMPONENT选项通常被指定install()为基本上将目标分类到特定的安装组中。这些“组件”分组通常与CPack一起使用:

对于某些类型的二进制安装程序(包括 macOS 和 Windows 上的图形安装程序),CPack 会生成允许用户选择要安装的单个应用程序组件的安装程序。每个组件的内容由COMPONENTCMakeINSTALL命令的参数标识。

但是,如果您不使用 CPack,CMake 仍然支持COMPONENT分组;他们只是更难管理。您可以遍历cmake_install.cmake文件中的每个安装规则,并过滤掉与特定COMPONENT. 这必须CMake 生成阶段之后(cmake_install.cmake生成文件之后)完成,因为在配置时不知道每个目标的完整路径。正如上面的问题所暗示的,您可以创建一个自定义目标来自己调用生成的 CMake 安装脚本,过滤基于COMPONENT

# Define install rule for MyExecutable target (grouping it in MyComponent).
install(TARGETS MyExecutable
    DESTINATION ${CMAKE_CURRENT_BINARY_DIR}/installation
    CONFIGURATIONS Release
    COMPONENT MyComponent
)

# Add custom target to filter and install MyComponent files.
add_custom_target(MyInstallTarget
    COMMAND "${CMAKE_COMMAND}" -DCOMPONENT=MyComponent -P cmake_install.cmake
    DEPENDS MyExecutable
    WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
)

在构建了这个自定义目标(例如make MyInstallTarget)之后,install_manifest_MyComponent.txt将创建清单文件,其中包含与该目标关联的所有文件的列表COMPONENT。(它不一定是通过构建 CMake 预定义的INSTALL目标来创建的。)

但是,这个清单文件本身并不是很有用。要以编程方式使用它,我们可以扩展自定义目标以将这些特定于组件的文件读入 CMake 变量。

add_custom_target(MyInstallTarget
    COMMAND "${CMAKE_COMMAND}" -DCOMPONENT=MyComponent -P cmake_install.cmake
    COMMAND "${CMAKE_COMMAND}" -DCOMPONENT=MyComponent -P ../my_install_script.cmake
    DEPENDS MyExecutable
    WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
)

在内部my_install_script.cmake,逻辑很大程度上取决于要对文件列表执行的操作。下面的脚本会将文件读入 CMake 列表变量,然后使用以下命令将它们复制到安装目标configure_file()

# Check if an install COMPONENT was provided.
if(COMPONENT)
    # Read the manifest file.
    file(READ "install_manifest_${COMPONENT}.txt" MY_INSTALL_FILES)
    # Create a list from the component files.
    string(REPLACE "\n" ";" MY_INSTALL_FILES ${MY_INSTALL_FILES})
    # Loop through each file, placing it in the installation directory.
    foreach(curFile ${MY_INSTALL_FILES})
        message("Installing file: " ${curFile})
        configure_file(${curFile} /your/final/install/folder COPYONLY)
    endforeach()
endif(COMPONENT)
于 2019-10-30T12:50:14.837 回答