编译原理与语法(五)——CMake语法详解

  • 在Android Studio 2.2及以上,构建原生库的默认工具是CMake
  • CMake是一个跨平台的支持产出各种不同的构建脚本的一个工具
  • CMake并不直接构建出最终的软件,而是产生其他工具的脚本(如makefile)

注释

单行注释:
# 注释内容

多行注释:
# [[注释内容
注释内容
注释内容]]

变量

声明变量:set(变量名 变量值)
移除变量:unset(变量名)
引用变量: ${变量名}

set(var 123)
message(WARNING "var = ${var}")

结果:var = 123

message

message([] "message to display" ...)

  • (none) = 重要消息
  • STATUS = 附带消息
  • WARNING = CMake警告,继续处理
  • AUTHOR_WARNING = CMake警告(dev),继续处理
  • SEND_ERROR = CMake错误,继续处理,但跳过生成
  • FATAL_ERROR = CMake错误,停止处理和生成
  • DEPRECATION = 如果分别启用了变量CMAKE_ERROR_DEPRECATED或CMAKE_WARN_DEPRECATED,则CMake弃用错误或警告,否则无消息

在高版本的CMake中,(none) 和 STATUS 两种级别的 message 不会直接打印出来,要使用其他级别

指定abi

abiFilters "armeabi", "armeabi-v7a" , "arm64-v8a", "x86", "x86_64", "mips", "mips64"

defaultConfig {
        applicationId "com.example.myapplication"
        minSdkVersion 25
        targetSdkVersion 29
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
        externalNativeBuild {
            cmake {
                cppFlags ""
                abiFilters "armeabi-v7a"
            }
        }
    }

列表

声明列表:set(列表名 值1 值2 ...值N)
声明列表:set(列表名 "值1;值2;...值N")
引用列表:${列表名}

set(list1 111 222 333)
message(WARNING "list1 = ${list1}")
set(list2 "aaa;bbb;ccc")
message(WARNING "list2 = ${list2}")

结果:
list1 = 111;222;333
list2 = aaa;bbb;ccc

流程控制

操作符
类型 名称
一元 EXIST,COMMAND,DEFINED
二元 EQUAL,LESS,LESS_EQUAL,GREATER,GREATER_EQUAL,STREQUAL,STRLESS,STRLESS_EQUAL,STRGREATER,STRGREATER_EQUAL,VERSION_EQUAL,VERSION_LESS,VERSION_LESS_EQUAL,VERSION_GREATER,VERSION_GREATER_EQUAL,MATCHES
逻辑 NOT,AND,OR
布尔常量值
类型
true 1,ON,YES,TRUE,Y,非0值
false 0,OFF,NO,FALSE,N,IGNORE,NOTFOUND,空字符串,以-NOTFOUND结尾的字符串
条件命令
  • 语法格式:
    if(表达式)
    COMMAND(ARGS...)
    endif(表达式)
    COMMAND(ARGS...)
    endif(表达式)
    COMMAND(ARGS...)
    end(表达式)
    COMMAND(ARGS...)
    endif(表达式)
    缩进和空格对语句没有影响
set(controloff OFF)
set(controlon ON)

if(${controloff})
    message(WARNING "if")
elseif(${controloff})
    message(WARNING "elseif1")
elseif(${controloff})
    message(WARNING "elseif2")
else(${controloff})
    message(WARNING "else")
endif(${controloff})

结果:else

循环命令
  • 语法格式:
    while(表达式)
    COMMAND(ARGS...)
    endwhile(表达式)
  • break()命令可以跳出整个循环,continue()可以跳出当前循环
set(a "")

while(NOT a STREQUAL "xxx")
  set(a "${a}x")
  message("a = ${a}")
endwhile()

结果:
a = x
a = xx
a = xxx
b = y
b = yyy
b = yyyy

循环遍历一

语法格式
foreach(循环变量 参数1 参数2 ... 参数N)
COMMAND(ARGS...)
endforeach(循环变量)

foreach(item 1 2 3)
  message(WARNING "item = ${item}")
endforeach(item)

结果:
item = 1
item = 2
item = 3

