CMake指令:list

发布于:2025-06-06 ⋅ 阅读:(15) ⋅ 点赞:(0)

目录

1.简介

2.常用命令

2.1.APPEND:向列表末尾添加元素

2.2.PREPEND:向列表开头添加元素

2.3.INSERT:在指定索引处插入元素

2.4.REMOVE_ITEM:删除列表中指定值的元素

2.5.REMOVE_AT:删除指定索引处的元素

2.6.REMOVE_DUPLICATES:移除列表中的重复元素

2.7.LENGTH:获取列表长度(元素个数)

2.8.GET:获取列表中指定索引的元素

2.9.JOIN:将列表元素用指定分隔符连接成字符串

2.10.REVERSE:反转列表顺序

2.11.SORT:对列表进行排序(按字母顺序)

2.12.CLEAR:清空列表中的所有元素 

2.13.CONCAT:合并多个列表为一个列表(等价于多次 APPEND)

2.14.TRANSFORM: 列表元素变换

3.注意事项

4.set 命令和 list 命令异同

5.总结


1.简介

       在 CMake 中,list 命令用于操作列表(Lists),这是 CMake 中一种重要的数据结构(用于存储多个值,如源文件路径、编译选项、宏定义等)。list 命令支持多种子命令,用于实现列表的创建、修改、查询和处理等操作。

list(COMMAND [arguments...])

其中,COMMAND 是子命令(如 APPENDREMOVE_ITEM 等),arguments 是对应子命令的参数。

2.常用命令

2.1.APPEND:向列表末尾添加元素

list(APPEND my_list "item1" "item2")  # 添加多个元素
# 结果:my_list = ["item1", "item2"]

2.2.PREPEND:向列表开头添加元素

list(PREPEND my_list "item0")
# 结果:my_list = ["item0", "item1", "item2"]

2.3.INSERT:在指定索引处插入元素

list(INSERT my_list 1 "item0.5")  # 在索引 1 处插入元素
# 结果:my_list = ["item0", "item0.5", "item1", "item2"]

2.4.REMOVE_ITEM:删除列表中指定值的元素

list(REMOVE_ITEM my_list "item0.5")  # 删除值为 "item0.5" 的元素
# 结果:my_list = ["item0", "item1", "item2"]

2.5.REMOVE_AT:删除指定索引处的元素

list(REMOVE_AT my_list 0)  # 删除索引 0 处的元素
# 结果:my_list = ["item1", "item2"]

2.6.REMOVE_DUPLICATES:移除列表中的重复元素

list(APPEND my_list "item1")  # 添加重复元素
# 此时 my_list = ["item1", "item2", "item1"]
list(REMOVE_DUPLICATES my_list)
# 结果:my_list = ["item1", "item2"]

2.7.LENGTH:获取列表长度(元素个数)

list(LENGTH my_list list_length)
message(STATUS "列表长度:${list_length}")  # 输出:列表长度:2

2.8.GET:获取列表中指定索引的元素

list(GET my_list 0 first_item)  # 获取索引 0 处的元素
message(STATUS "第一个元素:${first_item}")  # 输出:第一个元素:item1

2.9.JOIN:将列表元素用指定分隔符连接成字符串

list(JOIN my_list ";" joined_string)
message(STATUS "连接后的字符串:${joined_string}")  # 输出:item1;item2

2.10.REVERSE:反转列表顺序

list(REVERSE my_list)
# 结果:my_list = ["item2", "item1"]

2.11.SORT:对列表进行排序(按字母顺序)

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:清空列表中的所有元素 

list(CLEAR temp_files)  # 清空临时文件列表

