You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

CMake中set(var ${var} value)与set(var "${var}" value)工作机制解析

CMake两种set写法差异的底层原因

先看两种代码的实际运行效果:

无引号的代码示例

message("foo: ${foo}")
set(foo ${foo} abc)
message("foo: ${foo}")
set(foo ${foo} def)
message("foo: ${foo}")
set(foo ${foo} ghi)
message("foo: ${foo}")

输出:

foo: 
foo: abc
foo: abc;def
foo: abc;def;ghi

带引号的代码示例

message("foo: ${foo}")
set(foo "${foo}" abc)
message("foo: ${foo}")
set(foo "${foo}" def)
message("foo: ${foo}")
set(foo "${foo}" ghi)
message("foo: ${foo}")

输出:

foo: 
foo: ;abc
foo: ;abc;def
foo: ;abc;def;ghi

下面从CMake底层参数解析和变量展开逻辑拆解差异原因:

1. 无引号写法的逻辑

当foo还未定义时,${foo}会展开成空字符串。CMake在解析不带引号的参数时,会自动忽略空字符串参数——也就是说,set(foo ${foo} abc)实际等价于set(foo abc),直接把foo赋值为abc。

后续每次调用set(foo ${foo} def)时,${foo}是之前的列表值(比如第一次赋值后的abc),展开后作为单个参数传递,和def一起被set命令合并成新的分号分隔列表,所以结果依次是abc;def、abc;def;ghi。

2. 带引号写法的逻辑

同样,未定义的${foo}展开成空字符串,但引号会强制CMake把这个空字符串当作一个有效的独立参数。此时set(foo "${foo}" abc)实际接收到的参数是foo、空字符串、abc,CMake会把这两个值合并成列表,也就是;abc(空元素在前,abc在后,分号是CMake列表的默认分隔符)。

后续调用set(foo "${foo}" def)时,${foo}是之前的列表;abc,被引号包裹后会被当作一个完整的字符串";abc"传递,再加上def参数,合并后就得到;abc;def,重复操作就会得到;abc;def;ghi。

核心差异点

说白了,问题本质是CMake对空参数的处理规则:

  • 不用引号时,未定义变量展开的空字符串会被参数解析器直接跳过,不会成为列表的一部分;
  • 用引号包裹时,空字符串会被保留为列表里的一个正式空元素,后续每次赋值都会带着这个空元素叠加新内容。

内容的提问来源于stack exchange,提问作者starball

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 20:12:43