当前位置: 首页 > news >正文

NDK编译脚本:Android.mk or CMakeLists.txt

本文来自于:https://github.com/xufuji456/FFmpegAndroid/blob/master/doc/NDK_compile_shell.md

前言

Android NDK以前默认使用Android.mk与Application.mk进行构建,但是在Android Studio2.2之后推荐使用CMake进行编译。

CMake是跨平台编译工具,全称为cross platform make,内建c、c++、java自动相依性分析功能。NDK通过工具链支持CMake,工具链文件是用于自定义交叉编译工具链的CMake文件。用于NDK的工具链位于/build/cmake/android.toolchain.cmake。

关于CMake更多详情请参考官网:cmake官网。下面对比下Android.mk与CMakeLists.txt的语法。
更详细脚本分析可查看博客:NDK编译脚本分析

一、Android.mk语法

以动态库编译hello模块为例,完整脚本如下:

WORKING_DIR := $(call my-dir)
LOCAL_PATH := $(WORKING_DIR)include $(CLEAR_VARS)
LOCAL_ARM_MODE  := arm
LOCAL_MODULE    := libffmpeg
LOCAL_SRC_FILES := $(LOCAL_PATH)/ffmpeg/$(TARGET_ARCH_ABI)/lib$(LOCAL_MODULE).so
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/ffmpeg/include
include $(PREBUILT_SHARED_LIBRARY)include $(CLEAR_VARS)
LOCAL_ARM_MODE  := arm
#模块名称
LOCAL_MODULE    := hello
#源文件
LOCAL_SRC_FILES := hello.c
#头文件路径
LOCAL_C_INCLUDES := $(LOCAL_PATH)
#系统库依赖
LOCAL_LDLIBS    := -llog -lz -lm -landroid
#第三方动态库
LOCAL_SHARED_LIBRARIES := libffmpeg
#以动态库形式编译
include $(BUILD_SHARED_LIBRARY)

1、LOCAL_MODULE

声明模块名称,例如这里编译出来的动态库名称为libhello.so。

2、LOCAL_SRC_FILES

声明源文件列表,文件之间用空格分开,需要换行时使用’'换行符。

3、LOCAL_C_INCLUDES

声明头文件路径,例如$(LOCAL_PATH)/xxx

4、LOCAL_CPP_EXTENSION

指定C++源文件除.cpp以外的文件扩展名,例如这样LOCAL_CPP_EXTENSION := .cpp .cxx .cc

5、LOCAL_CPP_FEATURES

指定依赖c++的某些功能,例如RTTI(运行时类型信息):
LOCAL_CPP_FEATURES := rtti
使用c++异常检测:
LOCAL_CPP_FEATURES := exceptions

6、LOCAL_CFLAGS

在编译c和c++源文件时编译系统要传递的编译器标记,即指定额外的宏定义或编译选项。
LOCAL_CFLAGS += -I

7、LOCAL_STATIC_LIBRARIES

共享静态库,作为第三方库被引用
LOCAL_STATIC_LIBRARIES := libavcodec libavutil libavformat libavfilter

8、LOCAL_SHARED_LIBRARIES

共享动态库,与共享静态库一样作为第三方库被引用
LOCAL_SHARED_LIBRARIES := libffmpeg

9、LOCAL_LDLIBS

额外链接器,一般为系统库,使用-l来引用
LOCAL_LDLIBS := -lz -lm

10、 LOCAL_ARM_MODE

ndk默认使用thumb模式来生成目标二进制文件,每条指令为16位宽。也可以指定为ARM模式,来生成32位ARM的目标文件:
LOCAL_ARM_MODE := arm

11、LOCAL_ARM_NEON

用于开启NEON指令加速,仅对armeabi-v7a平台有效。为模块开启NEON:
LOCAL_ARM_NEON := true
为单独源文件开启NEON:
LOCAL_SRC_FILES := hello.c.neon

12、TARGET_ARCH

用于指向CPU架构,包括x86、x86_64、armeabi-v7a、 arm64-v8a

13、TARGET_PLATFORM

目标平台,对应Android API级别号,例如Android5.0系统镜像对应Android API级别21:android-21

14、打印信息

可用warning、debug、info、error级别来打印信息,如果是打印error信息,会终止编译。以warning为例:
$(warning ‘This is a test’)

15、if条件判断

