安装 CMake 组件时如何获取将要安装的文件列表

Posted

技术标签:

【中文标题】安装 CMake 组件时如何获取将要安装的文件列表【英文标题】:How to get the list of files that will be installed when installing a CMake component 【发布时间】:2014-09-18 04:14:05 【问题描述】:

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

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

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

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

【问题讨论】:

【参考方案1】:

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

【讨论】:

我找不到这个文件。这个答案适用于哪个 cmake 版本? ‘cmake -P cmake_install.cmake’或‘make install’将创建该文件。 @ziggystar 我认为它只是为一个组件X创建的,如果你安装了这个组件。这意味着它不会被创建,如果您通过例如安装所有组件。 make install。你能确认一下吗? 使用make install会生成一个名为install_manifest.txt的文件。【参考方案2】:

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

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

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

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

【讨论】:

我能否以某种方式安装一个组件组,以便该组内的所有组件都编写其安装清单? 如果你想安装多个COMPONENTs,你可以将COMMAND "$CMAKE_COMMAND" -DCOMPONENT=MyComponent2 -P cmake_install.cmake添加到自定义目标调用中,为你想要的每个不同的组件组。您还可以扩展它以为COMPONENTs 的不同分组创建多个自定义目标。希望这是有道理的。如果没有,我可以扩展我的答案。 @ziggystar 根据您尝试完成的自定义安装步骤,我还可以看到使用 bash 脚本(或者说,Python)来读取清单并进行进一步处理。您可以将其耦合到同一个自定义目标中这一事实是解决方案的关键;我只是提供了一个 CMake 脚本示例以保持一致。

以上是关于安装 CMake 组件时如何获取将要安装的文件列表的主要内容,如果未能解决你的问题,请参考以下文章

使用 CMake 和 CPack 为一个组件创建包

如何从 CentOS 6.5 获取最新的 cmake 版本

如何使用 CMake 安装脚本?

CMake + CPack:安装整个目录(包括子文件夹)

linux cmake 选项

linux 源码安装 cmake 时 可选的参数都有哪些