车载Android进阶篇(NDK其一) — CMake基础

1. 前言

在车载应用开发时,NDK其实并不常用。不常用但也不是完全用不到,车载应用开发以下的一些场景会需要使用NDK

  • 调用Linxu API。例如:将线程绑定到指定的CPU核心上运行。
  • 使用高性能图形API。例如:使用OpenGL ES或Vulkan绘制图。
  • 复用C/C++库
  • 其他需要使用Native API的情况

不过本文并不是NDK的入门教程,NDK的基础入门教程,请参考官方的中文教程:NDK 使用入门 | Android NDK | Android Developers
本文主要讲解,在Android使用NDK所必须的构建工具 — CMake。

注意本文是面向Android开发者编写的Cmake基础教程,完全不适用于非Android开发者阅读!

2. CMake 概述

2.1. CMake 简介

CMake是个一个开源的跨平台自动化建构系统,用来管理软件建置的程序,并不依赖于某特定编译器,并可支持多层目录、多个应用程序与多个库。 它用配置文件控制建构过程(build process)的方式和Unix的make相似,只是CMake的配置文件取名为CMakeLists.txt。CMake并不直接建构出最终的软件,而是产生标准的建构档(如Unix的Makefile或Windows Visual C++的projects/workspaces),然后再依一般的建构方式使用。这使得熟悉某个集成开发环境(IDE)的开发者可以用标准的方式建构他的软件,这种可以使用各平台的原生建构系统的能力是CMake和SCons等其他类似系统的区别之处。

CMake配置文件(CMakeLists.txt)可设置源代码或目标程序库的路径、产生适配器(wrapper)、还可以用任意的顺序建构可执行文件。CMake支持in-place建构(二进档和源代码在同一个目录树中)和out-of-place建构(二进档在别的目录里),因此可以很容易从同一个源代码目录树中建构出多个二进档。CMake也支持静态与动态程序库的建构。

“CMake”这个名字是"Cross platform Make"的缩写。虽然名字中含有"make",但是CMake和Unix上常见的“make”系统是分开的,而且更为高端。 它可与原生建置环境结合使用,例如:make、ninja、苹果的Xcode与微软的Visual Studio。

初学者需要注意,Cmake并不是只能构建C/C++语言编写的程序,CMake默认支持所有语言。

CMake 的官方网站:https://cmake.org/

2.2. CMake 在Android中的作用

Android应用开发时,我们只需要知道,CMake是一个外部构建工具,可与 Gradle 搭配使用来构建原生库即可。

3. CMake 基础语法

CMake 构建脚本是一个纯文本文件,必须将其命名为 CMakeLists.txt,并在其中包含 CMake 构建 C/C++ 库时需要使用的命令CMakeLists.txt都是由一个个指令组成的。

我们来看一个简单的例子,不需要理解它的含义。

project(HELLO)

if(TRUE)
   set(SRC_LIST "main.cpp")
   add_executable(hello ${SRC_LIST})
endif()
  • project()就是一个指令,而HELLO就是具体的参数。

  • 指令不区分大小写。在Android中默认推荐小写。

  • 参数与参数之间,用空格分割。

  • 引用定义好的变量,使用${}。但是在IF控制语句中直接使用变量名即可。

诸如 while、foreach等语句,在Android开发中不是很常用就不介绍了。

4. CMake 常用常量

在CMake中系统定义的常量极多,不过大多数都能见名知意,所以这里只介绍一些相对常用的。

  • CMAKE_VERSION: 当前CMake使用的版本
  • CMAKE_BINARY_DIR / PROJECT_BINARY_DIR: 工程编译发生的路径
  • CMAKE_SOURCE_DIR / PROJECT_SOURCE_DIR: 工程的顶层路径
  • CMAKE_CURRENT_BINARY_DIR: 工程编译结果存放的路径
  • CMAKE_CURRENT_SOURCE_DIR: 当前处理的CMakeLists.txt所在的路径
  • CMAKE_PROJECT_NAME: 工程的名字
  • CMAKE_CURRENT_LIST_FILE: 当前CMakeLists.txt所在的完整路径
  • CMAKE_CURRENT_LIST_LINE: 调用这个变量时,在CMakeList.txt中所在的行数
  • CMAKE_ANDROID_ARCH_ABI: 编译的二进制接口(armeabi-v7a、arm64-v8a、x86、x86_64)

在Cmake中常量的使用方式如下:

5. Cmake 常用指令

  • cmake_minimum_required
    设定Cmake所需要的最低版本,一般在CMakeLists.txt的开头声明。
