尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
【android】Application.mk的文件梳理
Application.mk的简要概述Application.mk是用来描述你的工程下的native模块的一般是个Android.mk放在同目录下即你的jni文件夹下。通常还有另外一种方式但是使用起来比较麻烦而且兼容性也没有很好就不在这里进行介绍了。那么问题来了Application.mk到底有什么用呢Application.mk是用来描述你的应用程序需要哪些模块以及这些模块所要具有的一些特性。而相对的Android.mk是用来描述要编译某个具体的模块所需要的一些资源包括要编译的源码、要链接的库等等。Application.mk所要描述的内容主要包括1你程序正常运行所需要到模块的具体列表2程序要编译成什么机器指令集的3所有模块要被编译成Release版本还是Debug版本的4传递给C或者C编译器的编译参数。Application.mk文件一般是放在**PROJECT/jni/∗∗目录下的PROJECT/jni/ **目录下的PROJECT/jni/∗∗目录下的PROJECT代表你所写程序的项目目录这样ndk-build命令可以自动搜索到它。当然Application.mk文件其实是可选的。默认情况下如果ndk-build命令找不到Application.mk文件的话就会使用如下规则进行编译1会编译全部在android.mk文件中列出的模块2对于所有模块NDK编译系统会根据“armeabi” ABI来生成机器代码即指令集是ARMv5TE。具体来说Application.mk文件中可以包含对下面几个变量的定义APP_PROJECT_PATH这个变量会告诉编译系统你应用程序项目的根目录的绝对路径。这用于指定JNI生成的.so文件安装路径或拷贝路径一般编译出来的Native模块是要被打包成某个APK应用程序的。而APK打包工具都是在项目根目录下的某个特定子目录中搜索有没有要打包的.so文件的所以指定了项目根目录的绝对路径后ndk-build命令在完成编译后会将编译好的.so模块文件拷贝到项目的特定子目录下方便后面打包。如果你的项目目录的组织形式是类似于**$PROJECT/jni/Application.mk**则这个变量是可选的。一般按照开头叙述的方法这个变量是不用显式的写出来的。APP_MODULES这个变量是可选的。如果APP_MODULES变量没有被定义的话NDK将编译在Android.mk文件中定义的所有模块以及所有其包含的子MakeFile文件。如果APP_MODULES变量被定义了的话则NDK只会编译明确列出的这几个模块。注意所有模块的名字要以空格分割并且NDK会自动计算每个模块之间的依赖关系。另外从NDK r4开始改变了这个变量的行为。在这个版本之前Application.mk中必须定义这个变量即其是强制的并且必须明确列出所有模块的名字列表。而在这个版本之后取消了这个限制。现在LZ用的ndk-r11所以并木有这个烦恼APP_OPTIM优化选项这个变量是可选的可以被定义成“release”或debug用来告诉NDK将所有的模块编译成Release版本还是Debug版本。比变量用来修改优先等级默认是Release版本。如果这个变量被定义成“release”的话则NDK会将所有模块编译成Release版本的也就是会对代码进行深度优化并且去除所有调试信息。这样的结果就是编译出的代码执行效率高且文件比较小但不利于调试。如果这个变量被定义成“debug”的话则NDK会将所有模块编译成Debug版本的和Release版本相反不会对代码进行任何优化并且会加上很多调试信息。这样的结果就是编译出的代码执行效率比较低且文件相对较大但调试起来很方便。如果没有特别指定这个变量则NDK会自动查看你的应用程序是否是可调试的即查看你项目目录下的AndroidManifest.xml文件看是否在****标签中是否将android:debuggable属性设置成了true来决定到底编译Release版本还是Debug版本的。但是如果你定义了这个变量的话则以这个变量定义的情况为准。无论你的应用程序是否是可调试的都不会产生影响。APP_CFLAGS如果想在编译所有模块的C或者C源码时都需要指定一些特殊的编译选项的话可以通过定义这个变量实现。在Android.mk文件中也可以分别为每个模块指定特定于这个模块的编译选项。但是如果在Application.mk文件中定义了这个变量的话其作用域是所有模块而不是某个特定的模块。比如你要编译的某几个模块如果都需要在一个特定目录下搜索头文件定义的话你可以有两种做法。一是修改各个模块的Android.mk文件为每个模块都定义LOCAL_CFLAGS变量包含那个目录二是只修改应用程序的Application.mk文件定义APP_CFLAGS变量包含那个目录。还要注意一个问题既然这个变量的作用域是所有模块那么如果有些模块源文件时C代码是会出现warning虽然编译也能通过但是在影响视觉效果以及强迫症患者看到会崩溃的所以为了分好每个模块化建议还是在Angroid.mk中对每个模块都单独指定好。注意在Android NDK 1.5 r1版中这个变量只会对编译C源文件起作用而对编译C源文件没有任何影响。这个问题已经在后面的NDK版本中得到了纠正。APP_CPPFLAGS和前面说明的APP_CFLAGS变量类似它也是用来指定一些特殊的编译选项但只对编译C源文件其作用。注意在Android NDK 1.5 r1版本中这个变量不仅对C源文件的编译而且对C源文件的编译都会起作用。这个问题已经在后面的NDK版本中得到了纠正。现在如果想对编译C和C源文件都指定相同的编译选项可以使用前面介绍的APP_CFLAGS变量。APP_CXXFLAGS它是APP_CPPFLAGS变量的一个别名但它已经过时了在未来的NDK版本中有可能不再使用。因此建议尽量不要使用它而是使用APP_CPPFLAGS变量。APP_BUILD_SCRIPT默认情况下NDK编译系统会自动在$(APP_PROJECT_PATH)/jni目录下寻找名为Android.mk文件作为模块定义文件。如果你的Android.mk文件被放到别的位置的话或者甚至你的模块定义文件不叫Android.mk则可以通过修改这个变量的值来让NDK使用你指定的模块定义文件。注意一个非绝对路径总是会被解释为相对于NDK顶层目录的路径。APP_ABI默认情况下NDK编译系统会根据“armeabi” ABI来生成机器代码即一个使用ARMv5TE指令集并且支持软件浮点操作的CPU。你可以通过定义APP_ABI变量来选择一个不同的ABI。比如如果你的程序想在使用ARMv7指令集且支持硬件FPU的设备上运行可以使用APP_ABI : armeabi-v7a或者你的程序想支持IA-32指令集可以使用APP_ABI : x86或者你的程序想支持MIPS指令集可以使用APP_ABI : mips或者想同时支持这四种平台可以使用APP_ABI : armeabi armeabi-v7a x86 mips当然你也可以使用任意某几个ABI只要每个ABI之间用空格隔开即可。或者如果你使用NDK r7以上版本的话还可以使用“all”来表示支持所有ABI平台APP_ABI : allAPP_STL默认情况下NDK编译系统只为最小的C运行时库/system/lib/libstdc.so提供C头文件。然而NDK还带有其它一些可选的C运行时库的实现你可以选择在你自己的应用程序中通过在Application.mk中定义APP_STL变量来使用或链接其中某一个。这个变量可以被设置成如下几个值1system2gabi_static3gabi_shared4stlport_static5stlport_shared6gnustl_static7gnustl_shared如果不特别定义的话“system”运行时库是默认的值。除此之外凡是后面带“_static”的表示其是一个静态链接的运行时库运行时库的代码包含在编译后的程序中而凡是后面带“_shared”的表示其是一个动态链接的运行时库运行时库在程序运行时被动态加载进来。如果去除动态或静态链接的因素则除了默认的“system”运行时库之外还有所谓的“gabi”运行时库、“stlport”运行时库和“gunstl”运行时库。这四种运行时库所支持的C特性各不相同总结如下表C异常CRTTIC标准库System不支持不支持不支持gabi不支持支持不支持stlport不支持支持支持gnustl支持支持支持可以看出如果想支持C异常的话必须要使用gunstl运行时库。APP_GNUSTL_FORCE_CPP_FEATURES在NDK r7b之前的版本中如果指定使用了gnustl运行时库则默认在编译之后的代码中都会加上对C异常和C RTTI的支持代码。这样做有可能会造成一定的问题。并且即使你的程序没有使用C异常和C RTTI这些特性支持它们的代码还是会加到你的模块中去这样会大大增加模块的大小。这个问题已经在NDK r7b及以后的版本中被修复了。不过这样也就意味着如果你真的需要使用C异常或C RTTI特性的话必须明确的告知NDK编译系统可以通过在Application.mk中定义APP_CPPFLAGS变量或在Android.mk中定义LOCAL_CPPFLAGS或LOCAL_CPP_FEATURES变量来告知。但是这样带来的问题就是兼容性问题同一个编译脚本要根据不同的NDK版本来做区分操作。为了让这种过度更加的顺畅可以在Application.mk文件中定义APP_GNUSTL_CPP_FEATURES变量来指定到底要支持哪些C的特性。这个变量可以被设置成如下两个值1exceptions表示编译后的代码要支持C异常特性2rtti表示编译后的代码要支持C RTTI特性。例如如果你想让你的程序既获得C异常的支持也得到C RTTI的支持可以使用APP_GNUSTL_FORCE_CPP_FEATURES : exceptions rtti(o)/~总算完成了♪(∇*)参考博客http://blog.csdn.net/roland_sun/article/details/46318893
RELATED