采用ifeq关键字,然后左右变量放在括号体内,用逗号分隔:

ifeq($(TARGET_ABI), arm64-v8a)
$(debug 'This is arm64-v8a')
endif

二、Application.mk语法

Android.mk依赖Application.mk文件进行编译,一般Application.mk脚本如下所示:

APP_STL      := c++_static
APP_DEBUG    := false
APP_OPTIM    := release
APP_CPPFLAGS := -frtti
APP_PLATFORM := android-16
APP_ABI      := armeabi-v7a arm64-v8a

1、APP_ABI

与Android.mk的TARGET_ABI对应,包括CPU架构有:x86、x86_64、armeabi-v7a、arm64-v8a,支持所有平台这样表示:APP_ABI := all

2、APP_BUILD_SCRIPT

指向编译脚本的路径,一般Android.mk和Application.mk都位于jni目录,默认指向jni/Android.mk路径,如果是其他路径,需要使用此变量来指定绝对路径:APP_BUILD_SCRIPT := /xx/xx/Android.mk

3、APP_OPTIM

编译优化选项,调试模式为debug,发布模式为release。在调试模式下,会保留symbol符号表;在发布模式下,会开启优化,去掉symbol符号表。

4、APP_PLATFORM

指定编译平台,面向于Android API级别,对应gradle声明的minSdkVersion。如果不声明,默认为ndk支持的最低API版本

5、APP_STL

声明使用c++的标准库,默认为system STL。其他选项包括c++_static、c++_shared和none

三、CMakeLists.txt语法

以编译hello模块以及依赖ffmpeg模块为例:

