是否可以确定 CMake install(CODE) 是从 "install" 还是 "package" 阶段调用的?

Is it possible to determine whether CMake install(CODE) is called from the "install" or "package" stage?

我正在使用 CMake v3.21.0 调用 Qt 的 windeployqt during the install stage by the means of the install(CODE) 命令,如下所示:

install(
    CODE "
    execute_process(
      COMMAND \"${CMAKE_COMMAND}\" -E
        env PATH=\"${windeployqt_ROOT_DIR}\"
        \"${windeployqt_EXECUTABLE}\"
        # TODO(2021-08-25 by wolters): This is a different path when CPack is`
        # used. How to check for this case and obtain the correct output path?
        --dir \"${CMAKE_INSTALL_PREFIX}/${args_INSTALL_SUFFIX}\"
        --no-quick-import
        --no-system-d3d-compiler
        --no-virtualkeyboard
        --no-compiler-runtime
        --no-webkit2
        --no-angle
        --no-opengl-sw
        --verbose 0
        \"$<TARGET_FILE:${args_TARGET}>\"
    )
    "
    COMPONENT runtime
  )

如果安装项目,这工作正常:

cmake --build . --config RelWithDebInfo --target install

但是在创建 CPack 包时,由 windeployqt 创建的文件 不是 包的一部分(在本例中为 ZIP):

cpack -G ZIP -C RelWithDebInfo -D CPACK_COMPONENTS_ALL="runtime"

我知道问题是 ${CMAKE_INSTALL_PREFIX}CODE 中的用法。

  1. 对于 install 目标,这是正确的。
  2. 对于 package 目标,这是不正确的。相反,应该使用 current CPack 生成器的构建目录,例如${CMAKE_CURRENT_BINARY_DIR}/_CPack_Packages/win64/ZIP/${CPACK_PACKAGE_FILE_NAME}.

我的问题是:

  1. 有没有办法区分 CODE 部分中的 installpackage 目标? (伪代码:if(CMAKE_IS_PACKAGING)
  2. 如果有办法:是否可以获取或动态构建实际 CPack 临时“安装”目录的目录路径?

如果两个问题都可以解决,windeployqt 生成的文件应该是 CPack 生成的包的一部分。

变量 CMAKE_INSTALL_PREFIX 不应 在 CMakeLists.txt 中展开,正如您所做的那样。它在调用时的实际值在 install(CODE) 片段中可用。

考虑以下片段:

cmake_minimum_required(VERSION 3.21)
project(test NONE)

install(CODE [[message(STATUS "HERE: ${CMAKE_INSTALL_PREFIX}")]])

请注意 [[ ... ]] 转义变量扩展(您也可以使用反斜杠)。现在,如果您使用 -DCMAKE_INSTALL_PREFIX=/tmp/install 配置此项目,您将看到按预期打印的消息。

$ cmake -S . -B build -DCMAKE_INSTALL_PREFIX=/tmp/install
-- Configuring done
-- Generating done
-- Build files have been written to: /home/alex/test/build
$ cmake --build build/ --target install
[0/1] Install the project...
-- Install configuration: ""
-- HERE: /tmp/install

如果您现在再次 运行 安装脚本 而无需重新配置或重建 ,它仍然可以工作:

$ cmake --install build/ --prefix /tmp/other-prefix
-- Install configuration: ""
-- HERE: /tmp/other-prefix

这就是 CPack 运行 安装规则的方式。它使用CMAKE_INSTALL_PREFIX的配置时间值。它希望您的项目可以重新定位(即无错误)。