CMake中list的使用

Posted fengbingchun

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CMake中list的使用相关的知识,希望对你有一定的参考价值。

      CMake中的list命令用于列表操作,其格式如下:

Reading
  list(LENGTH <list> <out-var>)
  list(GET <list> <element index> [<index> ...] <out-var>)
  list(JOIN <list> <glue> <out-var>)
  list(SUBLIST <list> <begin> <length> <out-var>)

Search
  list(FIND <list> <value> <out-var>)

Modification
  list(APPEND <list> [<element>...])
  list(FILTER <list> INCLUDE | EXCLUDE REGEX <regex>)
  list(INSERT <list> <index> [<element>...])
  list(POP_BACK <list> [<out-var>...])
  list(POP_FRONT <list> [<out-var>...])
  list(PREPEND <list> [<element>...])
  list(REMOVE_ITEM <list> <value>...)
  list(REMOVE_AT <list> <index>...)
  list(REMOVE_DUPLICATES <list>)
  list(TRANSFORM <list> <ACTION> [...])

Ordering
  list(REVERSE <list>)
  list(SORT <list> [...])

      list子命令APPEND, INSERT, FILTER, PREPEND, POP_BACK, POP_FRONT, REMOVE_AT, REMOVE_ITEM, REMOVE_DUPLICATES, REVERSE和SORT可以在当前CMake变量范围内为list创建新值。与set命令类似,list命令在当前作用域中创建新的变量值,即使list本身实际上是在父作用域中定义的也是如此。要向上(upwards)传播这些操作的结果,需要使用带有PARENT_SCOPE的set命令、带有CACHE INTERNAL的set命令或其它一些值传播方式。
      cmake中的list是;分割的字符串组要创建list,可以使用set命令注意:macro参数不是变量,因此不能在list命令中使用

set(var a b c d e) # create a list
message("var: $var") # var: a;b;c;d;e

set(var "a b c d e") # creates a string or a list with one item in it
message("var: $var") # var: a b c d e

      指定索引值(index value)时,如果<element index>为0或更大,则从list的开头开始索引,0表示第一个list元素。如果<element index>为-1或更小,则从list末尾开始索引,-1表示最后一个list元素。使用负索引计数时要小心:它们不是从0开始的。-0相当于0,即第一个list元素。

      1.Reading:
      LENGTH:返回list的长度

set(values a b c d e)
list(LENGTH values var)
message("var: $var") # var: 5

      GET:返回list中由索引指定的元素列表

set(values a b c d e)

list(GET values 1 3 var)
message("var: $var") # var: b;d

list(GET values -1 -3 -5 var)
message("var: $var") # var: e;c;a

      JOIN:返回使用粘合字符串(glue string)连接所有list元素的字符串。要连接多个不属于list的字符串,需要使用string命令的JOIN操作符

set(values a b c d e)
list(JOIN values "-" var)
message("var: $var") # var: a-b-c-d-e

      SUBLIST:返回给定list的子list.如果<length>为0,将返回一个空list.如果<length>为-1或list小于<begin>+<length>则将返回list中从<begin>开始的剩余元素

set(values a b c d e f g h i j)

list(LENGTH values len)
list(SUBLIST values 2 $len var)
message("var: $var") # var: c;d;e;f;g;h;i;j

list(SUBLIST values 2 2 var)
message("var: $var") # var: c;d

list(SUBLIST values 1 0 var)
message("var: $var") # var: 

list(SUBLIST values 3 -1 var)
message("var: $var") # var: d;e;f;g;h;i;j

list(SUBLIST values 3 -2 var) # CMake Error at test_list.cmake:45 (list):
                                #   list length: -2 should be -1 or greater

      2.Search:返回list中指定元素的的索引,如果未找到则返回-1

set(values a b c d e f g h i j)

list(FIND values c var)
message("var: $var") # var: 2