cmake_minimum_required(VERSION 3.18.1)
  • project
    设定工程名。
project("jnidemo")

该指令还可以配置工程支持的语言,缺省时默认支持所有语言,也是推荐使用的方式。

project("jnidemo" CXX) # 支持C++
project("jnidemo" C CXX) # 支持C 和 C++
  • add_library
    使用指定的源文件向工程中添加一个共享库,主要有一下几种形式。
add_library(<name> 
            [STATIC | SHARED]
            [<source>...])

<name> :设定共享库的名字。最终编译出的共享库会自动加上lib前缀。例如,如果设定目标库名为jnidemo,最终编译出的目标库的名字会是libjnidemo

[STATIC | SHARED] :设定共享库的类型,STATIC是静态库(libname.a),SHARED是动态库(libname.so)

[<source>...] :设定源文件。

使用示例:

add_library(jnidemo
        SHARED
        native-lib.cpp)

一个工程中可以设定添加多个目标库,gradle会自动将这些共享库打包到APK中。

add_library还有一些其他的用法,不过在Android开发中不常用,就不介绍了,以免增加入门学习的门槛。

  • find_library
    在系统中查找共享库的路径,并赋值给变量。
find_library(
<Varname>
        
[<path1> <path2> ...] )

<Varname> :变量名。

[<path1> <path2> ...] :需要查找的NDK共享库名称。

使用示例:

find_library(
        log-lib
log)

查找Android中的log库,并将路径赋值给变量log-lib

  • target_link_libraries
    将指定的库链接到另一个目标上,这样就可以在目标中调用被链接库的函数。
target_link_libraries(
[<name>...]
[${<Varname>}...] )

<name>: 目标库的名字

${<VarName>}: 需要链接的共享库

使用示例:

target_link_libraries(
        jnidemo
        ${log-lib})

该示例中,将log-lib变量对应的库,链接到jnidemo这个目标库中。

  • set_target_properties
    设定目标可以具有影响其构建方式的属性。
set_target_properties(target1 target2 ...
        PROPERTIES prop1 value1
        prop2 value2 ...)
  • set
    为一个CMake变量赋值。
set(SRC log-lib)

也可以将一个变量设置成多个值

set(SRC_LIST main.cpp test1.cpp test2.cpp)
  • message
    用于在终端向用户输出消息。
message([<mode>] "message to display" ...)

[<mode>]: 可选的输出形式(这里介绍几种常用)

缺省:信息打印到终端。

message("message to display")

WARNING :打印警告信息,但是不中断构建过程。

message(WARNING "message to display")

FATAL_ERROR :打印错误信息,终止构建过程。

message(FATAL_ERROR "message to display")

SEND_ERROR :打印错误信息,跳过构建过程。

message(SEND_ERROR "message to display")
  • include_directories
    将给定的目录添加到编译器用于搜索包含文件的目录。

在编写JNI程序导入我们自己编写的头文件时,需要使用include "xxx..h",而不能使用include <xxx.h>,这是因为""是从相对路径查找,而<>是从搜索路径查找。使用include_directories就可以将我们自己编写的头文件导入到搜索路径,这样就可以使用<>导入自定义的头文件。

include_directories([<path1> <path2> ...])

使用示例:

include_directories(${CMAKE_SOURCE_DIR})
  • add_executable
    使用指定的源文件将可执行文件添加到项目中。

  • include
    从文件或模块加载并运行CMake代码。

include(${OTHER_DIR}/CMakeLists.txt)
  • target_include_directories
    将包含目录添加到目标。
target_include_directories(<target> [SYSTEM] [BEFORE]
        <INTERFACE|PUBLIC|PRIVATE> [items1...]
        [<INTERFACE|PUBLIC|PRIVATE> [items2...] ...])
  • add_definitions
    在源文件的编译中添加-D define标志。
add_definitions(-DFOO -DBAR ...)

CMake的更多指令以及含义,可以参考官方手册cmake-commands(7) ‒ CMake 3.18.6 Documentation

6. 总结

以上就是CMake的基础教程,CMake本身虽然很复杂但是在Android应用开发中的使用却相对比较简单,一般只需要记住几个常用的指令即可。下一篇我们在继续介绍JNI的基础。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,098评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,213评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,960评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,519评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,512评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,533评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,914评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,574评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,804评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,563评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,644评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,350评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,933评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,908评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,146评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,847评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,361评论 2 342

推荐阅读更多精彩内容