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,主要是指配置不当的服务器)…...
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实例评测࿵…...
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的操作。这需要使用一个临时变量来保存…...
NewStarCTF2023公开赛道-压缩包们
题目提示是压缩包 用010editor打开,不见PK头,补上50 4B 03 04 14 00 00 00 将文件改成.zip后缀,打开,解压出flag.zip 尝试解压,报错 发现一串base64编码 SSBsaWtlIHNpeC1kaWdpdCBudW1iZXJzIGJlY2F1c2UgdGhleSBhcmUgd…...
oracle数据库增加表空间数据文件
查询数据文件:select * from dba_data_files order by file_name; 增加:alter tablespace 数据库名 add datafile data size 34359721984;...
【08】基础知识:React中收集表单数据(非受控组件和受控组件)
一、概念 非受控组件: 页面中所有输入类的 DOM,现用现取。 给组件绑定 ref 属性,在需要时通过 ref 获取相应值。 受控组件: 页面中所有输入类的 DOM,随着输入,将内容维护到状态 state中,当…...
数据结构之堆排序和前,中,后,层序遍历,链式二叉树
首先我们要知道升序我们要建小堆,降序建大堆,这与我们的大多人直觉相违背。 因为我们大多数人认为应该将堆顶的数据输出,但如果这样就会导致堆顶出堆以后,堆结构会被破坏,显然我们不能这样。 所有我们反其道而行&…...
多线程中ThreadPoolExecutor.map()中传递多个参数
with concurrent.futures.ThreadPoolExecutor(max_threads) as executor:results executor.map(get_captcha_image, ip_addrs, [img_url] * len(ip_addrs)) #要传入多个参数时,每个参数都得是固定相同长度的可迭代对象# 收集结果for result in results:print(resul…...
linux centos7 环境下 no such file or directory
目录 1.问题描述2.主要原因2.1修改后代码2.2修改前代码 总结参考 1.问题描述 预览excel文件时无法找到对应的html文件 2.主要原因 异常原因:代码获取的是系统的tmp文件,但是linux环境环境中心tmp目录是没有权限的,所以不能获取系统的根目录…...
Nginx 反向代理 SSL 证书绑定域名
配置 Nginx 反向代理和 SSL 泛域名证书绑定域名 Nginx 是一个功能强大的 Web 服务器和反向代理服务器,可以用于将客户端请求转发到后端服务器,并提供安全的 HTTPS 连接。本文将介绍如何配置 Nginx 反向代理,并使用 SSL 泛域名证书绑定域名&a…...
SpringBoot 集成 JMS 与 IBMMQ 代码示例教程
文章目录 前言一、集成 JMS 与 IBMMQ1、pom 依赖2、yml 配置3、Properties 配置类4、Factory 连接工厂类5、配置连接认证6、配置缓存连接工厂7、配置事务管理器8、配置JMS模板9、消息发送与接收 总结 前言 SpringBoot 集成 IBMMQ,实现两个服务间的消息通信。 一、集…...
大模型之Prompt研究和技巧
大模型之Prompt研究和技巧 大模型之Prompt编写简介组成技术Zero-ShotFew-shotCOTCOT-SCTOTGoTReAct 大模型之Prompt编写 简介 Prompt是是给 AI **模型的指令,**一个简短的文本输入,用于引导AI模型生成特定的回答或执行特定任务。 Prompt是你与语言模型沟…...
掌握Golang匿名函数
一个全面的指南,以理解和使用Golang中的匿名函数 Golang以其简单和高效而闻名,赋予开发人员各种编程范式。其中一项增强代码模块化和灵活性的功能就是匿名函数。在这篇正式的博客文章中,我们将踏上探索Golang匿名函数深度的旅程。通过真实世…...
手机 pc网站模板/线上推广方案
编一些小程序用VC6.0还是很方便的。 在VC6.0中的单步调试: 调试重要的几个键: F9在当前光标所在的行下断点,如果当前行已经有断点,则取消断点. F5调试状态运行程序,程序执行到有断点的地方会停下来. F10执行下一句话(不进入函数)step out F11执行(进…...
互联网网站开发服务合同/网上兼职外宣推广怎么做
BZOJ放这种丝帛我也是醉了... 不过来填一下求最小循环节的坑... 以这道题为例,相同文本串粘起来的串中取一小节,可以把任意一个字符看做文本串头. 那么我们一次KMP求出next函数然后显见,最后一个字符它会与上一个循环串的尾匹配,所以减一减就好啦... /* # Last modified: 2016-…...
给别人做网站收8000贵不贵/正规排名网站推广公司
在使用linux的过程中有时候会忘记root用户的密码(尤其是进行交接而文档内容不全的时候),这个时候我们就可以进入单用户模式来重置root用户密码。下面来讲解重置root密码的方式,也可以说是破解root密码的方式。系统环境:…...
诺德中心做网站/windows优化大师下载
在公司开发中,后端接口写完与前端对接的时候,肯定需要有接口文档,这里推荐一种EasyApi对接Yapi的使用,今天也是刚刚使用,写篇博客记录下。 首先在idea中下载EasyApi的插件: 安装完成之后在File->Settin…...
中航建设集团网站/seo排名查询
我的数据库中有以下表格:Questionsint:questionId(PK)varchar:questionTitleint:questionNumberint:sectionId(FK)我在Objective c中构建了几乎相同的结构化类#import interface Question : NSObject {NSInteger qId;NSString* qTitle;NSInteger qNumber;}property …...
做网站实训报告/茂名网站建设制作
文章发自http://www.cnblogs.com/hark0623/p/4167363.html 转发请注明 注意:基于CDH进行Spark开发时,使用高版本的apache原生包即可;不需要使用CDH中的spark开发包,不然会死都不知道死的。另外,其它生态项目也如此。 补…...