相关推荐

Rust正成为AI基础设施的底层新标准

Rust正成为AI基础设施的底层新标准

1. 项目概述:这不是技术风向标,而是基建层的静默迁移“3个信号:AI基建正在转向Rust”——这句话最近在多个技术社区高频出现,但很多人读完标题只留下模糊印象:哦,Rust又火了?AI圈开始用Rust了&a…

📅 2026/10/23 0:01:14
Rust为何成为AI基础设施的确定性选择

Rust为何成为AI基础设施的确定性选择

1. 这不是技术风潮,是基建层的静默迁移最近在几个核心开源项目的更新日志里反复看到同一个现象:原本用Go写的CLI工具,新版本悄悄换成了Rust;某知名云原生中间件的v2.0架构图里,底层数据平面模块标注着“Rust重写中”&a…

📅 2026/10/23 0:01:14
FreeRTOS任务通知实战详解:内核原理、API与避坑指南

FreeRTOS任务通知实战详解:内核原理、API与避坑指南

裸机编程切到RTOS之后,任务之间的通信和同步永远是躲不开的坎。前面聊过队列、信号量、互斥锁、事件组,这次把FreeRTOS任务通知(Task Notification)单独拎出来讲透。原因很简单:任务通知是FreeRTOS里最容易用错、也最容…

