目录
2.6.REMOVE_DUPLICATES:移除列表中的重复元素
[2.13.CONCAT:合并多个列表为一个列表(等价于多次 APPEND)](#2.13.CONCAT:合并多个列表为一个列表(等价于多次 APPEND))
[4.set 命令和 list 命令异同](#4.set 命令和 list 命令异同)
1.简介
在 CMake 中,list
命令用于操作列表(Lists) ,这是 CMake 中一种重要的数据结构(用于存储多个值,如源文件路径、编译选项、宏定义等)。list
命令支持多种子命令,用于实现列表的创建、修改、查询和处理等操作。
cpp
list(COMMAND [arguments...])
其中,COMMAND
是子命令(如 APPEND
、REMOVE_ITEM
等),arguments
是对应子命令的参数。
2.常用命令
2.1.APPEND
:向列表末尾添加元素
cpp
list(APPEND my_list "item1" "item2") # 添加多个元素
# 结果:my_list = ["item1", "item2"]
2.2.PREPEND
:向列表开头添加元素
cpp
list(PREPEND my_list "item0")
# 结果:my_list = ["item0", "item1", "item2"]
2.3.INSERT
:在指定索引处插入元素
cpp
list(INSERT my_list 1 "item0.5") # 在索引 1 处插入元素
# 结果:my_list = ["item0", "item0.5", "item1", "item2"]
2.4.REMOVE_ITEM
:删除列表中指定值的元素
cpp
list(REMOVE_ITEM my_list "item0.5") # 删除值为 "item0.5" 的元素
# 结果:my_list = ["item0", "item1", "item2"]
2.5.REMOVE_AT
:删除指定索引处的元素
cpp
list(REMOVE_AT my_list 0) # 删除索引 0 处的元素
# 结果:my_list = ["item1", "item2"]
2.6.REMOVE_DUPLICATES
:移除列表中的重复元素
cpp
list(APPEND my_list "item1") # 添加重复元素
# 此时 my_list = ["item1", "item2", "item1"]
list(REMOVE_DUPLICATES my_list)
# 结果:my_list = ["item1", "item2"]
2.7.LENGTH
:获取列表长度(元素个数)
cpp
list(LENGTH my_list list_length)
message(STATUS "列表长度:${list_length}") # 输出:列表长度:2
2.8.GET
:获取列表中指定索引的元素
cpp
list(GET my_list 0 first_item) # 获取索引 0 处的元素
message(STATUS "第一个元素:${first_item}") # 输出:第一个元素:item1
2.9.JOIN
:将列表元素用指定分隔符连接成字符串
cpp
list(JOIN my_list ";" joined_string)
message(STATUS "连接后的字符串:${joined_string}") # 输出:item1;item2
2.10.REVERSE
:反转列表顺序
cpp
list(REVERSE my_list)
# 结果:my_list = ["item2", "item1"]
2.11.SORT
:对列表进行排序(按字母顺序)
cpp
list(APPEND my_list "item3" "item0")
# 此时 my_list = ["item2", "item1", "item3", "item0"]
list(SORT my_list)
# 结果:my_list = ["item0", "item1", "item2", "item3"]
2.12.CLEAR:清空列表中的所有元素
cpp
list(CLEAR temp_files) # 清空临时文件列表
2.13.CONCAT:合并多个列表 为一个列表(等价于多次 APPEND
)
cpp
list(CONCAT all_files src_files test_files) # 合并源文件和测试文件列表
3.注意事项
- CMake中的list是通过空格分隔的字符串表示的,因此要注意元素中是否包含空格或特殊字符。
- 列表索引从 0 开始(类似 C/C++ 数组)。
list
命令修改的是当前作用域内的列表变量 ,若需在父作用域或全局作用域生效,需配合PARENT_SCOPE
或CACHE
使用。- 在使用list命令时,要确保指定的list变量已经存在,否则CMake会报错。
- CMake的list命令是大小写敏感的,因此在指定元素或索引时要保持一致。
- 列表常用于
add_executable
、add_library
等命令中传递源文件列表,例如:
cpp
list(APPEND SOURCES "file1.cpp" "file2.cpp")
add_executable(my_app ${SOURCES})
4.set
命令和 list
命令异同
在 CMake 中,set
命令和 list
命令的核心区别主要体现在 功能定位 和 操作对象 上,具体可以从以下几个方面区分:
1.功能用途:通用赋值 vs 列表专项操作
set
命令的核心是 设置变量 ,可以为变量赋予任意类型的值(字符串、数字、列表、布尔值等),甚至能操作缓存变量(CACHE
选项)或环境变量(PARENT_SCOPE
等作用域)。
简单来说,只要是 "给某个变量赋值" 的场景,无论是普通数据还是复杂结构,都可以用 set
,例如:
cpp
set(APP_NAME "MyProject") # 赋值字符串
set(SOURCE_FILES main.cpp util.cpp) # 赋值列表(本质是用空格分隔的字符串)
set(DEBUG ON CACHE BOOL "Debug mode") # 设置缓存变量
list
命令的核心是 对列表进行专项操作 ,只能作用于 "列表类型" 的数据(CMake 中列表本质是用空格分隔的字符串,但 list
命令会将其按列表逻辑处理),支持对列表进行元素添加、删除、查找、排序、拆分、合并等操作,必须通过子命令指定具体操作(如 APPEND
、REMOVE_ITEM
、FIND
等)。
例如,对已有的列表变量进行修改:
cpp
list(APPEND SOURCE_FILES module.cpp) # 向列表追加元素
list(REMOVE_ITEM SOURCE_FILES util.cpp) # 从列表删除指定元素
list(SORT SOURCE_FILES) # 对列表元素排序
2.操作对象:变量赋值 vs 列表修改
set
可以 创建新变量或覆盖已有变量 ,赋值时直接给定值,无需关注值的类型是否为列表(即使是列表,也是作为一个整体赋值给变量)。
比如,用 set
定义列表时,本质是将多个元素用空格拼接成字符串,存储到变量中:
cpp
set(MY_LIST item1 item2 item3) # 变量 MY_LIST 的值是 "item1 item2 item3"(列表形式的字符串)
list
必须 基于已有的变量(且通常假设该变量存储的是列表) ,通过子命令对列表的结构进行修改(增、删、改、查元素),不会直接创建变量,而是操作已有变量中的列表数据。
例如,必须先通过 set
定义一个列表变量,再用 list
对其元素进行操作:
cpp
set(MY_LIST item1 item2) # 先用 set 定义列表变量
list(INSERT MY_LIST 1 item0) # 用 list 在索引 1 处插入元素,结果 MY_LIST 变为 "item1 item0 item2"
3.常用场景:基础变量管理 vs 复杂列表处理
-
set
的使用场景更通用,包括:- 定义项目基本信息(如项目名称、版本);
- 收集源文件、头文件路径(以列表形式赋值,但本质是变量赋值);
- 设置编译选项(如
CMAKE_CXX_FLAGS
)、缓存变量(用于用户配置)等。
-
list
的使用场景更聚焦于 列表的动态操作,例如:- 向已有源文件列表中追加特定平台的文件(
list(APPEND ...)
); - 从列表中删除不需要的元素(如排除测试文件);
- 对列表进行排序、去重、查找特定元素(
list(SORT/REMOVE_DUPLICATES/FIND ...)
); - 拆分或合并列表(如
list(SPLIT ...)
按分隔符拆字符串为列表,list(JOIN ...)
用分隔符合并列表为字符串)。
- 向已有源文件列表中追加特定平台的文件(
总之,set命令和list命令可以简单理解为:
set
是 "万能赋值器",负责给变量 "存值",值可以是任何形式(单个值或列表),甚至能创建或修改变量的作用域(如缓存、父作用域);list
是 "列表处理器",负责对 "已经存了列表值的变量" 进行 "元素级别的操作",必须依赖已有变量,且需要通过子命令指定具体的列表操作逻辑。
5.总结
子命令 | 功能描述 | 示例(列表名为 my_list ) |
---|---|---|
APPEND |
向末尾添加元素 | list(APPEND my_list "a" "b") |
PREPEND |
向开头添加元素 | list(PREPEND my_list "x") |
INSERT |
在指定索引插入元素 | list(INSERT my_list 1 "mid") |
REMOVE_ITEM |
删除指定值的元素 | list(REMOVE_ITEM my_list "b") |
REMOVE_AT |
删除指定索引的元素 | list(REMOVE_AT my_list 0) |
REMOVE_DUPLICATES |
去重 | list(REMOVE_DUPLICATES my_list) |
LENGTH |
获取列表长度 | list(LENGTH my_list len) |
GET |
获取指定索引的元素 | list(GET my_list 2 val) |
JOIN |
连接元素为字符串 | list(JOIN my_list ";" str) |
REVERSE |
反转列表顺序 | list(REVERSE my_list) |
SORT |
按字母序排序 | list(SORT my_list) |
CLEAR | 清除列表 | list(CLEAR temp_files) |
CONCAT | 合并多个列表为一个列表 | list(CONCAT all_files src_files test_files) |
通过这些子命令,你可以灵活地操作 CMake 列表,实现源文件管理、编译选项配置、跨平台条件处理等复杂逻辑。
相关链接
- CMake 官网 CMake - Upgrade Your Software Build System
- CMake 官方文档:CMake Tutorial --- CMake 4.0.2 Documentation
- CMake 源码:GitHub - Kitware/CMake: Mirror of CMake upstream repository
- CMake 源码:Sign in · GitLab