list(FIND values w var)
message("var: $var") # var: -1

      3.Modification:
      APPEND:将元素附加到list中。如果当前范围内不存在名为<list>的变量,则其值被视为空,并且元素将附加到该空list中

set(values1 a b c d e)
set(values2 1 2 3 4 5)

list(APPEND var A B C)
message("var: $var") # var: A;B;C

list(APPEND var $values1 $values2)
message("var: $var") # var: A;B;C;a;b;c;d;e;1;2;3;4;5

      FILTER:从list中includes或removes与模式匹配的项(item)。在REGEX模式下,items将与给定的正则表达式匹配

set(values a 1 b 2 c 3 d 4 e 5)
list(FILTER values INCLUDE REGEX "[a-z]")
message("values: $values") # values: a;b;c;d;e

set(values a 1 b 2 c 3 d 4 e 5)
list(FILTER values EXCLUDE REGEX "[a-z]")
message("values: $values") # values: 1;2;3;4;5

      INSERT:将元素插入到指定索引的list中。指定超出范围的索引会触发error。有效索引我0到N,其中N是list的长度,含N。空list的长度为0.如果当前范围内不存在名为<list>的变量,则其值被视为空,并且元素将插入到该空list中

set(values a b c d e)

list(INSERT var 0 A B)
message("var: $var") # var: A;B

list(INSERT var 1 $values)
message("var: $var") # var: A;a;b;c;d;e;B

list(INSERT var -2 C)
message("var: $var") # var: A;a;b;c;d;C;e;B

list(INCLUDE var 10 D) # CMake Error at test_list.cmake:84 (list):
                        #   list does not recognize sub-command INCLUDE

      POP_BACK:如果没有给出变量名,则只删除最后一个元素。否则,在提供N个变量名的情况下,将最后N个元素的值分配给给定变量,然后从<list>中删除最后N个值

set(values a b c d e)
list(POP_BACK values)
message("values: $values") # values: a;b;c;d

set(values a b c d e)
list(POP_BACK values var1 var2 var3)
message("values: $values; var1: $var1; var2: $var2; var3: $var3") # values: a;b; var1: e; var2: d; var3: c

      POP_FRONT:如果没有给出变量名,则只删除最前一个元素。否则,在提供N个变量名的情况下,将最前N个元素的值分配给给定变量,然后从<list>中删除最前N个值

set(values a b c d e)
list(POP_FRONT values)
message("values: $values") # values: b;c;d;e

set(values a b c d e)
list(POP_FRONT values var1 var2 var3)
message("values: $values; var1: $var1; var2: $var2; var3: $var3") # values: d;e; var1: a; var2: b; var3: c

      PREPEND:将元素插入到list中的第0位。如果当前作用域中不存在名为<list>的变量,则其值被视为空,并且元素将附加到该空list中

list(PREPEND var a b c d)
message("var: $var") # var: a;b;c;d

set(values a b c d e)
list(PREPEND values 1 2 3)
message("values: $values") # values: 1;2;3;a;b;c;d;e

      REMOVE_ITEM:从list中删除给定items的所有实例(removes all instances of the given items)

set(values a 1 b 2 c 3 d 4 e 5)
list(REMOVE_ITEM values 1 2 3 4 5)
message("values: $values") # values: a;b;c;d;e

      REMOVE_AT:从list中删除给定index的item

set(values a 1 b 2 c 3 d 4 e 5)
list(REMOVE_AT values 0 2 4 6 8)
message("values: $values") # values: 1;2;3;4;5

      REMOVE_DUPLICATES:删除list中的重复项。items的相对顺序被保留,但如果遇到重复项,则仅保留第一个实例