循环遍历二
  • 语法格式
    foreach(循环变量 RANGE total)
    COMMAND(ARGS...)
    endforeach(循环变量)
  • 循环范围从0到total
foreach(item RANGE 3)
  message(WARNING "item = ${item}")
endforeach(item)

结果:
item = 0
item = 1
item = 2
item = 3

循环遍历三
  • 语法格式
    foreach(循环变量 RANGE start stop step)
    COMMAND(ARGS...)
    endforeach(循环变量)
  • 循环范围从start到stop,循环增量为step
foreach(item RANGE 1 8 2)
  message(WARNING "item = ${item}")
endforeach(item)

结果:
item = 1

item = 3
item = 5
item = 7

循环遍历四

语法格式
foreach(循环变量 IN LISTS 列表)
COMMAND(ARGS...)
endforeach(循环变量)

set(list_foreach 1 3 ass qw3dd)
foreach(item IN LISTS list_foreach)
    message(WARNING "item = ${item}")
endforeach(item)

结果:
item = 1
item = 3
item = ass
item = qw3dd

自定义函数

命令格式:
function(name arg1 arg2 arg3 ...)
COMMAND()
endfunction(name)

function(func a b c)
  message(WARNING "a= ${a}")
  message(WARNING "b= ${b}")
  message(WARNING "c= ${c}")
  message(WARNING "ARGC= ${ARGC}")
  message(WARNING "ARGV0= ${ARGV0}")
  message(WARNING "ARGV1= ${ARGV1}")
  message(WARNING "ARGV2= ${ARGV2}")
  message(WARNING "ARGV3= ${ARGV3}")
  message(WARNING "ARGV= ${ARGV}")
endfunction(func)

func(1 www 222)

结果:
a= 1
b= www
c= 222
ARGC= 3
ARGV0= 1
ARGV1= www
ARGV2= 222
ARGV3=
ARGV= 1;www;222

变量 含义
ARGC 函数有多少个参数
ARGV+N N代表第几个参数 ARGV0第一个参数,ARGV2第二个参数,依次类推
ARGV 打印所有的参数

自定义宏命令

命令格式:
macro(name arg1 arg2 arg3 ...)
COMMAND()
endmacro(name)

macro(ma x y z)
  message(WARNING "x= ${x}")
  message(WARNING "y= ${y}")
  message(WARNING "z= ${z}")
  message(WARNING "ARGC= ${ARGC}")
  message(WARNING "ARGV0= ${ARGV0}")
  message(WARNING "ARGV1= ${ARGV1}")
  message(WARNING "ARGV2= ${ARGV2}")
  message(WARNING "ARGV3= ${ARGV3}")
  message(WARNING "ARGV= ${ARGV}")
endmacro(ma)

ma(1 2 3)

结果:
x= 1
y= 2
z= 3
ARGC= 3
ARGV0= 1
ARGV1= 2
ARGV2= 3
ARGV3=
ARGV= 1;2;3

与函数的区别

函数有自己的作用域,宏的作用域与调用者是一样的

set(funcdifmacro 100)

function(funcdif)
    set(funcdifmacro 200)
    message(WARNING "in funcdif value = ${funcdifmacro}")
endfunction(funcdif)
funcdif()
message(WARNING "out funcdif value = ${funcdifmacro}")

macro(madif)
    set(funcdifmacro 200)
    message(WARNING "in madif value = ${funcdifmacro}")
endmacro(madif)
madif()
message(WARNING "out madif value = ${funcdifmacro}")

结果:
in funcdif value = 200
out funcdif value = 100
in madif value = 200
out madif value = 200
可以看到,function里面改变的funcdifmacro 值在外部并没有生效,function使用外部变量时,会拷贝一份外部变量来操作,所以并不会改变外部变量

变量的作用域
  • 全局层:cache变量,在整个项目范围可见,一般在set定义变量时,指定CACHE参数就能定义为cache变量
  • 目录层:在当前目录CMakeLists.txt中定义,以及在该文件包含的其他cmake源文件中定义的变量
  • 函数层:在命令函数中定义的变量,属于函数作用域内的变量

你可能感兴趣的:(编译原理与语法(五)——CMake语法详解)