NDK 开发之 CMake 的使用

1 概念

CMake 是一个开源的跨平台自动化构建系统。官网地址:CMake

2 使用步骤

之前做 NDK 开发或者老的项目都是基于 Android.mk、Application.mk 来构建项目的,但从 AS 2.2 之后便开始采用 CMake 的方式来构建 C/C++ 项目,采用 CMake 相比与之前的 Android.mk、Application.mk 方便简单了许多。“Talk is cheap. Show me the code.”下面我们介绍 CMake 的使用步骤。

2.1 安装 NDK 和 CMake

打开 Android Studio ,博主的软件版本是3.6.3,选择 Tools->SDK Manager->Android SDK->SDK Tools,勾选 NDK 和 CMake,然后点击 OK,如图所示:

在这里插入图片描述
此时系统会显示一个对话框,告诉您 NDK 软件包占用了多少磁盘空间。点击 OK,安装完成后,点击 Finish。
除了以上两个组件,调试原生代码还需要一个组件:LLDB。默认情况下,LLDB 是跟随 Android Studio 一起安装的。所以在 SDK Tools 列表中没有找到 LLDB 的同学也不用担心,调试原生代码的时候会出现 LLDB 的控制台。

2.2 新建一个项目

在这里插入图片描述
在这里插入图片描述
后面就用默认的设置,直到完成。项目创建完成后,如果底部的状态栏窗口弹出这样一个错误:
Caused by: org.gradle.api.InvalidUserDataException: NDK not configured. Download it with SDK manager. Preferred NDK version is ‘20.0.5594570’.
这是由于没有配置 NKD 路径,这时候我们选择File->Project Structure->SDK Location,设置Android NDK location,如图所示:

在这里插入图片描述
然后等待编译完成即可。

2.3 项目文件介绍

现在我们已经创建成功一个 CMake 项目,我们来看看项目目录。

在这里插入图片描述
这两个文件夹是相比普通项目新增的部分:

  • .cxx :CMake 编译的临时文件,类似于 build 文件夹。
  • cpp :存放 native 代码,包括 .c、.cpp、.h 文件。还有 CMakeLists.txt,CMake 脚本配置的文件。

另外,module 下的 build.gradle 文件也有差异:

在这里插入图片描述

  • 上面的 externalNativeBuild 是 CMake 的一些编译参数。
  • 下面的 externalNativeBuild 是 CMakeLists.txt 的路径和 CMake 的版本信息。

2.4 运行

运行代码,就能看到效果,调用了 C++方法在界面上显示了“Hello from C++”。下面我们来分析下执行逻辑。
首先打开 MainActivity.java

在这里插入图片描述
这里是在界面的 TextView 调用了 stringFromJNI() 方法设置了一个字符串,该方法是一个 native 声明的方法,所以这个方法会调用 c++ 的函数。我们注意到上面有个静态代码块,当 MainActivity 这个类被加载进内存的时候就执行了该部分代码,这里是 System.loadLibrary(“native-lib”) ,加载一个名为 native-lib 的动态链接库,所以才可以调用里面的 c++ 函数。我们打开 native-lib.cpp

在这里插入图片描述
这里有个 Java_com_example_cmakesample_MainActivity_stringFromJNI 函数,返回了一个"Hello from C++"字符串,即 java 代码中调用的 native 方法。我们发现该 native 方法的名字与java方法的名字是一一对应关系,格式为Java_<包名><类名><方法名>(<参数>),这是静态注册的方式,还有另外一种动态注册的方式,详细请见 NDK 开发之 JNI 方法静态注册与动态注册

3 语法介绍

下面介绍 CMake 的基础语法。

#1. 指定 cmake 的最小版本
cmake_minimum_required(VERSION 3.4.1)

#2. 设置项目名称
project(demo)

#3. 设置编译类型
add_executable(demo test.cpp) # 生成可执行文件
add_library(common STATIC test.cpp) # 生成静态库
add_library(common SHARED test.cpp) # 生成动态库或共享库

#4. 明确指定包含哪些源文件
add_library(demo test.cpp test1.cpp test2.cpp)

#5. 自定义搜索规则并加载文件
file(GLOB SRC_LIST "*.cpp" "protocol/*.cpp")
add_library(demo ${SRC_LIST}) //加载当前目录下所有的 cpp 文件
## 或者
file(GLOB SRC_LIST "*.cpp")
file(GLOB SRC_PROTOCOL_LIST "protocol/*.cpp")
add_library(demo ${SRC_LIST} ${SRC_PROTOCOL_LIST})
## 或者
aux_source_directory(. SRC_LIST)//搜索当前目录下的所有.cpp文件
aux_source_directory(protocol SRC_PROTOCOL_LIST) 
add_library(demo ${SRC_LIST} ${SRC_PROTOCOL_LIST})

#6. 用来显式地定义变量,多个变量用空格或分号隔开,引用的时候使用${SRC_LIST}
set(SRC_LIST main.cpp test.cpp)