set(values a 1 b 2 a 1 b 2 c 3)
list(REMOVE_DUPLICATES values)
message("values: $values") # values: a;1;b;2;c;3

      TRANSFORM:通过将<ACTION>应用于所有或通过<SELECTOR>指定的元素来转换list,将结果存储在原list或指定的<output variable>中。TRANSFORM子命令不会更改list中元素的数量。如果指定了<SELECTOR>,则只会更改一些元素,其它元素将保持与转换前相同。<ACTION>指定应用于list元素的操作。这些操作与string命令的子命令具有完全相同的语义。<ACTION>必须是以下之一:

list(TRANSFORM <list> <ACTION> [<SELECTOR>] [OUTPUT_VARIABLE <output variable>])
list(TRANSFORM <list> <APPEND|PREPEND> <value> ...) # 将指定的value追加或前置到list的每个元素
list(TRANSFORM <list> <TOLOWER|TOUPPER> ...) # 将list的每个元素转换为大写或小写字符
list(TRANSFORM <list> STRIP ...) # 移除list中的前后空格
list(TRANSFORM <list> GENEX_STRIP ...) # 从list的每个元素中删除any generator expressions
list(TRANSFORM <list> REPLACE <regular_expression> <replace_expression> ...) # 匹配正则表达式,替换list中每个元素的匹配项
set(values a b c d e)
list(TRANSFORM values APPEND 1)
message("values: $values") # values: a1;b1;c1;d1;e1
list(TRANSFORM values PREPEND 2)
message("values: $values") # values: 2a1;2b1;2c1;2d1;2e1

set(values a b c d e)
list(TRANSFORM values APPEND 1 OUTPUT_VARIABLE var)
message("values: $values; var: $var") # values: a;b;c;d;e; var: a1;b1;c1;d1;e1

set(values a b c d e)
list(TRANSFORM values TOUPPER)
message("values: $values") # values: A;B;C;D;E
list(TRANSFORM values TOLOWER)
message("values: $values") # values: a;b;c;d;e

set(values a b c d e)
list(APPEND values " f j " " p  q ")
message("values: $values") # values: a;b;c;d;e; f j ; p  q 
list(TRANSFORM values STRIP)
message("values: $values") # values: a;b;c;d;e;f j;p  q

set(value one;$<1:two;three>;four;$<TARGET_OBJECTS:some_target>)
list(TRANSFORM value GENEX_STRIP)
message("value: $value") # value: one;$<1:two;three>;four;

set(values a 1 b 2 c 3 d 4 e 5)
list(TRANSFORM values REPLACE "[a-z]" "T")
message("values: $values") # values: T;1;T;2;T;3;T;4;T;5

set(values a b c d e)
list(TRANSFORM values APPEND 1 AT 0 3)
message("values: $values") # values: a1;b;c;d1;e

set(values a b c d e 1 2 3 4 5)
list(TRANSFORM values APPEND "#" FOR 2 8 2)
message("values: $values") # values: a;b;c#;d;e#;1;2#;3;4#;5

set(values a b c d e 1 2 3 4 5)
list(TRANSFORM values APPEND "#" REGEX [a-c])
message("values: $values") # values: a#;b#;c#;d;e;1;2;3;4;5

      <SELECTOR>确定转换list中的哪些元素。一次只能指定一种类型的selector,若给定,<SELECTOR>必须是以下之一:

list(TRANSFORM <list> <ACTION> AT <index> [<index> ...] ...) # 指定list索引
list(TRANSFORM <list> <ACTION> FOR <start> <stop> [<step>] ...) # 指定一个范围,<step>可选项,迭代增量
list(TRANSFORM <list> <ACTION> REGEX <regular_expression> ...) # 正则表达式,只有匹配正则表达式的元素才会被转换

      4.Ordering:
      REVERSE:就地(in-place)反转list的内容

set(values a b c d e)
list(REVERSE values)
message("values: $values") # values: e;d;c;b;a

      SORT:就地(in-place)按字母顺序对list进行排序

