CMake入门

CMake是一个跨平台的构建工具,可以用简单的语句来描述所有平台的安装(编译)过程,能够输出各种各样的makefile或者project文件。CMake并不直接构建出最终的软件,而是产生其他工具的脚本(如makefile),然后再依据这个工具的构建方式使用。

  • Android利用CMake生成的是ninja(ninja是个小型的关注速度的构建系统)。
  • CMake源文件中所有的有效语句都是命令,可以是内置命令或自定义的函数/宏命令。

1. 基础语法

注释
#[[多行注释
多行注释
多行注释]]
定义变量

CMake中所有的变量都是string类型,可以使用set()和unset()命令来声明或者移除一个变量。

#set(变量名 变量值)
set(var 123)
#message() 打印
message("var = ${var}")
列表

列表也是一个字符串,可以把列表看成一个特殊的变量,这个变量有多个值。

#列表声明 set(列表名 值1 值2 值3) 或者 set(列表名 "值1;值2;值3")
set(list_var 1 2 3)
set(list_var1 "1;2;3")
message("list_var = ${list_var}")
条件命令
#和其他语言差不多,不过if和else都可以加表达式,注意endif,而且缩进和空格对语句解析没有影响
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()可以跳出当前循环

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

循环遍历
foreach(循环变量 参数1 参数2 参数3)
COMMAND(ARGS...)
endforeach(循环变量)

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

foreach(循环变量 RANGE total)
COMMAND(ARGS...)
endforeach(循环变量)
total循环范围为 0-total

foreach(item RANGE 3)
   message("item = ${item}")
endforeach(item)

foreach(循环变量 RANGE start stop step)
COMMAND(ARGS...)
endforeach(循环变量)

循环范围为 start-stop 增量为step

foreach(item RANGE 1 5 2)
    message("item = ${item}")
endforeach(item)

foreach(循环变量 IN LIST 列表)
COMMAND(ARGS...)
endforeach(循环变量)

set(list 1 2 3)
foreach(item IN LISTS list)
   message("item = ${item}")
endforeach(item)
自定义函数

function(name args1 args2 args3)
COMMAND()
endfunction(name)
name(实参列表)

function(func a b c)
   message("a = ${a}")
   message("b = ${b}")
   message("c = ${c}")
   # 参数个数
   message("ARGC = ${ARGC}")
   # 参数列表
   message("ARGV = ${ARGV}")
   message("ARGV0 = ${ARGV0}")
endfunction(func)
func(4 5 6)

自定义宏命令
macro(name args1 args2 arg3)
COMMAND()
endmacro(name)
name(实参列表)

macro(ma x y)
   message("x = ${x}")
   message("y = ${y}")
   endmacro()
ma("hello" "world")
变量的作用域

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

2. 在Android常用到的方法

#查找当前目录所有源文件,并将源文件名称列表保存到DIR_SRCS变量中
#不能查找子目录
aux_source_directory(.DIR_SRCS)
message(${DIR_SRCS})
添加一个常用库
add_library( [STATIC | SHARED | MODULE] [EXCLUDE_FROM_ALL] source1 soure2 .. sourceN)

name:添加一个库文件,名为,会生成 lib.so
指定库的类型:STATIC , SHARED , MODULE
STATIC:静态库
SHARED:动态库
MODULE:在使用dyld的系统有效,如不支持dyld,等同于dyld
EXCLUDE_FROM_ALL:表示该库不会被默认构建
source:指定库的源文件

导入预编译库
add_library(  IMPORTED)
 添加一个已存在的预编译库,名为

#一般配合set_target_properties使用
# 比如
add_library(test SHARED IMPORTED)
set_target_properties(
    test # 指定目标库名
    PROPERTIES IMPORTED_LOCATION # 指明要设置的参数
    库路径/${ANDROID_ABI}/libtest.so # 指明要导入的库路径
)
set常用命令
# 设置可执行文件的输出路径(EXCUTABLE_OUTPUT_PATH是全局变量)
set(EXCUTABLE_OUTPUT_PATH [output_path])
# 设置库文件的输出路径(LIBRARY_OUTPUT_PATH是全局变量)
set(LIBRARY_OUTPUT_PATH [output_path])
# 设置C++编译参数(CMAKE_CXX_FLAGS是全局变量)
set(CMAKE_CXX_FLAGS "-Wall std=c++11")
# 设置源文件集合(SOURCE_FILES是本地变量即自定义变量)
set(SOURCE_FILES main.cpp test.cpp ...)
设置头文件目录
include_directories(./include ${MY_INCLUDE})
添加可执行文件
add_executable( #{SRC_LIST})
添加预编译库
# CMAKE_C_FLAGS c的参数,会传递给编译器
# 如果是C++文件,需要使用CMAKE_CXX_FLAGS
# -L:库的查找路径
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -L[SO所在的目录]")

3. Android中的默认脚本

# 添加一个库,根据native-lib.cpp 源文件编译一个native-lib的动态库
add_library(
    native-lib
    SHARED
    native-lib.cpp)
# 查找系统库,这里是查找了系统的日志库(liblog),并赋值给变量log-lib
# 这个库位于 Android/sdk/ndk-bundle/platforms/android-28/arch-arm64/usr/lib
find_library(
    log-lib
    log)
# 设置依赖库(第一个参数必须为目标模块,顺序不能替换)
target_link_libraries(
    native-lib
    ${log-lib})

补充

在Android Studio中调试命令时,一些高版本可能不会输出CMake指令,但是可以在其他地方查看,具体路径为

app/.externalNativeBuild/cmake/debug/armeabi-v7a/cmake_build_output.txt

你可能感兴趣的:(CMake入门)