主要参考资料
https://cmake.org/cmake/help/v3.14/manual/cmake-language.7.html
这份资料将cmake的语言特性完全讲述,是了解其他所有模块的基础。
cmake的组织
cmake主要有两个类型的文件 CMakeLists.txt以及 *.cmake,按照逻辑分为三种:
- Directory (每个目录下面的CMakeLists.txt)
- Scripts
<Scripts>.cmake
- Modules
<Module>.cmake
最顶层的CMakeLists.txt是通过cmake .. 来进行调用的,子模块的CMakeList.txt则通过上层的add_subdirectory()来引用。不管后缀名是.txt还是.cmake,实际上就类似于一个shell脚本。
Script是另外一种,需要通过cmake -P <scripts>.script
来执行。script不会产生build system,不能定义target。
Modules可以由Directory或者Scripts进行调用,详细可以看 cmake-modules, modules通过include()来调用。
CMake的编写
CMake需要使用全英文编写,因为只有7位ASCII可以跨更多的平台使用。
variable
cmake的variable是cmake的基础存储单元,很多命令都是以variable的方式进行存储的。variable的类型只有string一种,即使是逻辑上的int,bool之类的数据类型,也只不过是解析时候转换成相应的类型而已。直接修改variable的命令只有set和unset两个,其余的命令均为间接的方式进行的。
变量的引用采用${<variable>}
的方式,并且支持嵌套,${outer_${inner_variable}_variable}
, 这样就
variable有相应的作用域,一共有三种作用域:
- Function Scope
在function()…endfunction()之间的代码,如果不指定PARENT_SCOPE, 那么所有的变量定义都只在该函数内有效(通过参数传进来的外部变量不受此限制), 也就是说在function scope内部定义的变量只能在function内部及其嵌套子函数内部有效。 - Directory Scope
每一个目录下的CMakeLists.txt都使用一个特定的scope,该scope会继承所有父级目录的变量,因此可以默认使用来自上一级目录的变量。 - Persistent Cache
Cache entries have an isolated binding scope modified only by explicit request, such as by the CACHE option of the set() and unset() commands. 要添加或者修改cache变量必须要显式指定,否则cache变量将一直独立存在。
cache优先级是最低的, 优先级排序是function > directory > cache。看官网的这一段描述。
When evaluating Variable References, CMake first searches the function call stack, if any, for a binding and then falls back to the binding in the current directory scope, if any. If a “set” binding is found, its value is used. If an “unset” binding is found, or no binding is found, CMake then searches for a cache entry. If a cache entry is found, its value is used. Otherwise, the variable reference evaluates to an empty string.
如果希望修改Parent Scope的变量,需要加上parent scope这个参数。否则,修改只会在当前scope生效。注意,cache变量时独立一个scope,无所谓parent
variable的set以及unset
normal variable
Set Normal Variable
set(
Set the given
If the PARENT_SCOPE option is given the variable will be set in the scope above the current scope. Each new directory or function creates a new scope. This command will set the value of a variable into the parent directory or calling function (whichever is applicable to the case at hand).
cache variable
set(<variable> <value>... CACHE <type> <docstring> [FORCE])
Since cache entries are meant to provide user-settable values this does not overwrite existing cache entries by default. Use the FORCE option to overwrite existing entries.
这个用来定义默认变量最好了,如果不开启force, 那么在存在这个变量时,将不会改变,这样子如果用户提供了参数,那么默认参数就不会生效。
cache变量还需要指定type,The
- BOOL
Boolean ON/OFF value. cmake-gui(1) offers a checkbox. - FILEPATH
Path to a file on disk. cmake-gui(1) offers a file dialog. - PATH
Path to a directory on disk. cmake-gui(1) offers a file dialog. - STRING
A line of text. cmake-gui(1) offers a text field or a drop-down selection if the STRINGS cache entry property is set. - INTERNAL
A line of text. cmake-gui(1) does not show internal entries. They may be used to store variables persistently across runs. Use of this type implies FORCE.
Set Environment Variable
set(ENV{<variable>} <value>...)
list
list实际上是一个有特殊格式的string, 但是通过分号隔开, 如果想要打一个分号,那必须通过转义字符。建立list有以下几种方式: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"
cmake的variable分为normal, cache, environment三种。
function
cmake的function定义规则如下:function(<name> [arg1 [arg2 [arg3 ...]]])
COMMAND1(ARGS ...)
COMMAND2(ARGS ...)
...
endfunction(<name>)