You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

CMake中add_custom_target的COMMAND参数无法正确拆分变量内多参数的问题求助

CMake中add_custom_target的COMMAND参数无法正确拆分变量内多参数的问题求助

问题原因

你碰到的这个问题,核心是CMake对COMMAND参数的解析逻辑和常规命令行不同

当你在COMMAND里使用${CARGO_BUILD_FLAGS}时,CMake会把这个变量的整个值当成单个完整的命令行参数传递给cargo,而不会自动按空格拆分成多个独立参数。

举个Debug模式的例子:CARGO_BUILD_FLAGS的值是"--no-default-features --features debug_mode",CMake会把这个字符串原封不动作为一个参数传给cargo build,此时cargo实际收到的命令是:

cargo build --package proj-bin "--no-default-features --features debug_mode"

这就导致cargo把这个长字符串识别成一个未知的单一参数,而非两个独立的选项,自然会报错。

而当你直接把所有参数写死在COMMAND里时,CMake会自动按空格将内容拆分成多个独立参数,cargo就能正确识别每个选项,所以编译正常。


解决方案

解决的核心是让CMake把CARGO_BUILD_FLAGS的内容处理成独立的参数列表,而非单个字符串。这里有几种实用的方法:

方法1:直接用CMake列表形式定义变量

CMake中用分号;分隔的内容会被识别为列表,每个元素对应一个独立参数。修改变量定义如下:

if(CMAKE_BUILD_TYPE STREQUAL "Debug")
    # 用分号分隔每个参数,构成CMake列表
    set(CARGO_BUILD_FLAGS "--no-default-features;--features;debug_mode")
    set(RUST_BUILD_TYPE "debug")
else()
    set(CARGO_BUILD_FLAGS "--release;--no-default-features;--features;release_mode")
    set(RUST_BUILD_TYPE "release")
endif()

add_custom_target(
    build-binary ALL
    COMMAND cargo build --package proj-bin ${CARGO_BUILD_FLAGS}
    WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
    COMMENT "Building Rust project with Cargo..."
)

此时${CARGO_BUILD_FLAGS}会被展开为多个独立参数,效果和你手动写死所有参数完全一致。

方法2:用separate_arguments拆分现有字符串变量

如果你不想修改变量的初始空格分隔写法,可以用CMake的separate_arguments命令把空格分隔的字符串转成列表:

if(CMAKE_BUILD_TYPE STREQUAL "Debug")
    set(CARGO_BUILD_FLAGS "--no-default-features --features debug_mode")
    set(RUST_BUILD_TYPE "debug")
else()
    set(CARGO_BUILD_FLAGS "--release --no-default-features --features release_mode")
    set(RUST_BUILD_TYPE "release")
endif()

# 按Unix命令行规则,把空格分隔的字符串拆成CMake列表
separate_arguments(CARGO_BUILD_FLAGS UNIX_COMMAND "${CARGO_BUILD_FLAGS}")

add_custom_target(
    build-binary ALL
    COMMAND cargo build --package proj-bin ${CARGO_BUILD_FLAGS}
    WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
    COMMENT "Building Rust project with Cargo..."
)

方法3:使用COMMAND_EXPAND_LISTS选项(CMake 3.18+)

如果你使用的是CMake 3.18及以上版本,可以在add_custom_target中添加COMMAND_EXPAND_LISTS选项,它会自动将COMMAND中的列表变量展开为独立参数:

if(CMAKE_BUILD_TYPE STREQUAL "Debug")
    set(CARGO_BUILD_FLAGS "--no-default-features;--features;debug_mode")
    set(RUST_BUILD_TYPE "debug")
else()
    set(CARGO_BUILD_FLAGS "--release;--no-default-features;--features;release_mode")
    set(RUST_BUILD_TYPE "release")
endif()

add_custom_target(
    build-binary ALL
    COMMAND cargo build --package proj-bin ${CARGO_BUILD_FLAGS}
    COMMAND_EXPAND_LISTS  # 关键选项
    WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
    COMMENT "Building Rust project with Cargo..."
)

验证

用以上任意一种方法修改后,cargo收到的命令行参数都会和你手动写死的完全一致:

cargo build --package proj-bin --no-default-features --features debug_mode

此时就能正常编译你的Rust项目了。

备注:内容来源于stack exchange,提问作者Harry

火山引擎 最新活动