cmake_minimum_required(VERSION 3.4.1)
#添加动态库,包含源文件路径
add_library( helloSHAREDsrc/main/jni/hello.c)
#添加第三方动态库
add_library( ffmpegSHAREDIMPORTED )
#指定第三方库路径
set_target_properties( ffmpegPROPERTIES IMPORTED_LOCATION../../../../libs/${CMAKE_ANDROID_ARCH_ABI}/libffmpeg.so )
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11")
#指定头文件路径
include_directories(src/main/cpp)
if(${CMAKE_ANDROID_ARCH_ABI} MATCHES "armeabi-v7a")include_directories(src/main/cpp/include/armeabi-v7a)message("This is armeabi-v7a")
elseif(${CMAKE_ANDROID_ARCH_ABI} MATCHES "arm64-v8a")include_directories(src/main/cpp/include/arm64-v8a)message("This is arm64-v8a")
endif()
#查找系统库
find_library( # Sets the name of the path variable.log-liblog )
#链接目标库
target_link_libraries( helloffmpeg${log-lib} )

1、add_library

传递三个参数,第一个参数是模块名称,第二个参数是SHARED或者STATIC。如果是源文件模块,第三个参数是源文件列表;如果是第三方库,第三个参数是IMPORTED。

2、set_target_properties

用于指定第三方库路径,IMPORT_LOCATION一般是指向src/main/cpp目录

3、include_directories

用于指定头文件路径,头文件路径可以有多个

4、find_library

用于查找系统库,比如Android系统的log日志库

5、target_link_libraries

链接目标库,把依赖库都链接到目标库中

6、if条件判断

与Android.mk稍有差异,CMake采用if...MATCHES形式,例如:

if(${CMAKE_ANDROID_ARCH_ABI} MATCHES "armeabi-v7a")
......
endif()

7、打印日志

与Android.mk不同的是,CMake采用message函数来打印日志,括号体传入msg内容message("hello, cmake")

8、命令行参数

命令行参数前面统一加上-D,常用的参数:

  • -DANRDOID_ABI :android的ABI架构平台

  • -DANDROID_NDK :ndk路径

  • -DANDROID_ARM_MODE :arm模式/thumb模式

  • -DANDROID_ARM_NEON :是否开启arm neon加速,针对armeabi-v7a平台

  • -DANDROID_TOOLCHAIN :编译工具链

  • -DANDROID_NATIVE_API_LEVEL :与ANDROID_PLATFORM相同,对应minSdkVersion

  • -DCMAKE_BUILD_TYPE :编译类型,debug或release

  • -DCMAKE_MAKE_PROGRAM :编译程序

  • -DCMAKE_TOOLCHAIN_FILE :编译文件

9、命令行编译

以cmake作为关键字,后面带着指定参数,示例如下:

    cmake \-DANDROID_ABI=armeabi-v7a \-DANDROID_NDK=${HOME}/Android/Sdk/ndk-bundle \-DCMAKE_BUILD_TYPE=Debug \-DCMAKE_MAKE_PROGRAM=${HOME}/Android/Sdk/cmake/3.6.3155560/bin/ninja \-DCMAKE_TOOLCHAIN_FILE=${HOME}/Android/Sdk/ndk-bundle/build/cmake/android.toolchain.cmake \-DANDROID_NATIVE_API_LEVEL=23 \-DANDROID_TOOLCHAIN=clang

四、ndk编译配置

1、Android.mk方式配置

在gradle的defaultConfig配置ndk:

defaultConfig {......ndk {moduleName "hello"abiFilters "armeabi-v7a", "arm64-v8a"}
}

然后配置jni源文件路径:

sourceSets {main {jniLibs.srcDir 'src/main/libs' // Enable to use libsjni.srcDirs 'src/main/jni' // Enable the automatic ndk-build}
}

另外配置Android.mk文件绝对路径:

externalNativeBuild {ndkBuild {"src/main/jni/Android.mk"}
}

2、CMake方式配置

前两步与Android.mk方式一样,配置脚本路径稍有差异:

externalNativeBuild {cmake {path "CMakeLists.txt"}
}

另外在defaultConfig设置cppFlags:

externalNativeBuild {cmake {cppFlags ""}
}

五、ndk编译过程

1、ndk-build编译

在命令行输入ndk-build后,会根据声明所支持的平台依次编译。首先是armeabi-v7a平台架构,把hello.c源文件编译成hello目标文件,然后链接成libhello.so动态库,最终安装到libs/armeabi-v7a目录下。

2、cmake在Gradle中编译

编译arm64-v8a平台架构的hello模块。首先把hello.c源文件编译成hello.c.o目标文件,然后链接成libhello.so动态库。

生成的debug模式动态库在/build/intermediates/cmake/debug/obj/arm64-v8a目录下。

相关文章:

NDK编译脚本:Android.mk or CMakeLists.txt

本文来自于:https://github.com/xufuji456/FFmpegAndroid/blob/master/doc/NDK_compile_shell.md 前言 Android NDK以前默认使用Android.mk与Application.mk进行构建,但是在Android Studio2.2之后推荐使用CMake进行编译。 CMake是跨平台编译工具&#…...

低代码提速应用开发

低代码介绍 低代码平台是指一种能够帮助企业快速交付业务应用的平台。自2000年以来,低代码市场一直充斥着40大大小小的各种玩家,比如国外的Appian、K2、Pega Systems、Salesforce和Ultimus,国内的H3 BPM。 2015年以后,这个市场更是…...

Hi3516DV500 SVP_NNN添加opencv库记录

默认没有带opencv库,但是实际项目中需要用到opencv库,因此添加一下此库; 1:编译opencv源码,这里具体可以参考 海思Hi3516移植opencv以及错误调试_海思hi3516摄像头开发-CSDN博客 2:在工程的根目录下新建…...

BIO实战、NIO编程与直接内存、零拷贝深入剖析

原生 JDK 网络编程 BIO BIO,意为 Blocking I/O,即阻塞的 I/O。   BIO 基本上就是我们上面所说的生活场景的朴素实现。在 BIO 中类 ServerSocket 负责绑定 IP 地址,启动监听端口,等待客户连接;客户端 Socket 类的实例…...

计网第六章(应用层)(四)(电子邮件)

电子邮件采用客户/服务器的方式。 1、三个构成 电子邮件系统的三个组成构件:用户代理、邮件服务器以及电子邮件所需的协议。 用户代理是用户与电子邮件系统的接口,又称为电子邮件客户端软件。 邮件服务器是电子邮件系统的基础设施。因特网上所有的服…...

Lua篇笔记

. 和 : 的区别 lua的面向对象 Lua数据类型 nil number bool table string userdata thread function Lua-字符串连接 C#与Lua交互过程及原理 Lua中的闭包 常见的一些Lua功能 热重载: function reload_module(module_name) local old_module _G[module_name] --取…...

一种更具破坏力的DDoS放大攻击新模式

近日,内容分发网络(CDN)运营商Akamai表示,一种使网站快速瘫痪的DDoS放大攻击新方法正在被不法分子所利用。这种方法是通过控制数量巨大的中间设备(middlebox,主要是指配置不当的服务器)&#xf…...

WordPress 常规设置页面调用媒体中心上传图片插入URL(新版可用)

首先,我们需要在主题或插件文件夹中创建一个 JavaScript 文件(如:media-uploader.js),该文件中包含如下代码。 /*** 媒体中心上传 js **/ jQuery(document).ready(function($){var mediaUploader;$(#upload_image_but…...

Elasticsearch实现检索词自动补全(检索词补全,自动纠错,拼音补全,繁简转换) 包含demo

Elasticsearch实现检索词自动补全 自动补全定义映射字段建立索引测试自动补全 自动纠错查询语句查询结果 拼音补全与繁简转换安装 elasticsearch-analysis-pinyin 插件定义索引与映射建立拼音自动补全索引测试拼音自动补全测试繁简转换自动补全 代码实现demo结构demo获取 自动补…...

LaunchView/启动页 的实现

1. 创建启动画板,LaunchScreen.storyboard 添加组件如图: 2. 项目中设置只支持竖屏,添加启动画板,如图: 3. 创建启动画面动画视图,LaunchView.swift import SwiftUI/// 启动视图 struct LaunchView: View {/// 字符串转换为字符串…...

windows安装npm教程

在安装和使用NPM之前,我们需要先了解一下,NPM 是什么,能干啥? 一、NPM介绍 NPM(Node Package Manager)是一个用于管理和共享JavaScript代码包的工具。它是Node.js生态系统的一部分,广泛用于构…...

网络端口验证

网络端口连通性验证 1、背景2、目标3、环境4、部署4.1、准备工作4.2、安装4.3、场景测试 1、背景 在日常运维过程中经常会遇到以下两种场景: 1、程序业务端口的开具及验证 2、业务程序访问异常网络排障 2、目标 1、验证端口的正确开具 2、网络策略的连通性 3、环…...

MongoDB 索引和常用命令

一、基本常用命令 1.1 案例需求 存放文章评论的数据存放到 MongoDB 中,数据结构参考如下,其中数据库为 articledb, 专栏文章评论 comment 字段名称 字段含义 字段类型 备注 _id ID ObjectId或String Mongo的主键的字段 articlei…...

【超详细】win10安装docker

win10安装docker 因为要在win10复现一个CVE漏洞,需要用到docker所以特地自己亲自安装了一下,其实在win10上安装docker与在Linux上面的原理一致,都是将docker安装在虚拟机里,不同的是win10是安装在Hyper-V虚拟机上的,需…...

JVM调优(一)

什么时候会有内存泄漏,怎么排查? 答: 首先内存泄漏是堆中的一些对象不会再被使用了,但是无法被垃圾收集器回收,如果不进行处理,最终会导致抛出 java.lang.OutOfMemoryError 异常。 内存泄露: …...

Parallels Desktop 19中文-- PD19最新安装

Parallels Desktop 19可以让我们在Mac电脑上运行Windows和其他操作系统,而无需重启计算机。这款软件的稳定性较高,能够在Mac上同时运行多个操作系统,如Windows、Linux等,而无需重启电脑。它可以让用户无缝地在不同操作系统之间切换…...

【c++】向webrtc学比较1:AheadOf、IsNewerTimestamp

webrtc源码分析-rtp序列号新旧比较 大神文章分析的非常到位。大神分析:AheadOrAt(a, b)是判断a是否比b新的核心,其原理是这样的:rfc1982规定了序列号递增间隔不能超过取值范围的1/2(这是自己理解的),那么要判断a是否比b新,只要判断b到a的递增是否在1/2即可,递增超过1/2,…...

华为云云耀云服务器L实例评测|企业项目最佳实践之docker部署及应用(七)

华为云云耀云服务器L实例评测|企业项目最佳实践系列: 华为云云耀云服务器L实例评测|企业项目最佳实践之云服务器介绍(一) 华为云云耀云服务器L实例评测|企业项目最佳实践之华为云介绍(二) 华为云云耀云服务器L实例评测&#xff5…...

MAC上使用Wireshark常见问题

文章目录 介绍正文启动异常-Permission denied解决方法 过滤协议和地址指定源地址和目的地址调整 time format 介绍 简单记录Wireshark在日常使用过程中的遇到的小case。 正文 Wireshark相较于tcpdump使用较为简单,交互也更为友好。 点击Start即可启动抓包 启动…...

在C++中++a和a++有什么区别?

2023年10月16日,周一中午 a和a在语义上的区别 a是先进行运算(增加1),然后返回新值。 a是先返回原值,然后进行运算(增加1)。 a和a在效率上的区别 a直接返回新值,不需要临时变量保存原值。 而a需要先返回原值,然后再进行增加1的操作。这需要使用一个临时变量来保存…...

观成科技:隐蔽隧道工具Ligolo-ng加密流量分析

1.工具介绍 Ligolo-ng是一款由go编写的高效隧道工具,该工具基于TUN接口实现其功能,利用反向TCP/TLS连接建立一条隐蔽的通信信道,支持使用Let’s Encrypt自动生成证书。Ligolo-ng的通信隐蔽性体现在其支持多种连接方式,适应复杂网…...

【第二十一章 SDIO接口(SDIO)】

第二十一章 SDIO接口 目录 第二十一章 SDIO接口(SDIO) 1 SDIO 主要功能 2 SDIO 总线拓扑 3 SDIO 功能描述 3.1 SDIO 适配器 3.2 SDIOAHB 接口 4 卡功能描述 4.1 卡识别模式 4.2 卡复位 4.3 操作电压范围确认 4.4 卡识别过程 4.5 写数据块 4.6 读数据块 4.7 数据流…...

MODBUS TCP转CANopen 技术赋能高效协同作业

在现代工业自动化领域,MODBUS TCP和CANopen两种通讯协议因其稳定性和高效性被广泛应用于各种设备和系统中。而随着科技的不断进步,这两种通讯协议也正在被逐步融合,形成了一种新型的通讯方式——开疆智能MODBUS TCP转CANopen网关KJ-TCPC-CANP…...

CRMEB 框架中 PHP 上传扩展开发:涵盖本地上传及阿里云 OSS、腾讯云 COS、七牛云

目前已有本地上传、阿里云OSS上传、腾讯云COS上传、七牛云上传扩展 扩展入口文件 文件目录 crmeb\services\upload\Upload.php namespace crmeb\services\upload;use crmeb\basic\BaseManager; use think\facade\Config;/*** Class Upload* package crmeb\services\upload* …...

Maven 概述、安装、配置、仓库、私服详解

目录 1、Maven 概述 1.1 Maven 的定义 1.2 Maven 解决的问题 1.3 Maven 的核心特性与优势 2、Maven 安装 2.1 下载 Maven 2.2 安装配置 Maven 2.3 测试安装 2.4 修改 Maven 本地仓库的默认路径 3、Maven 配置 3.1 配置本地仓库 3.2 配置 JDK 3.3 IDEA 配置本地 Ma…...

Go 并发编程基础:通道(Channel)的使用

在 Go 中,Channel 是 Goroutine 之间通信的核心机制。它提供了一个线程安全的通信方式,用于在多个 Goroutine 之间传递数据,从而实现高效的并发编程。 本章将介绍 Channel 的基本概念、用法、缓冲、关闭机制以及 select 的使用。 一、Channel…...

【Redis】笔记|第8节|大厂高并发缓存架构实战与优化

缓存架构 代码结构 代码详情 功能点: 多级缓存,先查本地缓存,再查Redis,最后才查数据库热点数据重建逻辑使用分布式锁,二次查询更新缓存采用读写锁提升性能采用Redis的发布订阅机制通知所有实例更新本地缓存适用读多…...

TSN交换机正在重构工业网络,PROFINET和EtherCAT会被取代吗?

在工业自动化持续演进的今天,通信网络的角色正变得愈发关键。 2025年6月6日,为期三天的华南国际工业博览会在深圳国际会展中心(宝安)圆满落幕。作为国内工业通信领域的技术型企业,光路科技(Fiberroad&…...

Oracle11g安装包

Oracle 11g安装包 适用于windows系统,64位 下载路径 oracle 11g 安装包...

从物理机到云原生:全面解析计算虚拟化技术的演进与应用

前言:我的虚拟化技术探索之旅 我最早接触"虚拟机"的概念是从Java开始的——JVM(Java Virtual Machine)让"一次编写,到处运行"成为可能。这个软件层面的虚拟化让我着迷,但直到后来接触VMware和Doc…...