Cmake命令之list介绍

  • 命令格式

    list (subcommand <list> [args...])
    subcommand为具体的列表操作子命令,例如读取查找修改排序等。<list>为待操作的列表变量,[args...]为对列表变量操作需要使用的参数表,不同的子命令对应的参数也不一致。

    list命令即对列表的一系列操作,cmake中的列表变量是用分号;分隔的一组字符串,创建列表可以使用set命令(参考set命令),例如:set (var a b c d)创建了一个列表 "a;b;c;d",而set (var "a b c d")则是只创建了一个变量"a c c d"。list命令的具体格式根据子命令不同会有所区别。

  • 命令解析

      对列表的操作分为读取查找修改排序等4个大类,下面按照这四个大类逐一对列表的子命令进行介绍。

    1. 列表的读取

    1.1 LENGTH:子命令LENGTH用于读取列表长度

    list (LENGTH <list> <output variable>)
      <output variable>为新创建的变量,用于存储列表的长度。

    # CMakeLists.txt
    cmake_minimum_required (VERSION 3.12.2)
    project (list_cmd_test)
    set (list_test a b c d) # 创建列表变量"a;b;c;d"
    list (LENGTH list_test length)
    message (">>> LENGTH: ${length}")
    
    # 输出
    >>> LENGTH: 4
    

    1.2 GET:子命令GET用于读取列表中指定索引的的元素,可以指定多个索引。

    list (GET <list> <element index> [<element index> ...] <output variable>)
      <element index>为列表元素的索引,从0开始编号,索引0的元素为列表中的第一个元素;索引也可以是负数,-1表示列表的最后一个元素,-2表示列表倒数第二个元素,以此类推。注意:当索引(不管是正还是负)超过列表的长度,运行会报错(list index: XX out of range)。
      <output variable>为新创建的变量,存储指定索引元素的返回结果,也是一个列表。

    # CMakeLists.txt
    cmake_minimum_required (VERSION 3.12.2)
    project (list_cmd_test)
    set (list_test a b c d) # 创建列表变量"a;b;c;d"
    list (GET list_test 0 1 -1 -2 list_new)
    message (">>> GET: ${list_new}")
    
    # 输出
    >>> GET: a;b;d;c
    

    1.3 JOIN:子命令JOIN用于将列表中的元素用连接字符串连接起来组成一个字符串,注意,此时返回的结果已经不是一个列表。

    list (JOIN <list> <glue> <output variable>)
      将列表中的元素用<glue>链接起来,组成一个字符串后,返回给<output variable>变量。对于不属于列表的多个字符串的连接操作,可以使用string()命令的连接操作。

    # CMakeLists.txt
    cmake_minimum_required (VERSION 3.12.2)
    project (list_cmd_test)
    set (list_test a b c d) # 创建列表变量"a;b;c;d"
    list (JOIN list_test -G- list_new)
    message (">>> JOIN: ${list_new}")
    
    # 输出
    >>> JOIN: a-G-b-G-c-G-d
    

    1.4 SUBLIST:子命令SUBLIST用于获取列表中的一部分(子列表)。

    list (SUBLIST <list> <begin> <length> <output variable>)
      返回列表<list>中,从索引<begin>开始,长度为<length>的子列表。如果长度<length>为0,返回的时空列表。如果长度<length>为-1或列表的长度小于<begin>+<length>,那么将列表中从<begin>索引开始的剩余元素返回。

    # CMakeLists.txt
    cmake_minimum_required (VERSION 3.12.2)
    project (list_cmd_test)
    set (list_test a b c d) # 创建列表变量"a;b;c;d"
    list (SUBLIST list_test 1 2 list_new)
    message (">>> SUBLIST: ${list_new}")
    list (SUBLIST list_test 1 0 list_new)
    message (">>> SUBLIST: ${list_new}")
    list (SUBLIST list_test 1 -1 list_new)
    message (">>> SUBLIST: ${list_new}")
    list (SUBLIST list_test 1 8 list_new)
    message (">>> SUBLIST: ${list_new}")
    
    # 输出
    >>> SUBLIST: b;c
    >>> SUBLIST:
    >>> SUBLIST: b;c;d
    >>> SUBLIST: b;c;d
    
    2. 列表的查找

    2.1 FIND:子命令FIND用于查找列表是否存在指定的元素。

    list (FIND <list> <value> <output variable>)
      如果列表<list>中存在<value>,那么返回<value>在列表中的索引,如果未找到则返回-1。

    # CMakeLists.txt
    cmake_minimum_required (VERSION 3.12.2)
    project (list_cmd_test)
    set (list_test a b c d) # 创建列表变量"a;b;c;d"
    list (FIND list_test d list_index)
    message (">>> FIND 'd': ${list_index}")
    list (FIND list_test e list_index)
    message (">>> FIND 'e': ${list_index}")
    
    # 输出
    >>> FIND 'd': 3
    >>> FIND 'e': -1
    
    3. 列表的修改

      列表的修改子命令可能会改变原列表的值。
    3.1 APPEND:子命令APPEND用于将元素追加到列表。

    list (APPEND <list> [<element> ...])
      此命令会改变原列表的值。

    # CMakeLists.txt
    cmake_minimum_required (VERSION 3.12.2)
    project (list_cmd_test)
    set (list_test a b c d) # 创建列表变量"a;b;c;d"
    list (APPEND list_test 1 2 3 4)
    message (">>> APPEND: ${list_test}")
    
    # 输出
    >>> APPEND: a;b;c;d;1;2;3;4
    

    3.2 FILTER:子命令FILTER用于根据正则表达式包含或排除列表中的元素。

    list (FILTER <list> <INCLUDE|EXCLUDE> REGEX <regular_expression>)
      根据模式的匹配结果,将元素添加(INCLUDE选项)到列表或者从列表中排除(EXCLUDE选项)。此命令会改变原来列表的值。模式REGEX表明会对列表进行正则表达式匹配。(从官方文档目前未找到其他模式)

    # CMakeLists.txt
    cmake_minimum_required (VERSION 3.12.2)
    project (list_cmd_test)
    set (list_test a b c d 1 2 3 4) # 创建列表变量"a;b;c;d;1;2;3;4"
    message (">>> the LIST is: ${list_test}")
    list (FILTER list_test INCLUDE REGEX [a-z])
    message (">>> FILTER: ${list_test}")
    list (FILTER list_test EXCLUDE REGEX [a-z])
    message (">>> FILTER: ${list_test}")
    
    # 输出
    >>> the LIST is: a;b;c;d;1;2;3;4
    >>> FILTER: a;b;c;d
    >>> FILTER: 
    

    3.3 INSERT:子命令INSERT用于在指定位置将元素(一个或多个)插入到列表中。

    list (INSERT <list> <element_index> <element> [<element> ...])
      <element_index>为列表指定的位置,如果元素的位置超出列表的范围,会报错。此命令会改变原来列表的值。

    # CMakeLists.txt
    cmake_minimum_required (VERSION 3.12.2)
    project (list_cmd_test)
    set (list_test a b c d) # 创建列表变量"a;b;c;d"
    list (INSERT list_test 0 8 8 8 8)
    message (">>> INSERT: ${list_test}")
    list (INSERT list_test -1 9 9 9 9)
    message (">>> INSERT: ${list_test}")
    list (LENGTH list_test lenght)
    list (INSERT list_test ${length} 0)
    message (">>> INSERT: ${list_test}")
    
    # 输出
    >>> INSERT: 8;8;8;8;a;b;c;d
    >>> INSERT: 8;8;8;8;a;b;c;9;9;9;9;d
    >>> INSERT: 8;8;8;8;a;b;c;9;9;9;9;d;0
    

    3.4 POP_BACK:子命令POP_BACK用于将列表中最后元素移除。

    list (POP_BACK <list> [<out-var>...])
      <out-var>如果未指定输出变量,则仅仅是将原列表的最后一个元素移除。如果指定了输出变量,则会将最后一个元素移入到该变量,并将元素从原列表中移除。如果指定了多个输出变量,则依次将原列的最后一个元素移入到输出变量中,如果输出变量个数大于列表的长度,那么超出部分的输出变量未定义。

    # CMakeLists.txt
    cmake_minimum_required (VERSION 3.12.2)
    project (list_cmd_test)
    set (list_test a b c d) # 创建列表变量"a;b;c;d"
    list (POP_BACK list_test)
    message (">>> POP_BACK: ${list_test}")
    list (POP_BACK list_test outvar1 outvar2 outvar3 outvar4)
    message (">>> POP_BACK: ${outvar1}、${outvar2}、${outvar3}、${outvar4}")
    
    # 输出
    >>> POP_BACK: a;b;c
    >>> POP_BACK: c、b、a、
    

    3.5 POP_FRONT:子命令POP_FRONT用于将列表中第一个元素移除。

    list (POP_FRONT <list> [<out-var>...])
      <out-var>如果未指定输出变量,则仅仅是将原列表的第一个元素移除。如果指定了输出变量,则会将第一个元素移入到该变量,并将元素从原列表中移除。如果指定了多个输出变量,则依次将原列的第一个元素移入到输出变量中,如果输出变量个数大于列表的长度,那么超出部分的输出变量未定义。

    # CMakeLists.txt
    cmake_minimum_required (VERSION 3.12.2)
    project (list_cmd_test)
    set (list_test a b c d) # 创建列表变量"a;b;c;d"
    list (POP_FRONT list_test)
    message (">>> POP_FRONT: ${list_test}")
    list (POP_FRONT list_test outvar1 outvar2 outvar3 outvar4)
    message (">>> POP_FRONT: ${outvar1}、${outvar2}、${outvar3}、${outvar4}")
    
    # 输出
    >>> POP_FRONT: b;c;d
    >>> POP_FRONT: b、c、d、
    

    3.6 PREPEND:子命令PREPEND用于将元素插入到列表的0索引位置。

    list (PREPEND <list> [<element> ...])
      如果待插入的元素是多个,则相当于把多个元素整体“平移”到原列表0索引的位置。

    # CMakeLists.txt
    cmake_minimum_required (VERSION 3.12.2)
    project (list_cmd_test)
    set (list_test a b c d) # 创建列表变量"a;b;c;d"
    list (PREPEND list_test z)
    message (">>> PREPEND: ${list_test}")
    list (PREPEND list_test p q r s t)
    message (">>> POP_FRONT: ${list_test}")
    
    # 输出
    >>> PREPEND: z;a;b;c;d
    >>> PREPEND: p;q;r;s;t;z;a;b;c;d
    

    3.7 REMOVE_ITEM:子命令REMOVE_ITEM用于将指定的元素从列表中移除。

    list (REMOVE_ITEM <list> <value> [<value> ...])
      注意:指定的是元素的值,当指定的值在列表中存在重复的时候,会删除所有重复的值。

    # CMakeLists.txt
    cmake_minimum_required (VERSION 3.12.2)
    project (list_cmd_test)
    set (list_test a a b c c d) # 创建列表变量"a;a;b;c;c;d"
    list (REMOVE_ITEM list_test a)
    message (">>> REMOVE_ITEM: ${list_test}")
    list (REMOVE_ITEM list_test b e)
    message (">>> REMOVE_ITEM: ${list_test}")
    
    # 输出
    >>> REMOVE_ITEM: b;c;c;d
    >>> REMOVE_ITEM: c;c;d
    

    3.8 REMOVE_AT:子命令REMOVE_AT用于将指定索引的元素从列表中移除。

    list (REMOVE_AT <list> <index> [<index> ...])
      注意:指定的是元素的索引,当指定的索引不存在的时候,会提示错误;如果指定的索引存在重复,则只会执行一次删除动作。

    # CMakeLists.txt
    cmake_minimum_required (VERSION 3.12.2)
    project (list_cmd_test)
    set (list_test a b c d e f) # 创建列表变量"a;b;c;d;e;f"
    list (REMOVE_AT list_test 0 -1)
    message (">>> REMOVE_AT: ${list_test}")
    list (REMOVE_AT list_test 1 1 1 1)
    message (">>> REMOVE_AT: ${list_test}")
    
    # 输出
    >>> REMOVE_AT: b;c;d;e
    >>> REMOVE_AT: b;d;e
    

    3.9 REMOVE_DUPLICATES:子命令REMOVE_DUPLICATES用于移除列表中的重复元素。

    list (REMOVE_DUPLICATES <list>)
      如果没有重复元素,原列表不会做更改。如果原列表所有元素都是一样的,则会保留一个;如果有多个重复元素,则保留第一个。

    # CMakeLists.txt
    cmake_minimum_required (VERSION 3.12.2)
    project (list_cmd_test)
    set (list_test a a a b b b c c c d d d) # 创建列表变量"a;a;a;b;b;b;c;c;c;d;d;d;"
    list (REMOVE_DUPLICATES list_test)
    message (">>> REMOVE_DUPLICATES: ${list_test}")
    set (list_test a a a a) 
    list (REMOVE_DUPLICATES list_test)
    message (">>> REMOVE_DUPLICATES: ${list_test}")
    set (list_test a b c a d a e a f)  # 多个元素重复,只保留第一个 
    list (REMOVE_DUPLICATES list_test)
    message (">>> REMOVE_DUPLICATES: ${list_test}")
    
    # 输出
    >>> REMOVE_DUPLICATES: a;b;c;d
    >>> REMOVE_DUPLICATES: a
    >>> REMOVE_DUPLICATES: a;b;c;d;e;f
    

    3.10 TRANSFORM:子命令TRANSFORM用于将指定的动作运用到所有或者部分指定的元素,结果可以存到原列表中,或存到指定输出新的变量中。

    list (TRANSFORM <list> <ACTION> [<SELECTOR>]
    [OUTPUT_VARIABLE <output variable>])

      选项ACTION用于指定应用到列表元素的动作,动作必须在如下中选择一个:APPEND/PREPEND/TOUPPER/TOUPPER/STRIP/GENEX_STRIP/REPLACE;选项SELECTOR用于指定哪些列表元素会被选择,并执行动作,SELECTOR只能从如下中选择一个:AT/FOR/REGEX;选项OUTPUT_VARIABLE用于指定新的输出变量。 TRANSFORM命令不会改变列表中元素的个数。

    ACTION选项的解析如下:

    • APPEND,PREPEND:在列表的每个元素后/前插入指定的值。
      list (TRANSFORM <list> <APPEND|PREPEND> <value> [OUTPUT_VARIABLE <output variable>])
    # CMakeLists.txt
    cmake_minimum_required (VERSION 3.12.2)
    project (list_cmd_test)
    set (list_test a b c d)
    list (TRANSFORM list_test APPEND B OUTPUT_VARIABLE list_test_out)
    list (TRANSFORM list_test APPEND B)
    message (">>> TRANSFORM-APPEND: ${list_test} --- ${list_test_out}")
    set (list_test a b c d)
    list (TRANSFORM list_test PREPEND F OUTPUT_VARIABLE list_test_out)
    list (TRANSFORM list_test PREPEND F)
    message (">>> TRANSFORM-PREPEND: ${list_test} --- ${list_test_out}")
    
    # 输出
    >>> TRANSFORM-APPEND: aB;bB;cB;dB --- aB;bB;cB;dB
    >>> TRANSFORM-PREPEND: Fa;Fb;Fc;Fd --- Fa;Fb;Fc;Fd
    
    • TOUPPER, TOLOWER:将列表的每一个元素转换成大写/小写。
      list(TRANSFORM <list> <TOLOWER|TOUPPER> [OUTPUT_VARIABLE <output variable>])
    # CMakeLists.txt
    cmake_minimum_required (VERSION 3.12.2)
    project (list_cmd_test)
    set (list_test a bb c d)
    list (TRANSFORM list_test TOUPPER OUTPUT_VARIABLE list_test_out)
    list (TRANSFORM list_test TOUPPER)
    message (">>> TRANSFORM-TOUPPER: ${list_test} --- ${list_test_out}")
    set (list_test A B C DD)
    list (TRANSFORM list_test TOLOWER OUTPUT_VARIABLE list_test_out)
    list (TRANSFORM list_test TOLOWER)
    message (">>> TRANSFORM-TOLOWER: ${list_test} --- ${list_test_out}")
    
    # 输出
    >>> TRANSFORM-TOUPPER: A;BB;C;D --- A;BB;C;D
    >>> TRANSFORM-TOLOWER: a;b;c;dd --- a;b;c;dd
    
    • STRIP:去除列表中每一个元素的头尾空格。
      list(TRANSFORM <list> STRIP [OUTPUT_VARIABLE <output variable>])
    # CMakeLists.txt
    cmake_minimum_required (VERSION 3.12.2)
    project (list_cmd_test)
    set (list_test " a b " "   bb   " "c e" d)
    message (">>> TRANSFORM list: ${list_test}")
    list (TRANSFORM list_test STRIP OUTPUT_VARIABLE list_test_out)
    list (TRANSFORM list_test STRIP)
    message (">>> TRANSFORM-STRIP: ${list_test} --- ${list_test_out}")
    
    # 输出
    >>> TRANSFORM list:  a b ;   bb   ;c e;d
    >>> TRANSFORM-STRIP: a b;bb;c e;d --- a b;bb;c e;d
    
    • GENEX_STRIP:裁剪列表中任何为产生表达式的元素(产生表达式请参考此处)从下面的例子可以看出,虽然列表中是产生表达式的元素被清除了,但是实际列表的长度没有变化,产生表达式的位置被空元素占据了(TRANSFROM命令不会改变列表元素的个数)。
      list(TRANSFORM <list> GENEX_STRIP [OUTPUT_VARIABLE <output variable>])
    # CMakeLists.txt
    cmake_minimum_required (VERSION 3.12.2)
    project (list_cmd_test)
    set (list_test a b c d $<STREQUAL:"a","a"> $<STREQUAL:"a","b">)
    list (LENGTH list_test len)
    message (">>> TRANSFORM list: ${list_test}, len=${len}")
    list (TRANSFORM list_test GENEX_STRIP OUTPUT_VARIABLE list_test_out)
    list (TRANSFORM list_test GENEX_STRIP) 
    list (LENGTH list_test len_new)
    message (">>> TRANSFORM-STRIP: ${list_test} --- ${list_test_out}, new len = ${len_new}")
    
    # 输出
    >>> TRANSFORM list: a;b;c;d;$<STREQUAL:"a","a">;$<STREQUAL:"a","b">, len = 6
    >>> TRANSFORM-STRIP: a;b;c;d;; --- a;b;c;d;;, new len = 6
    
    • REPLACE:尽可能多的查找(用正则表达式<regular_expression>匹配)并替换(用<replace_expression>替换)列表中符合条件的元素。
      list(TRANSFORM <list> REPLACE <regular_expression> <replace_expression> [OUTPUT_VARIABLE<output variable>])
    # CMakeLists.txt
    cmake_minimum_required (VERSION 3.12.2)
    project (list_cmd_test)
    set (list_test aa bb cc dd 1a b2 33 44)
    message (">>> TRANSFORM-list: ${list_test}")
    list (TRANSFORM list_test REPLACE "[a-c]" 9)    
    message (">>> TRANSFORM-REPLACE: ${list_test}")
    
    # 输出
    >>> TRANSFORM-list: aa;bb;cc;dd;1a;b2;33;44
    >>> TRANSFORM-REPLACE: 99;99;99;dd;19;92;33;44
    

    SELECTOR选项的解析如下:

    • AT:指定元素的索引(可以是多个)。
      list(TRANSFORM <list> <ACTION> AT <index> [<index> ...] [OUTPUT_VARIABLE <output variable>])
    # CMakeLists.txt
    cmake_minimum_required (VERSION 3.12.2)
    project (list_cmd_test)
    set (list_test a b c d)
    message (">>> TRANSFORM-list: ${list_test}")
    list (TRANSFORM list_test APPEND Q AT 1 2 OUTPUT_VARIABLE list_test_out)
    list (TRANSFORM list_test APPEND Q AT 1 2)
    message (">>> TRANSFORM-AT: ${list_test} --- ${list_test_out}")
    
    # 输出
    >>> TRANSFORM-list: a;b;c;d
    >>> TRANSFORM-REPLACE: a;bQ;cQ;d --- a;bQ;cQ;d
    
    • FOR:指定元素的范围和迭代的步长。
      list(TRANSFORM <list> <ACTION> FOR <start> <stop> [<step>] [OUTPUT_VARIABLE <output variable>])
    # CMakeLists.txt
    cmake_minimum_required (VERSION 3.12.2)
    project (list_cmd_test)
    set (list_test a b c d e f g h i j k)
    message (">>> TRANSFORM-list: ${list_test}")
    list (TRANSFORM list_test APPEND Q FOR 0 -1 2 OUTPUT_VARIABLE list_test_out)
    list (TRANSFORM list_test APPEND Q FOR 0 -1 2)
    message (">>> TRANSFORM-FOR: ${list_test} --- ${list_test_out}")
    
    # 输出
    >>> TRANSFORM-list: a;b;c;d;e;f;g;h;i;j;k
    >>> TRANSFORM-REPLACE: aQ;b;cQ;d;eQ;f;gQ;h;iQ;j;kQ --- aQ;b;cQ;d;eQ;f;gQ;h;iQ;j;kQ
    
    • REGEX:指定正则表达式,符合正则表达式的元素才会被处理。
      list(TRANSFORM <list> <ACTION> REGEX <regular_expression>[OUTPUT_VARIABLE <output variable>])
    # CMakeLists.txt
    cmake_minimum_required (VERSION 3.12.2)
    project (list_cmd_test)
    set (list_test a b c d e f g h i j k)
    message (">>> TRANSFORM-list: ${list_test}")
    list (TRANSFORM list_test APPEND Q REGEX "[a-f]" OUTPUT_VARIABLE list_test_out)
    list (TRANSFORM list_test APPEND Q REGEX "[a-f]")
    message (">>> TRANSFORM-REGEX: ${list_test} --- ${list_test_out}")  
    
    # 输出
    >>> TRANSFORM-list: a;b;c;d;e;f;g;h;i;j;k
    >>> TRANSFORM-REGEX: aQ;bQ;cQ;dQ;eQ;fQ;g;h;i;j;k --- aQ;bQ;cQ;dQ;eQ;fQ;g;h;i;j;k
    
    4. 列表的排序

    4.1 REVERSE:子命令REVERSE用于将整个列表反转。

    list (REVERSE <list>)
      反转列表。

    # CMakeLists.txt
    cmake_minimum_required (VERSION 3.12.2)
    project (list_cmd_test)
    set (list_test aa bb cc dd) 
    message (">>> list: ${list_test}")
    list (REVERSE list_test)
    message (">>> REVERSE: ${list_test}")
    
    # 输出
    >>> list: aa;bb;cc;dd
    >>> REVERSE: dd;cc;bb;aa
    

    4.1 SORT:子命令SORT用于对列表进行排序。

    list (SORT <list> [COMPARE <compare>] [CASE <case>] [ORDER <order>])
      对列表进行排序。

    • COMPARE:指定排序方法。有如下几种值可选:1)STRING:按照字母顺序进行排序,为默认的排序方法;2)FILE_BASENAME:如果是一系列路径名,会使用basename进行排序;3)NATURAL:使用自然数顺序排序。
    • CASE:指明是否大小写敏感。有如下几种值可选:1)SENSITIVE:按照大小写敏感的方式进行排序,为默认值;2)INSENSITIVE:按照大小写不敏感方式进行排序。
    • ORDER:指明排序的顺序。有如下几种值可选:1)ASCENDING:按照升序排列,为默认值;2)DESCENDING:按照降序排列。
    # CMakeLists.txt
    cmake_minimum_required (VERSION 3.12.2)
    project (list_cmd_test)
    set (list_test 3 1 1.1 10.1 3.4 9)
    list (SORT list_test) # 以字母顺序,按照大小写敏感方式,升序排列
    message (">>> SORT STRING-SENSITIVE-ASCENDING: ${list_test}")
    list (SORT list_test COMPARE NATURAL ORDER DESCENDING) # 以自然顺序,降序排列
    message (">>> SORT STRING-SENSITIVE-DESCENDING: ${list_test}")
    
    # 输出
    >>> SORT STRING-SENSITIVE-ASCENDING: 1;1.1;10.1;3;3.4;9
    >>> SORT STRING-SENSITIVE-DESCENDING: 10.1;9;3.4;3;1.1;1
    


附录:参考资料

1.https://cmake.org/cmake/help/latest/command/list.html

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。