首页 > 解决方案 > 带分号的 CMake 变量

问题描述

假设有一个程序需要输入 form <prog> --param "one;two;three":一个标志--param,后跟一个由分号分隔的单词字符串(用引号括起来)。例如,可以使用以下 Bash 脚本:

flag=${1}
items=(${2//;/ })

echo "flag: ${flag}"
echo "items: ${items[@]}"

显然,输出将是:

flag: --param
items: one two three

分隔符;是必须的,因此我们需要传递一个用引号括起来的字符串,否则 shell 会将分号之间的内容视为单独的命令。

这个问题有点类似于这个问题但那里提出的答案不适用于以下问题。

考虑这个CMakeLists.txt文件:

cmake_minimum_required(VERSION 3.16.2)
project(clumsy)

add_custom_command(OUTPUT foo.txt
    COMMAND bash ${CMAKE_SOURCE_DIR}/script.sh --param "one;two;three" &>> foo.txt
    WORKING_DIRECTORY ${CMAKE_BUILD_DIR}
    VERBATIM
)
add_custom_target(foo DEPENDS foo.txt)

set(PARAMS "one;two;three")
add_custom_command(OUTPUT bar.txt
    COMMAND bash ${CMAKE_SOURCE_DIR}/script.sh --param "${PARAMS}" &>> bar.txt
    WORKING_DIRECTORY ${CMAKE_BUILD_DIR}
    VERBATIM
)
add_custom_target(bar DEPENDS bar.txt)

配置后运行make foo按预期工作:

[100%] Generating foo.txt
flag: --param
items: one two three  <----
[100%] Built target foo

但是make bar会导致错误的输出,因为变量PARAMS被扩展为列表并且实际输入--param one two three不是--param "one;two;three"

[100%] Generating bar.txt
flag: --param
items: one  <----
[100%] Built target bar

如何使用变量PARAMS并仍然使外部命令的输入包含两个参数

更新

CMakeLists.txt使用涉及&(like &>>) 的输出重定向使代码变得更加复杂,这与使用VERBATIM标志相冲突,这对于使变量引用工作很重要。

标签: cmakecmake-language

解决方案


在对为什么变量用法与字面用法(用于定义变量)不同的问题有些头疼之后,我决定发布此答案以说明问题。

正如@KamilCuk 所建议的那样,使用带引号的变量--params "${PARAMS}"有效,但前提是也使用VERBATIM选项。在大多数情况下,这不是问题,但由于缺乏 CMake 支持将输出重定向到文件的能力,因此无法&>>VERBATIM模式下使用(它被引号包围)。

因此,在 中似乎不可能有重定向和非扩展变量add_custom_command,您可能只有其中任何一个。


推荐阅读