cmake:cmake-language 灰太狼 2022-10-11 12:19 214阅读 0赞 # 组织 # CMake输入文件以CMake语言写在名为CMakeLists.txt的源文件中,或者以`.CMake`扩展名结尾的文件中 项目中的CMake语言源文件被组织为: * Directories (CMakeLists.txt) * Scripts (< script>.cmake) * Modules (< module>.cmake). ## Directories ## * 当CMake处理一个项目源树时,入口点是顶级源目录中的一个名为CMakeLists.txt的源文件。 * 这个文件可能包含整个构建规范,或者使用add\_subdirectory()命令向构建添加子目录。 * 该命令添加的每个子目录还必须包含一个CMakeLists.txt文件作为该目录的入口点。 * 对于处理CMakeLists.txt文件的每个源目录,CMake在构建树中生成一个响应的目录,作为默认的工作和输出目录。 ## Scripts ## * 单个< script>.cmake源文件可以通过使用带有-P选项的cmake(1)命令行工具在脚本模式下进行处理。 * 脚本模式只是在给定的CMake语言源文件中运行命令,并不生成生成系统。它不允许使用CMake命令来定义构建目标或操作。 ## Modules ## * 【Directories 】或【Scripts】中的CMake语言代码可以使用include()命令在include上下文的范围内加载< module>.CMake源文件。请参阅cmake模块(7)手册页,了解cmake发行版中包含的模块文档。 * 项目源树还可以提供自己的模块,并在 CMAKE\_MODULE\_PATH 变量中指定它们的位置。 # 语法 # ## 编码 ## * CMake Language源文件可以用7位ASCII文本编写,以便在所有支持的平台上实现最大的可移植性。换行可以被编码为\\n或\\r\\n,但当读取输入文件时将被转换为\\n。 * 注意,这个实现是8位的,所以在支持这种编码的系统api平台上,源文件可以被编码为UTF-8。 ## 源文件 ## CMake语言源文件由零个或多个由换行符分隔的【命令调用】以及可选的空格和【注释】组成: file ::= file_element* file_element ::= command_invocation line_ending | (bracket_comment|space)* line_ending line_ending ::= line_comment? newline space ::= <match '[ \t]+'> newline ::= <match '\n'> 请注意,任何不在【命令参数】或括号注释内的源文件行都可以以行注释结束。 ## 命令调用 ## 命令调用是一个名称,后跟由空格分隔的paren封闭参数: command_invocation ::= space* identifier space* '(' arguments ')' identifier ::= <match '[A-Za-z_][A-Za-z0-9_]*'> arguments ::= argument? separated_arguments* separated_arguments ::= separation+ argument? | separation* '(' arguments ')' separation ::= space | line_ending 例如: add_executable(hello world.c) * 命令名称不区分大小写。 * 参数中嵌套的不带引号的圆括号必须保持平衡。 * 每个(或)都作为一个【无引号的实参】赋给命令调用。 这可以用于调用if()命令来封装条件。例如: if(FALSE AND (FALSE OR TRUE)) # evaluates to FALSE ## 命令参数 ## 在【命令调用】中有三种类型的参数: argument ::= bracket_argument | quoted_argument | unquoted_argument ### bracket\_argument(括号参数) ### 一个括号参数,受Lua长括号语法的启发,将内容括在相同长度的开始和结束“括号”之间: bracket_argument ::= bracket_open bracket_content bracket_close bracket_open ::= '[' '='* '[' bracket_content ::= <any text not containing a bracket_close with the same number of '=' as the bracket_open> bracket_close ::= ']' '='* ']' * 左括号被写成\[后跟0或多个=后跟\[。相应的右括号写为\],后面跟着相同数目的=,后面跟着\] * 括号参数内容包括在开始和结束括号之间的所有文本,除非紧跟在开始括号之后的换行符(如果有的话)被忽略。不会对包含的内容(如转义序列或变量引用)执行计算。方括号参数总是作为一个参数给命令调用。 例子: message([=[ This is the first line in a bracket argument with bracket length 1. No \-escape sequences or ${ variable} references are evaluated. This is always one argument even though it contains a ; character. The text does not end on a closing bracket of length 0 like ]]. It does end in a closing bracket of length 1. ]=]) ### Quoted Argument(引号参数) ### 用双引号括起来的参数将内容括在双引号的开始和结束字符之间: quoted_argument ::= '"' quoted_element* '"' quoted_element ::= <any character except '\' or '"'> | escape_sequence | quoted_continuation quoted_continuation ::= '\' newline 引用的参数内容包括在开始和结束引号之间的所有文本。转义序列和变量引用都会被计算。带引号的参数总是作为一个参数提供给命令调用。 例如: message("This is a quoted argument containing multiple lines. This is always one argument even though it contains a ; character. Both \\-escape sequences and ${ variable} references are evaluated. The text does not end on an escaped double-quote like \". It does end in an unescaped double quote. ") 任何以奇数个反斜杠结尾的行的最后一个\\将被视为行延续符,并与紧随其后的换行符一起被忽略。例如: message("\ This is the first line of a quoted argument. \ In fact it is the only line but since it is long \ the source code uses line continuation.\ ") 注意:3.0之前的CMake版本不支持使用\\继续。如果引用的参数包含以奇数个\\字符结尾的行,则报告错误。 ### 无引号的参数 ### 非引号参数不包含在任何引号语法中。它不能包含任何空格,(,),\#,"或\\,除非用反斜杠转义: unquoted_argument ::= unquoted_element+ | unquoted_legacy unquoted_element ::= <any character except whitespace or one of '()#"\'> | escape_sequence unquoted_legacy ::= <see note in text> 不带引号的参数内容由允许或转义字符的连续块中的所有文本组成。转义序列和变量引用都会被计算。结果值的划分方式与list划分元素的方式相同。每个非空元素都作为参数提供给命令调用。因此,一个未带引号的参数可以作为零个或多个参数提供给命令调用。 例如: foreach(arg NoSpace Escaped\ Space This;Divides;Into;Five;Arguments Escaped\;Semicolon ) message("${arg}") endforeach() 我们不建议在新代码中使用遗留的不带引号的参数。相反,使用引号参数或括号参数来表示内容。 ## 转义序列 ## 转义序列是一个\\后跟一个字符: escape_sequence ::= escape_identity | escape_encoded | escape_semicolon escape_identity ::= '\' <match '[^A-Za-z0-9;]'> escape_encoded ::= '\t' | '\r' | '\n' escape_semicolon ::= '\;' 后跟非字母数字字符的\\只对文字字符进行编码,而不将其解释为语法。一个\\t、\\r或\\n分别编码制表符、回车符或换行符。一个;外部的任何变量引用本身编码,但可以在无引号参数中使用;而不需要在上面划分参数值。一个;inside变量引用编码文字;的性格 ## 变量引用 ## 变量引用的形式为`${<variable>}`,并且在带引号参数或不带引号参数中计算。变量引用被替换为该变量的值,如果没有设置该变量,则替换为空字符串。变量引用可以嵌套并由内到外计算,例如`${outer_${inner_variable}_variable}`。 字面值变量引用可以包含字母数字字符,字符`·/_.+-`和转义序列。嵌套引用可用于计算任何名称的变量。也请参阅政策CMP0053文档,了解历史考虑和为什么$在技术上也是允许的,但不鼓励的原因。 【Variables】部分记录变量名的范围以及如何设置它们的值。 环境变量引用的格式为`$ENV{<variable>}`。有关详细信息,请参见环境变量部分。 缓存变量引用的格式为`$cache{<variable>}`。有关详细信息,请参见缓存。 `if()`命令有一个特殊的条件语法,允许使用缩写形式`<variable>`而不是`${<variable>}`的变量引用。但是,环境和缓存变量总是需要被引用为`$ENV{<variable>}`或`$cache{<variable>}`。 ## 注释 ## 注释以\#字符开头,该字符不在方括号参数、带引号的参数中,也不作为不带引号的参数的一部分用\\转义。有两种类型的注释:括号注释和行注释。 ### 括号注释 ### 紧跟在bracket\_open后面的\#构成了一个由整个括号括起来的括号注释: bracket_comment ::= '#' bracket_argument 例子: #[[这是一个括号注释。 它一直运行到右括号。]] message("First Argument\n" #[[Bracket Comment]] "Second Argument") 注意3.0之前的CMake版本不支持括号注释。它们将开头\#解释为行注释的开始。 ### 行注释 ### 没有紧跟bracket\_open的\#会形成行注释,一直运行到行尾: line_comment ::= '#' <任何不以括号开头的文本 不包含换行符> 例子: # This is a line comment. message("First Argument\n" # This is a line comment :) "Second Argument") # This is a line comment. # 流程控制 # ## 条件块 ## if()/elseif()/else()/endif()命令将有条件执行的代码块分隔开。 ## 循环 ## foreach()/endforeach()和while()/endwhile()命令分隔要在循环中执行的代码块。在这样的块中,break()命令可以用来提前终止循环,而continue()命令可以用来立即开始下一个迭代。 ## 命令定义 ## macro()/endmacro()和function()/endfunction()命令将代码块分隔,以便稍后作为命令调用。 # 变量 # 变量是CMake语言中最基本的存储单元。它们的值总是字符串类型,尽管有些命令可能将字符串解释为其他类型的值。set()和unset()命令显式地设置或取消设置变量,但其他命令也有修改变量的语义。变量名区分大小写,可以包含几乎任何文本,但我们建议只包含字母数字字符加上\_和-的名称。 变量具有动态作用域。每个变量“set”或“unset”在当前作用域内创建一个绑定: * 函数作用域: * 由function()命令创建的【命令定义】创建命令,在调用时,这些命令将在新的变量绑定作用域内处理记录的命令 * 变量“set”或“unset”绑定在此作用域内,对当前函数和其中的任何嵌套调用可见,但在函数返回后不可见。 * 目录作用域 * 源树中的每个目录都有自己的变量绑定。 * 在处理目录的CMakeLists.txt文件之前,CMake复制当前在父目录中定义的所有变量绑定(如果有),以初始化新的目录作用域 * 使用CMake-P处理CMake脚本时,将变量绑定到一个“目录”作用域中。 * 不在函数调用内的变量“set”或“unset”绑定到当前目录作用域。 * 持久缓存 * CMake存储一组单独的“cache”变量或“cache entries”,它们的值在项目生成树中的多个运行中保持不变。 * 缓存项有一个仅由显式请求修改的独立绑定范围,如set()和unset()命令的Cache选项。 当计算变量引用时,CMake首先在函数调用堆栈(如果有的话)中搜索绑定,然后返回到当前目录作用域(如果有的话)中的绑定。 * 如果找到一个“set”绑定,则使用它的值。 * 如果找到一个“unset”绑定,或者没有找到绑定,CMake就会搜索一个缓存条目。 * 如果找到一个缓存条目,就使用它的值。 * 否则,变量引用将计算为空字符串。 $CACHE\{VAR\}语法可以用来进行直接的缓存条目查找。 CMake -variables(7)手册文档记录了cmake提供的许多变量,或者在项目代码设置时对cmake有意义的变量。 # 环境变量 # 环境变量和普通变量一样,有以下区别: * 作用域:环境变量在CMake过程中具有全局作用域。它们从不被缓存。 * 引用:变量引用的形式为`$ENV{< Variable >}`。 * 初始化 * CMake环境变量的初始值是调用进程的初始值。 * 可以使用set()和unset()命令更改值。 * 这些命令只影响正在运行的CMake进程,对整个系统环境没有影响。 * 更改后的值不会写回调用流程,后续的构建或测试流程也不会看到它们。 CMake -env-variables(7)手册记录了对cmake有特殊意义的环境变量。 # 列表 # 尽管CMake中的所有值都存储为字符串,但在某些上下文中,例如在计算一个未带引用的参数时,字符串可以被视为一个列表。在这样的上下文中,一个字符串被拆分为列表元素;不跟在数量不相等的\[and\]字符后面且前面不直接跟一个\\的字符。 元素列表通过连接以;分隔的元素来表示为字符串。例如,set()命令将多个值以列表的形式存储到目标变量中: set(srcs a.c b.c c.c) # sets "srcs" to "a.c;b.c;c.c" 列表用于简单的用例,例如源文件列表,不应用于复杂的数据处理任务。大多数构造列表的命令不会转义;列表元素中的字符,从而展平嵌套列表: set(x a "b;c") # sets "x" to "a;b;c", not "a;b\;c" ### 文章目录 ### * 组织 * * Directories * Scripts * Modules * 语法 * * 编码 * 源文件 * 命令调用 * 命令参数 * * bracket\_argument(括号参数) * Quoted Argument(引号参数) * 无引号的参数 * 转义序列 * 变量引用 * 注释 * * 括号注释 * 行注释 * 流程控制 * * 条件块 * 循环 * 命令定义 * 变量 * 环境变量 * 列表
还没有评论,来说两句吧...