跳到主要内容

kmpkg_list

kmpkg_list 是 CMake 原生 list() 函数的替代方案,重点优化了对包含内部分号的元素(例如嵌套列表)的处理逻辑。

用法

kmpkg_list(SET <输出变量> [<元素>...])
kmpkg_list(<子命令> <列表变量> [<其他参数>...])

说明

当需要正确处理“列表的列表(嵌套列表)”时,应优先使用 kmpkg_list() 而非原生 list()

kmpkg_list() 支持原生 list() 函数的所有子命令,但存在以下限制:

  • GETREMOVE_ITEMREMOVE_AT 仅支持单个索引/值(不支持批量操作);
  • POP_BACKPOP_FRONT 不支持将弹出的值存入另一个输出变量。需采用 C++ 风格:先 GET 获取值,再执行 POP_(BACK|FRONT)
  • 不支持 FILTERTRANSFORM 子命令。

kmpkg_list 额外新增了 kmpkg_list(SET) 子命令,该子命令可正确创建嵌套列表(列表的列表)。

更多基础用法可参考 CMake 官方 list() 文档

关于零元素列表的特殊说明

kmpkg_list 最核心的特殊行为源于空字符串 "" 的双重语义:CMake 中 "" 既表示“零元素列表”,也表示“包含一个空元素的列表”。kmpkg_list 始终将 "" 解读为零元素列表,这可能导致以下特殊行为:

示例 1:向空列表追加两个空元素

set(lst "")
kmpkg_list(APPEND lst "" "")
# 最终 lst = ";"(表示包含两个空元素的列表)

示例 2:向空列表追加一个空元素(最特殊的场景)

set(lst "")
kmpkg_list(APPEND lst "")
# 最终 lst = ""
# 原因:空列表追加一个空元素后,理论上是“包含一个空元素的列表”,但受 "" 语义影响仍表现为 ""

非空列表无此特殊行为:

set(lst "a")
kmpkg_list(APPEND lst "")
# 最终 lst = "a;"(表示包含 "a" 和一个空元素的列表)

示例

1. 创建列表(支持嵌套)

kmpkg_list(SET foo_param)  # 初始化空列表
if(DEFINED arg_FOO)
kmpkg_list(SET foo_param FOO "${arg_FOO}") # 构建嵌套列表
endif()

2. 向列表追加含内部分号的元素

set(OPTIONS -DFOO=BAR)
if(KMPKG_TARGET_IS_WINDOWS)
# 原生 list() 会将 "-DOS=WINDOWS;FOO" 拆分为两个元素,kmpkg_list 可保留为单个元素
kmpkg_list(APPEND OPTIONS "-DOS=WINDOWS;FOO")
endif()

3. 弹出列表末尾元素

if(NOT list STREQUAL "")  # 先判断列表非空
kmpkg_list(GET list end -1) # 先获取末尾元素到变量 end
kmpkg_list(POP_BACK list) # 再弹出末尾元素
endif()

源码

scripts/cmake/kmpkg_list.cmake