list(SORT <list> [COMPARE <compare>] [CASE <case>] [ORDER <order>])

      使用COMPARE关键字选择排序的比较方法,<compare>选项应该是其中之一:
      (1).STRING:按字母顺序对字符串list进行排序。如果没有给出COMPARE选项,这是默认行为
      (2).FILE_BASENAME:按文件的basenames对文件的路径名list进行排序
      (3).NATURAL:使用自然顺序(natural order)对字符串list进行排序
      使用CASE关键字选择区分大小写或不区分大小写的排序模式。<case>选项应该是其中之一:
      (1).SENSITIVE:list items以区分大小写(case-sensitive)的方式排序。如果没有给出CASE选项,这是默认行为
      (2).INSENSITIVE:list items不区分大小写
      要控制排序顺序,可以给出ORDER关键字。<order>选项应该是其中之一:
      (1).ASCENDING:按升序对list进行排序。这是未给出ORDER选项时的默认行为
      (2).DESCENDING:按降序对list进行排序

set(values c 4 a I f 9 -1 B b)
list(SORT values COMPARE STRING)
message("values: $values") # values: -1;4;9;B;I;a;b;c;f

set(values 10.0 1.1 2.1 8.0 2.0 3.1)
list(SORT values)
message("values: $values") # values: 1.1;10.0;2.0;2.1;3.1;8.0

set(values 10.0 1.1 2.1 8.0 2.0 3.1)
list(SORT values COMPARE NATURAL)
message("values: $values") # values: 1.1;2.0;2.1;3.1;8.0;10.0

set(values A c B e i H)
list(SORT values CASE SENSITIVE)
message("values: $values") # values: A;B;H;c;e;i

set(values A c B e i H)
list(SORT values CASE INSENSITIVE)
message("values: $values") # values: A;B;c;e;H;i

set(values A c B e i H)
list(SORT values ORDER ASCENDING)
message("values: $values") # values: A;B;H;c;e;i

set(values A c B e i H)
list(SORT values ORDER DESCENDING)
message("values: $values") # values: i;e;c;H;B;A

      执行上述测试代码需要3个文件:build.sh, CMakeLists.txt, test_list.cmake

     build.sh内容如下:

#! /bin/bash

# supported input parameters(cmake commands)
params=(function macro cmake_parse_arguments \\
		find_library find_path find_file find_program find_package \\
		cmake_policy cmake_minimum_required project include \\
		string list set)

usage()

	echo "Error: $0 needs to have an input parameter"

	echo "supported input parameters:"
	for param in $params[@]; do
		echo "  $0 $param"
	done

	exit -1


if [ $# != 1 ]; then
	usage
fi

flag=0
for param in $params[@]; do
	if [ $1 == $param ]; then
		flag=1
		break
	fi
done

if [ $flag == 0 ]; then
	echo "Error: parameter \\"$1\\" is not supported"
	usage
	exit -1
fi

if [[ ! -d "build" ]]; then
	mkdir build
	cd build
else
	cd build
fi

echo "==== test $1 ===="
cmake -DTEST_CMAKE_FEATURE=$1 ..

      CMakeLists.txt内容如下:

cmake_minimum_required(VERSION 3.22)
project(cmake_feature_usage)

message("#### current cmake version: $CMAKE_MAJOR_VERSION.$CMAKE_MINOR_VERSION.$CMAKE_PATCH_VERSION")
include(test_$TEST_CMAKE_FEATURE.cmake)
message("==== test finish ====")

      test_list.cmake:为上面的所有示例代码

      可能的执行结果如下图所示:

      GitHub: https://github.com/fengbingchun/Linux_Code_Test

以上是关于CMake中list的使用的主要内容,如果未能解决你的问题,请参考以下文章

常见的三种排序

C# 集合及集合内排序 问题 速求

CMake:从函数内定义范围中的访问变量

CMake:从“make install [all]”中排除自定义安装目标

如何使用 LINQ 从列表中选择提供的索引范围内的值

具有覆盖范围的 CMake ninja 将 gcno 文件放在根二进制目录中