📅 2026/10/23 0:01:14
MORE NEWS

更多资讯

📰

直播美颜SDK性能优化全解析:架构、算法与踩坑实录

开篇先聊一个很现实的问题:直播场景下的美颜 SDK,和拍照修图里的美颜,看起来都是“把人变好看”,但技术选型几乎完全是两条路。拍照可以离线慢慢算,一张图处理几百毫秒用户都不觉得慢;直播是 30 帧每秒连续…

📰

RAG检索优化实战:分块、混合召回与重排核心方案

做 RAG 这行当,demo 阶段人人都觉得“已经成了”,真正上线跑一两周,才会撞见那个经典场面:模型能力没问题,prompt 也调了十几版,可用户一问到具体业务,回复要么“抱歉,我没有找到相关…

📰

大模型Agent开发全流程:模型选型、工具设计、护栏与编排

“真香警告”这四个字放在标题里,是有原因的。我一开始对Agent这类项目是持谨慎态度的,觉得无非是把模型调用包装得更花哨了一些,大概率又是概念大于实用。直到我亲手把一个会调外部工具、能分步骤干活、出错了还能自我修正的小东西跑起来之后…

📰

SDFT:缓解灾难性遗忘的选择性微调方法,从核心设计到落地实践

如果你经常微调模型,一定遇到过这种场景:模型在第一个任务上学得很好,准确率已经稳定了,然后你用第二批数据让它学习新技能,训练完成后新任务的表现上去了,但回过去一测旧任务,效果明显下滑。我…

📰

模型越强越需要人:Human in the loop落地指南

Human in the loop 人在回路中,这个概念在我第一次做大型语言模型项目的时候还不太被当回事。当时团队里很多人的想法是:模型已经这么强了,把人的反馈接进来,不是拖慢效率吗?但实际跑了几轮之后,所有人都不…

📰

融合DWA与速度障碍法的移动机器人动态避障实践

我们做移动机器人底盘导航调试那几年,最头疼的从来不是静态地图上的路径规划,而是动态障碍物。明明全局路径规划得好好的,车一开起来,碰到行人横穿、其他机器人迎面过来,传统的动态窗口法(DWA)经…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