2.13.CONCAT:合并多个列表为一个列表(等价于多次 APPEND

list(CONCAT all_files src_files test_files)  # 合并源文件和测试文件列表

2.14.TRANSFORM: 列表元素变换

在 CMake 3.12 及以上版本中,list(TRANSFORM ...) 用于对列表中的每个元素执行转换操作(如添加前缀、替换字符串、调用函数等),并将结果存储到原列表或新变量中。这是处理列表元素的强大工具,尤其适合批量处理文件路径、编译选项等场景。

list(TRANSFORM <list> <ACTION> ... [OUTPUT_VARIABLE <output>])
  • <list>:要操作的列表变量名。
  • <ACTION>:转换动作,支持以下几种:
    • PREPEND <prefix>:为每个元素添加前缀。
    • APPEND <suffix>:为每个元素添加后缀。
    • REPLACE <match> <replace>:替换元素中的匹配字符串。
    • STRIP:去除元素首尾的空格。
    • TOUPPER/TOLOWER:转换为大写 / 小写。
    • GENEX_STRIP:移除生成器表达式(如 $<CONFIG:Debug>)。
  • OUTPUT_VARIABLE <output>(可选):将结果存储到新变量,而非覆盖原列表。

常用场景示例

1.添加前缀 / 后缀(最常用)

set(SOURCES "main.cpp" "utils.cpp")

# 为每个源文件添加 "src/" 前缀(等效于 "src/main.cpp" "src/utils.cpp")
list(TRANSFORM SOURCES PREPEND "src/")

# 为每个源文件添加 "_test" 后缀(等效于 "main_test.cpp" "utils_test.cpp")
list(TRANSFORM SOURCES APPEND "_test.cpp")

2.替换字符串

set(PATHS "/old/path/file1" "/old/path/file2")

# 将 "/old/path/" 替换为 "/new/path/"
list(TRANSFORM PATHS REPLACE "/old/path/" "/new/path/")

3.大小写转换

set(FLAGS "Debug" "Release")

# 转换为大写(等效于 "DEBUG" "RELEASE")
list(TRANSFORM FLAGS TOUPPER)

# 转换为小写(等效于 "debug" "release")
list(TRANSFORM FLAGS TOLOWER)

4.输出到新变量(保留原列表)

set(INPUT "file1.txt" "file2.txt")

# 将结果存入 NEW_INPUT,原 INPUT 不变
list(TRANSFORM INPUT PREPEND "data/" OUTPUT_VARIABLE NEW_INPUT)
# NEW_INPUT 为 "data/file1.txt" "data/file2.txt"

5.结合生成器表达式

生成器表达式可在构建时动态计算值,例如:

set(SOURCES "main.cpp" "utils.cpp")

# 为每个源文件添加基于配置的编译定义(如 Debug 模式下定义 DEBUG=1)
list(TRANSFORM SOURCES APPEND "$<$<CONFIG:Debug>:-DDEBUG=1>")

3.注意事项

  • CMake中的list是通过空格分隔的字符串表示的,因此要注意元素中是否包含空格或特殊字符。
  • 列表索引从 0 开始(类似 C/C++ 数组)。
  • list 命令修改的是当前作用域内的列表变量,若需在父作用域或全局作用域生效,需配合 PARENT_SCOPE 或 CACHE 使用。
  • 在使用list命令时,要确保指定的list变量已经存在,否则CMake会报错。
  • CMake的list命令是大小写敏感的,因此在指定元素或索引时要保持一致。
  • 列表常用于 add_executableadd_library 等命令中传递源文件列表,例如:
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,例如:

set(APP_NAME "MyProject")          # 赋值字符串  
set(SOURCE_FILES main.cpp util.cpp) # 赋值列表(本质是用空格分隔的字符串)  
set(DEBUG ON CACHE BOOL "Debug mode") # 设置缓存变量  

list 命令的核心是 对列表进行专项操作,只能作用于 “列表类型” 的数据(CMake 中列表本质是用空格分隔的字符串,但 list 命令会将其按列表逻辑处理),支持对列表进行元素添加、删除、查找、排序、拆分、合并等操作,必须通过子命令指定具体操作(如 APPENDREMOVE_ITEMFIND 等)。
例如,对已有的列表变量进行修改:

list(APPEND SOURCE_FILES module.cpp) # 向列表追加元素  
list(REMOVE_ITEM SOURCE_FILES util.cpp) # 从列表删除指定元素  
list(SORT SOURCE_FILES) # 对列表元素排序  

2.操作对象:变量赋值 vs 列表修改

set 可以 创建新变量或覆盖已有变量,赋值时直接给定值,无需关注值的类型是否为列表(即使是列表,也是作为一个整体赋值给变量)。
比如,用 set 定义列表时,本质是将多个元素用空格拼接成字符串,存储到变量中:

set(MY_LIST item1 item2 item3) # 变量 MY_LIST 的值是 "item1 item2 item3"(列表形式的字符串)  

list 必须 基于已有的变量(且通常假设该变量存储的是列表),通过子命令对列表的结构进行修改(增、删、改、查元素),不会直接创建变量,而是操作已有变量中的列表数据。
例如,必须先通过 set 定义一个列表变量,再用 list 对其元素进行操作:

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)
TRANSFORM 列表元素转换 list(TRANSFORM SOURCES PREPEND "src/")

通过这些子命令,你可以灵活地操作 CMake 列表,实现源文件管理、编译选项配置、跨平台条件处理等复杂逻辑。

相关链接


网站公告

今日签到

点亮在社区的每一天
去签到