什么是CMake
- 在Android2.2及以上版本,构建原生库的默认工具是CMake。
- CMake是一个跨平台的构建工具,可以用简单的语句来描述所有平台的安装(编译过程)。能够输出各种各样的makefile或者project文件。CMake并不是直接构建出最终软件,而是产生其他工具的脚本(如Makefile),然后在依据这个工具的构建方式使用。
- CMake是一个比make更高级的编译配置工具,它可以根据不同的平台、不同的编译器,生成响应的makefile或者vcproj项目,从而达到跨平台的目的。Android Studio利用CMake生成的是ninja。ninja是一个小型的关注速度的构建系统。我们不需要关心ninja的脚本,知道怎么配置CMake就可以了。
- CMake其实是一个跨平台的支持产出各种不同的构建脚本的一个工具。
CMake源文件
- CMake的源文件可以包含命令、注释、空格和换行。
- 以CMake编写的源文件以CMakeLists.txt命名或以.cmake为扩展名。
- 可以通过add_subdirectory()命令把子目录的CMake源文件添加进来。
- CMake源文件中所有有效的语句都是命令,可以是内置命令或自定义的函数/宏命令。
注释
- 单行注释:#注释内容(注释从#开始到行尾结束)
- 多行注释:#[[多行注释]]
变量
- CMake中所有的变量都是string类型。可以使用set()和unset()命令来声明或移除一个变量
- 变量的引用:${变量名}
# 声明变量
set(var 123)
# 引用变量
message("var = ${var}")
列表(lists)
- 列表也是字符串,可以把列表看做一个特殊的变量,这个变量有多个值。
- 语法格式
set(列表名 值1 值2...值N)
或
set(列表名 "值1;值2;...;值N")
- 列表的引用:${列表名}
set(list_var "1;2;3;4;5")
message("list_var = ${list_var}")
流程控制
-
操作符
操作符
运算符优先级:小括号 > 一元 > 二元 > 逻辑
-
布尔常量值
布尔常量值 -
条件命令
# 语法格式:
if(表达式)
COMMAND(ARGS...)
elseif(表达式)
COMMAND(ARGS...)
else(表达式)
COMMAND(ARGS...)
endif(表达式)
# elseif和else部分是可选的,也可以有多个elseif部分,缩进和空格对语句解析没有影响。
# 例子
set(if_tap OFF)
set(elseif_tap ON)
if(${if_tap})
message("if")
elseif(${elseif_tap})
message("elseif")
else(${if_tap})
message("else")
endif(${if_tap})
- 循环命令
# 语法格式:
while(表达式)
COMMAND(ARGS...)
endwhile(表达式)
# break()命令可以跳出整个循环
# continue()命令可以跳出当前循环
- 循环遍历
# 语法格式1:
foreach(循环变量 参数1 参数2...参数N)
COMMAND(ARGS...)
endforeach(循环变量)
# 语法格式2:
# 循环范围从0到total。
foreach(循环变量 RANGE total)
COMMAND(ARGS...)
endforeach(循环变量)
# 语法格式3:
# 循环范围从start到stop,循环增量为step。
foreach(循环变量 RANGE start stop step)
COMMAND(ARGS...)
endforeach(循环变量)
# 语法格式4:对列表的循环
foreach(循环变量 IN LISTS 列表)
COMMAND(ARGS...)
endforeach(循环变量)
自定义函数命令
# 格式
function(<name> [arg1[arg2[arg3...]]])
COMMAND()
endfunction(<name>)
# 函数命令调用
name(实参列表)
# 例子
function(func a b c)
message("a = ${a}")
message("a = ${b}")
message("a = ${c}")
# ARGC 内置变量表示传入参数的个数
# 输出:ARGC = 3
message("ARGC = ${ARGC}")
# ARGV 输入的参数列表
# 输出 ARGV = 1;2;3
message("ARGV = ${ARGV}")
# ARGV0 代表输入的第一个参数值
message("ARGV0 = ${ARGV0}")
message("ARGV1 = ${ARGV1}")
message("ARGV2 = ${ARGV2}")
endfunction(func)
func(1 2 3)
自定义宏命令
函数有自己的作用域 而宏命令的作用域与调用者的作用域相同
# 自定义宏命令格式:
macro(<name> [arg1[arg2[arg3...]]])
COMMAND()
endmacro(<name>)
# 宏命令调用
name(实参列表)
变量的作用域
- 全局层:cache变量,在整个项目范围内可见,一般在set定义变量时,指定CACHE参数就能定义为cache变量。
- 目录层:在当前目录CMakeLists.txt中,以及在该文件包含的其他cmake源文件中定义的变量。
- 函数层:在命令函数中定义的变量,属于函数作用域内的变量。
作用域优先级:函数层 <覆盖>> 目录层 <覆盖>> 全局层
在当前层修改上一层的作用域不会传递到上一层的作用域中:因为当前作用域只是复制上一层作用域的全部变量到自己的作用域在进行修改
如果在修改时通过set命令明确指定PARENT_SCOPE参数,修改的变量作用域就是上一层的作用域
网友评论