关于安装:如何获取安装CMake组件时要安装的文件列表

How to get the list of files that will be installed when installing a CMake component

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

目前,我正在将 COMPONENT 安装到临时位置进行打包(不使用 CPack 进行打包),然后使用自定义命令进行打包。我在 CMake 中的打包过程中调用了以下命令。

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

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


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


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

关联的文件

通常,COMPONENT 选项通常与 install() 一起指定,以将目标分类到特定的安装组中。这些"组件"分组通常与 CPack 一起使用:

For certain kinds of binary installers (including the graphical installers on macOS and Windows), CPack generates installers that allow users to select individual application components to install. The contents of each of the components are identified by the COMPONENT argument of CMakea€?s INSTALL command.

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

进行过滤

1
2
3
4
5
6
7
8
9
10
11
12
13
# 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 变量。

1
2
3
4
5
6
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():

将它们复制到安装目标

1
2
3
4
5
6
7
8
9
10
11
12
13
# 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"\
"
";" 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)