#7. 在列表末尾添加新的对象
list(APPEND SRC_LIST new_test.cpp)

#8. 向终端输出用户定义的信息,包含了三种类型:SEND_ERROR,产生错误,生成过程被跳过;
# STATUS,输出前缀为—-的信息;FATAL_ERROR,立即终止所有 CMake 过程
message([SEND_ERROR | STATUS | FATAL_ERROR] “message to display” … )

#9. 查找指定库文件
find_library(
              log-lib //为 log 定义一个变量名称
              log ) //ndk 下的 log 库

#10. 设置包含的目录
include_directories(
    ${CMAKE_CURRENT_SOURCE_DIR}
    ${CMAKE_CURRENT_BINARY_DIR}
    ${CMAKE_CURRENT_SOURCE_DIR}/include
)

#11. 设置链接库搜索目录
link_directories(
    ${CMAKE_CURRENT_SOURCE_DIR}/libs
)

#12. 设置 target 需要链接的库
target_link_libraries( # 目标库
                       demo
 
                       # 目标库需要链接的库
                       # log-lib 是上面 find_library 指定的变量名
                       ${log-lib} )
                       
#13. 指定链接动态库或者静态库
target_link_libraries(demo libtest.a) # 链接libtest.a
target_link_libraries(demo libtest.so) # 链接libtest.so

#14. 根据全路径链接动态静态库
target_link_libraries(demo ${CMAKE_CURRENT_SOURCE_DIR}/libs/libtest.a)
target_link_libraries(demo ${CMAKE_CURRENT_SOURCE_DIR}/libs/libtest.so)

#15. 指定链接多个库
target_link_libraries(demo
    ${CMAKE_CURRENT_SOURCE_DIR}/libs/libtest.a
    test.a
    boost_thread
    pthread)

常用预定义变量

预定义变量说明
PROJECT_SOURCE_DIR工程的根目录
PROJECT_BINARY_DIR运行 cmake 命令的目录,通常是 ${PROJECT_SOURCE_DIR}/build
PROJECT_NAME返回通过 project 命令定义的项目名称
CMAKE_CURRENT_SOURCE_DIR当前处理的 CMakeLists.txt 所在的路径
CMAKE_CURRENT_BINARY_DIRtarget 编译目录
CMAKE_CURRENT_LIST_DIRCMakeLists.txt 的完整路径
CMAKE_CURRENT_LIST_LINE当前所在的行
CMAKE_MODULE_PATH定义自己的 cmake 模块所在的路径,SET(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake),然后可以用INCLUDE命令来调用自己的模块
EXECUTABLE_OUTPUT_PATH重新定义目标二进制可执行文件的存放位置
LIBRARY_OUTPUT_PATH重新定义目标链接库文件的存放位置

官方文档链接,选择最新的 Documentation ->Reference Manuals 中的 cmake-commands(7),就可以看到全部的命令了。

4 安装特定版本的 NDK

要安装特定版本的 NDK,请执行以下操作:
选择 Tools->SDK Manager->Android SDK->SDK Tools,选中 Show Package Details 复选框,选中 NDK (Side by side) 复选框及其下方与您要安装的 NDK 版本对应的复选框。Android Studio 会将所有选中版本的 NDK 安装到 android-sdk/ndk/ 目录中。

在这里插入图片描述
如果要安装特定版本的 CMake,方法也是一样的。

  • 4
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论
Android NDK开发是指利用NDK(Native Development Kit)将C/C++开发的代码编译成so库,然后通过JNI(Java Native Interface)让Java程序调用。在Android开发中,默认使用的是Android SDK进行Java语言的开发,而对于一些需要使用C/C++的高性能计算、底层操作或跨平台需求的场景,可以使用NDK进行开发。 在Android Studio中进行NDK开发相对于Eclipse来说更加方便,特别是在Android Studio 3.0及以上版本中,配置更加简化,并引入了CMake等工具,使得开发更加便捷。首先要进行NDK开发,需要配置环境,包括导入NDK、LLDB和CMake等工具。可以通过打开Android Studio的SDK Manager,选择SDK Tools,在其中选中相应的工具进行导入。 在项目的build.gradle文件中,可以配置一些NDK相关的参数,例如编译版本、ABI过滤器等。其中,可以通过externalNativeBuild配置CMake的相关设置,包括CMakeLists.txt文件的路径和版本号。此外,在sourceSets.main中还可以设置jniLibs.srcDirs,指定so库的位置。 在进行NDK开发时,可以在jni文件夹中编写C/C++代码,并通过JNI调用相关的函数。通过JNI接口,可以实现Java与C/C++之间的相互调用,从而实现跨语言的开发。 综上所述,Android NDK开发是指利用NDK将C/C++开发的代码编译成so库,并通过JNI实现与Java的相互调用。在Android Studio中进行NDK开发相对方便,可以通过配置环境和相应的参数来进行开发。<span class="em">1</span><span class="em">2</span><span class="em">3</span>

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ByteSaid

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值