CMake基础

主要参考资料

https://cmake.org/cmake/help/v3.14/manual/cmake-language.7.html
这份资料将cmake的语言特性完全讲述,是了解其他所有模块的基础。

cmake的组织

cmake主要有两个类型的文件 CMakeLists.txt以及 *.cmake,按照逻辑分为三种:

  1. Directory (每个目录下面的CMakeLists.txt)
  2. Scripts<Scripts>.cmake
  3. 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有相应的作用域,一共有三种作用域:

  1. Function Scope
    在function()…endfunction()之间的代码,如果不指定PARENT_SCOPE, 那么所有的变量定义都只在该函数内有效(通过参数传进来的外部变量不受此限制), 也就是说在function scope内部定义的变量只能在function内部及其嵌套子函数内部有效。
  2. Directory Scope
    每一个目录下的CMakeLists.txt都使用一个特定的scope,该scope会继承所有父级目录的变量,因此可以默认使用来自上一级目录的变量。
  3. 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( … [PARENT_SCOPE])
Set the given in the current function or directory scope.

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 must be specified as one of:

  1. BOOL
    Boolean ON/OFF value. cmake-gui(1) offers a checkbox.
  2. FILEPATH
    Path to a file on disk. cmake-gui(1) offers a file dialog.
  3. PATH
    Path to a directory on disk. cmake-gui(1) offers a file dialog.
  4. 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.
  5. 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>)

0%