百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术分析 > 正文

深入理解Android NDK 编译(二) android ndk教程

liebian365 2024-11-09 13:41 23 浏览 0 评论

使用 CMake 进行Android NDK编译的原理


介绍

Android Studio 2.2 及以后的版本默认使用CMake进行 NDK 编译 NDK, 其中最吸引人的地方是,在开发NDK程序时可以进行联机调试,这真是大在的方便了我们开发NDK程序的效率了。 那么使用CMake编译NDK程序是否与我们之前介绍的使用ndk-build编译有很大的不同呢?下面我们就来一窥它的原理吧。

前面我给大家介绍了两种交叉编译的方式,没看过的同学可以浏览一下( Linux/Mac 交叉编译 Android 程序深入理解Android NDK编译(一)

什么是CMake

CMake是个开源的跨平台自动化建构系统,它用配置文件控制建构过程(build process)的方式和Unix的Make相似,只是CMake的配置文件取名为CMakeLists.txt。Cmake并不直接建构出最终的软件,而是产生标准的建构档(如Unix的Makefile或Windows Visual C++的projects/workspaces),然后再依一般的建构方式使用

“CMake”这个名字是"cross platform make"的缩写。虽然名字中含有"make",但是CMake和Unix上常见的“make”系统是分开的,而且更为高级

Android Studio 如何使用 CMake

其实通过 CMake 进行 NDK 交叉编译的方式与我们之前介绍的两种方式的原理是相同的。 都是要先设定交叉编译各种工具的环境, 包括编译器、链接器等。 然后再通过自动化构建工具进行编译。

Android Studio在执行 CMake build 之前,会将需要的参数存放在 cmake_build_command.txt 文件中,针对每种ABI(arm, mips, x86等)及每种build类型(debug, release),Android Studio都会拷贝一份 cmake_build_command.txt 到<project-root>/<module-root>/.externalNativeBuild/cmake/<build-type>/<ABI>/目录下。

我们来看一下在 cmake_build_command.txt 里都是些什么内容:

Executable : ~/Library/Android/sdk/cmake/3.6.3155560/bin/cmake

arguments :

-H~/mytest/MyApplication/app

-B~/mytest/MyApplication/app/.externalNativeBuild/cmake/debug/arm64-v8a

-GAndroid Gradle - Ninja

-DANDROID_ABI=arm64-v8a

-DANDROID_NDK=~/Library/Android/sdk/ndk-bundle

-DCMAKE_LIBRARY_OUTPUT_DIRECTORY=~/mytest/MyApplication/app/build/intermediates/cmake/debug/obj/arm64-v8a

-DCMAKE_BUILD_TYPE=Debug

-DCMAKE_MAKE_PROGRAM=~/Library/Android/sdk/cmake/3.6.3155560/bin/ninja

#下面这个参数特别重要

-DCMAKE_TOOLCHAIN_FILE=~/Library/Android/sdk/ndk-bundle/build/cmake/android.toolchain.cmake

-DANDROID_PLATFORM=android-21

-DCMAKE_CXX_FLAGS=-std=c++11 -frtti -fexceptions

Build ArgumentsDescription
-G < build-system ><build-system> 一般设置为 “Android Gradle - Ninja” 它指明 CMake 使用 ninja build system 编译并链接C/C++ ,同时 CMake 还会产生android_gradle_build.json 文件,该文件包含了Gradle CMake 插件使用的信息,如编译参数,产生的目标名等。
-DANDROID_ABI < abi >NDK 支持的 ABIs, 如 armeabi,armeabi-v7a,armeabi-v7a with NEON,arm64-v8a等。
-DANDROID_NDK < path >NDK安装路径
-DCMAKE_LIBRARY_OUTPUT_DIRECTORY < path >输出库的位置
-DCMAKE_BUILD_TYPE < type >build 类型 release 或 debug
-DCMAKE_MAKE_PROGRAM < program-name >启动 native build 系统的工具
-DCMAKE_TOOLCHAIN_FILE < path >CMake 用于交叉编译 Andriod配置文件的路径。它位于 $NDK/build/cmake/ directory 目录下。
-DANDROID_PLATFORM < level >CMake 编译 Android API 级别

在这些参数里,-DCMAKE_TOOLCHAIN_FILE 这个参数特别重要,因为 Android Stuido 在这个参数指定的文件里设置了交叉编译工具的环境变量,下面我们来大体看一下它流程:

207 ......

208 # ABI.

209 set(CMAKE_ANDROID_ARCH_ABI ${ANDROID_ABI})

210 if(ANDROID_ABI MATCHES "^armeabi(-v7a)?$")

211 set(ANDROID_SYSROOT_ABI arm)

212 set(ANDROID_TOOLCHAIN_NAME arm-linux-androideabi)

213 set(ANDROID_TOOLCHAIN_ROOT ${ANDROID_TOOLCHAIN_NAME})

214 set(ANDROID_HEADER_TRIPLE arm-linux-androideabi)

215 if(ANDROID_ABI STREQUAL armeabi)

216 set(CMAKE_SYSTEM_PROCESSOR armv5te)

217 set(ANDROID_LLVM_TRIPLE armv5te-none-linux-androideabi)

218 elseif(ANDROID_ABI STREQUAL armeabi-v7a)

219 set(CMAKE_SYSTEM_PROCESSOR armv7-a)

220 set(ANDROID_LLVM_TRIPLE armv7-none-linux-androideabi)

221 endif()

222

223 ......

android.toolchain.cmake 在第 208 行根据 cmake_build_command.txt 文件中ABI的值,设置 ANDROID_SYSROOT_ABI、ANDROID_TOOLCHAIN_NAME、ANDROID_TOOLCHAIN_ROOT等参数。 然后走到 318 行,设置 CMAKE_SYSROOT 值如下:

317 ......

318 # Sysroot.

319 if(ANDROID_DEPRECATED_HEADERS)

320 set(CMAKE_SYSROOT

321 "${ANDROID_NDK}/platforms/${ANDROID_PLATFORM}/arch-${ANDROID_SYSROOT_ABI}")

322 else()

323 set(CMAKE_SYSROOT "${ANDROID_NDK}/sysroot")

324 ......

设置完 CMAKE_SYSROOT 走到 355 行,设置ANDROID_TOOLCHAIN_ROOT 和 C/C++ 编译器,代码如下:

354 ......

355 # Toolchain.

355 # 首先判断运行的宿主机是什么

356 if(CMAKE_HOST_SYSTEM_NAME STREQUAL Linux)

357 set(ANDROID_HOST_TAG linux-x86_64)

358 elseif(CMAKE_HOST_SYSTEM_NAME STREQUAL Darwin)

359 set(ANDROID_HOST_TAG darwin-x86_64)

360 elseif(CMAKE_HOST_SYSTEM_NAME STREQUAL Windows)

361 set(ANDROID_HOST_TAG windows-x86_64)

362 endif()

362 # 设置 ANDROID_TOOLCHAIN_ROOT

363 set(ANDROID_TOOLCHAIN_ROOT "${ANDROID_NDK}/toolchains/${ANDROID_TOOLCHAIN_ROOT}-4.9/prebuilt/${ANDROID_HOST_TAG}")

364 set(ANDROID_TOOLCHAIN_PREFIX "${ANDROID_TOOLCHAIN_ROOT}/bin/${ANDROID_TOOLCHAIN_NAME}-")

365 ......

368

369 set(ANDROID_HOST_PREBUILTS "${ANDROID_NDK}/prebuilt/${ANDROID_HOST_TAG}")

370 # 如果编译器是 clang

371 if(ANDROID_TOOLCHAIN STREQUAL clang)

372 set(ANDROID_LLVM_TOOLCHAIN_PREFIX "${ANDROID_NDK}/toolchains/llvm/prebuilt/${ANDROID_HOST_TAG}/bin/")

373 set(ANDROID_C_COMPILER "${ANDROID_LLVM_TOOLCHAIN_PREFIX}clang${ANDROID_TOOLCHAIN_SUFFIX}")

374 set(ANDROID_CXX_COMPILER "${ANDROID_LLVM_TOOLCHAIN_PREFIX}clang++${ANDROID_TOOLCHAIN_SUFFIX}")

375 set(ANDROID_ASM_COMPILER "${ANDROID_LLVM_TOOLCHAIN_PREFIX}clang${ANDROID_TOOLCHAIN_SUFFIX}")

376 ......

396 # 如果编译器是 gcc

397 elseif(ANDROID_TOOLCHAIN STREQUAL gcc)

398 set(ANDROID_C_COMPILER "${ANDROID_TOOLCHAIN_PREFIX}gcc${ANDROID_TOOLCHAIN_SUFFIX}")

399 set(ANDROID_CXX_COMPILER "${ANDROID_TOOLCHAIN_PREFIX}g++${ANDROID_TOOLCHAIN_SUFFIX}")

400 set(ANDROID_ASM_COMPILER "${ANDROID_TOOLCHAIN_PREFIX}gcc${ANDROID_TOOLCHAIN_SUFFIX}")

所以通过上面的分析我们可以了解到,Android Studio 通过cmake_build_command.txt指定的 android.toolchain.cmake 文件就把交叉编译的环境设置好了。

CMake NDK 编译过程

当我们在Android Studio中build我们的NDK工程时,AS会通过上面的步骤为我们设置好交叉编译环境,然后再将CMakelists.txt文件传给 CMake, CMake解析里面的内容,并最终调用不同平台的工具,编译出我们需要的目标环境程序。

小结

通过上面的分析,我们知道了 Android Studio 在开发 NDK 程序时,是如何使用 CMake Gradle plugin 设置交叉编译环境的,也基本了解了 CMake 编译 NDK 程序的基本流程。希望本篇文章可以帮助大家理解最新的 Andriod Studio 是如何使用 CMake进行交叉编译的。

相关推荐

精品博文嵌入式6410中蓝牙的使用

BluetoothUSB适配器拥有一个BluetoothCSR芯片组,并使用USB传输器来传输HCI数据分组。因此,LinuxUSB层、BlueZUSB传输器驱动程序以及B...

win10跟这台计算机连接的前一个usb设备工作不正常怎么办?

前几天小编闲来无事就跑到网站底下查看粉丝朋友给小编我留言询问的问题,还真的就给小编看到一个问题,那就是win10跟这台计算机连接的一个usb设备运行不正常怎么办,其实这个问题的解决方法时十分简单的,接...

制作成本上千元的键盘,厉害在哪?

这是稚晖君亲自写的开源资料!下方超长超详细教程预警!!全文导航:项目简介、项目原理说明、硬件说明、软件说明项目简介瀚文智能键盘是一把我为自己设计的——多功能、模块化机械键盘。键盘使用模块化设计。左侧的...

E-Marker芯片,USB数据线的“性能中枢”?

根据线缆行业的研究数据,在2019年搭载Type-C接口的设备出货量已达到20亿台,其中80%的笔记本电脑和台式电脑采用Type-C接口,50%的智能手机和平板电脑也使用Type-C接口。我们都知道,...

ZQWL-USBCANFD二次开发通讯协议V1.04

修订历史:1.功能介绍1.1型号说明本文档适用以下型号:  ZQWL-CAN(FD)系列产品,USB通讯采用CDC类实现,可以在PC机上虚拟出一个串口,串口参数N,8,1格式,波特率可以根据需要设置(...

win10系统无法识别usb设备怎么办(win10不能识别usb)

从驱动入手,那么win10系统无法识别usb设备怎么办呢?今天就为大家分享win10系统无法识别usb设备的解决方法。1、右键选择设备管理器,如图:  2、点击更新驱动程序,如图:  3、选择浏览...

微软七月Win8.1可选补丁有内涵,含大量修复

IT之家(www.ithome.com):微软七月Win8.1可选补丁有内涵,含大量修复昨日,微软如期为Win7、Win8.1发布7月份安全更新,累计为6枚安全补丁,分别修复总计29枚安全漏洞,其中2...

如何从零开始做一个 USB 键盘?(怎么制作usb)

分两种情况:1、做一个真正的USB键盘,这种设计基本上不涉及大量的软件编码。2、做一个模拟的USB键盘,实际上可以没有按键功能,这种的需要考虑大量的软件编码,实际上是一个单片机。第一种设计:买现成的U...

电脑识别U盘失败?5个实用小技巧,让你轻松搞定USB识别难题

电脑识别U盘失败?5个实用小技巧,让你轻松搞定USB识别难题注意:有些方法会清除USB设备里的数据,请谨慎操作,如果不想丢失数据,可以先连接到其他电脑,看能否将数据复制出来,或者用一些数据恢复软件去扫...

未知usb设备设备描述符请求失败怎么解决

出现未知daousb设备设备描述符请求失du败解决办zhi法如下:1、按下Windows+R打开【运行】;2、在版本运行的权限输入框中输入:services.msc按下回车键打开【服务】;2、在服务...

读《飘》47章20(飘每章概括)

AndAhwouldn'tleaveMissEllen'sgrandchildrenfornotrashystep-patobringup,never.Here,Ah...

英翻中 消失的过去 37(消失的英文怎么说?)

翻译(三十七):消失的过去/茱迪o皮考特VanishingActs/JodiPicoult”我能做什么?“直到听到了狄利亚轻柔的声音,我才意识到她已经在厨房里站了好一会儿了。当她说话的时候,...

RabbitMQ 延迟消息实战(rabbitmq如何保证消息不被重复消费)

现实生活中有一些场景需要延迟或在特定时间发送消息,例如智能热水器需要30分钟后打开,未支付的订单或发送短信、电子邮件和推送通知下午2:00开始的促销活动。RabbitMQ本身没有直接支持延迟...

Java对象拷贝原理剖析及最佳实践(java对象拷贝方法)

作者:宁海翔1前言对象拷贝,是我们在开发过程中,绕不开的过程,既存在于Po、Dto、Do、Vo各个表现层数据的转换,也存在于系统交互如序列化、反序列化。Java对象拷贝分为深拷贝和浅拷贝,目前常用的...

如何将 Qt 3D 渲染与 Qt Quick 2D 元素结合创建太阳系行星元素?

Qt组件推荐:QtitanRibbon:遵循MicrosoftRibbonUIParadigmforQt技术的RibbonUI组件,致力于为Windows、Linux和MacOSX提...

取消回复欢迎 发表评论: