Android.mk 语法详解

2023-11-01

Android.mk 语法详解

转:http://blog.sina.com.cn/s/blog_602f8770010148ce.html

0. Android.mk简介:

Android.mk文件用来告知NDK Build 系统关于Source的信息。 Android.mk将是GNU Makefile的一部分,且将被Build System解析一次或多次。

所以,请尽量少的在Android.mk中声明变量,也不要假定任何东西不会在解析过程中定义。


Android.mk文件语法允许我们将Source打包成一个"modules". modules可以是:

静态库

动态库。


只有动态库可以被 install/copy到应用程序包(APK). 静态库则可以被链接入动态库。

可以在一个Android.mk中定义一个或多个modules. 也可以将同一份source 加进多个modules.


Build System帮我们处理了很多细节而不需要我们再关心。例如:你不需要在Android.mk中列出头文件和外部依赖文件。

NDK Build System自动帮我们提供这些信息。这也意味着,当用户升级NDK后,你将可以受益于新的toolchain/platform而不必再去修改Android.mk.


1. Android.mk语法:

首先看一个最简单的Android.mk的例子:

LOCAL_PATH := $(call my-dir)
 
include $(CLEAR_VARS)
 
LOCAL_MODULE    := hello-jni
LOCAL_SRC_FILES := hello-jni.c
 
include $(BUILD_SHARED_LIBRARY)

讲解如下:

LOCAL_PATH := $(call my-dir) 

每个Android.mk文件必须以定义LOCAL_PATH为开始。它用于在开发tree中查找源文件。

my-dir 则由Build System提供。返回包含Android.mk的目录路径。


include $(CLEAR_VARS) 

CLEAR_VARS 变量由Build System提供。并指向一个指定的GNU Makefile,由它负责清理很多LOCAL_xxx.

例如:LOCAL_MODULE, LOCAL_SRC_FILES, LOCAL_STATIC_LIBRARIES等等。但不清理LOCAL_PATH.

这个清理动作是必须的,因为所有的编译控制文件由同一个GNU Make解析和执行,其变量是全局的。所以清理后才能避免相互影响。


LOCAL_MODULE    := hello-jni 

LOCAL_MODULE模块必须定义,以表示Android.mk中的每一个模块。名字必须唯一且不包含空格。

Build System会自动添加适当的前缀和后缀。例如,foo,要产生动态库,则生成libfoo.so. 但请注意:如果模块名被定为:libfoo.则生成libfoo.so. 不再加前缀。


LOCAL_SRC_FILES := hello-jni.c 

LOCAL_SRC_FILES变量必须包含将要打包如模块的C/C++ 源码。

不必列出头文件,build System 会自动帮我们找出依赖文件。

缺省的C++源码的扩展名为.cpp. 也可以修改,通过LOCAL_CPP_EXTENSION。


include $(BUILD_SHARED_LIBRARY) 

BUILD_SHARED_LIBRARY:是Build System提供的一个变量,指向一个GNU Makefile Script。

它负责收集自从上次调用 include $(CLEAR_VARS)  后的所有LOCAL_XXX信息。并决定编译为什么。

 

BUILD_STATIC_LIBRARY:编译为静态库。 
BUILD_SHARED_LIBRARY :编译为动态库 
BUILD_EXECUTABLE:编译为Native C可执行程序     
  

2. NDK Build System变量:

NDK Build System 保留以下变量名:

以LOCAL_  为开头的

以PRIVATE_ ,NDK_ 或者APP_ 开头的名字。

小写字母名字:如my-dir


如果想要定义自己在Android.mk中使用的变量名,建议添加 MY_ 前缀。


2.1: NDK提供的变量:

此类GNU Make变量是NDK Build System在解析Android.mk之前就定义好了的。

2.1.1:CLEAR_VARS:

指向一个编译脚本。必须在新模块前包含之。 

include $(CLEAR_VARS)

2.1.2:BUILD_SHARED_LIBRARY

指向一个编译脚本,它收集自从上次调用 include $(CLEAR_VARS)  后的所有LOCAL_XXX信息。

并决定如何将你列出的Source编译成一个动态库。 注意,在包含此文件前,至少应该包含:LOCAL_MODULE and LOCAL_SRC_FILES 例如: 

include $(BUILD_SHARED_LIBRARY)      

2.1.3:BUILD_STATIC_LIBRARY

与前面类似,它也指向一个编译脚本,

收集自从上次调用 include $(CLEAR_VARS)  后的所有LOCAL_XXX信息。

并决定如何将你列出的Source编译成一个静态库。 静态库不能够加入到Project 或者APK中。但它可以用来生成动态库。

LOCAL_STATIC_LIBRARIES and LOCAL_WHOLE_STATIC_LIBRARIES将描述之。    
include $(BUILD_STATIC_LIBRARY) 

2.1.4: BUILD_EXECUTABLE: 
与前面类似,它也指向一个编译脚本,收集自从上次调用 include $(CLEAR_VARS)  后的所有LOCAL_XXX信息。
并决定如何将你列出的Source编译成一个可执行Native程序。
include $(BUILD_EXECUTABLE) 

2.1.5:PREBUILT_SHARED_LIBRARY:
把这个共享库声明为 “一个” 独立的模块。

指向一个build 脚本,用来指定一个预先编译好多动态库。 与BUILD_SHARED_LIBRARY and BUILD_STATIC_LIBRARY不同,

此时模块的LOCAL_SRC_FILES应该被指定为一个预先编译好的动态库,而非source file.  LOCAL_PATH := $(call my-dir)
    
include $(CLEAR_VARS)
LOCAL_MODULE := foo-prebuilt     # 模块名
LOCAL_SRC_FILES := libfoo.so     # 模块的文件路径(相对于 LOCAL_PATH)
    
include $(PREBUILT_SHARED_LIBRARY) # 注意这里不是 BUILD_SHARED_LIBRARY

这个共享库将被拷贝到 $PROJECT/obj/local 和 $PROJECT/libs/<abi> (stripped)  主要是用在将已经编译好的第三方库

使用在本Android Project中。为什么不直接将其COPY到libs/armabi目录呢?因为这样做缺陷很多。下一节再详细说明。

2.1.6: PREBUILT_STATIC_LIBRARY: 预先编译的静态库。 同上。


2.1.7: TARGET_ARCH: 目标CPU架构名。如果为 “arm” 则声称ARM兼容的指令。与CPU架构版本无关。


2.1.8: TARGET_PLATFORM:  目标平台的名字。


2.1.9:TARGET_ARCH_ABI

Name of the target CPU+ABI  
armeabi For ARMv5TE  armeabi-v7a
2.1.10:TARGET_ABI

2.2: NDK提供的功能宏:
GNU Make 提供的功能宏,只有通过类似: $(call function)   的方式来得到其值,它将返回文本化的信息。

2.2.1: my-dir: $(call my-dir):
返回最近一次include的Makefile的路径。通常返回Android.mk所在的路径。它用来作为Android.mk的开头来定义LOCAL_PATH.
LOCAL_PATH := $(call my-dir) 
请注意:返回的是最近一次include的Makefile的路径。所以在Include其它Makefile后,再调用$(call my-dir)会返回其它Android.mk 所在路径。   例如:  
LOCAL_PATH := $(call my-dir)   ... declare one module   include $(LOCAL_PATH)/foo/Android.mk   LOCAL_PATH := $(call my-dir)   ... declare another module
则第二次返回的LOCAL_PATH 为:$PATH/foo。 而非$PATH.   


2.2.2: all-subdir-makefiles:
返回一个列表,包含'my-dir'中所有子目录中的Android.mk。
例如: 结构如下:
sources/foo/Android.mk   sources/foo/lib1/Android.mk   sources/foo/lib2/Android.mk 
If sources/foo/Android.mk 中, include $(call all-subdir-makefiles)  那则自动include 了sources/foo/lib1/Android.mk and sources/foo/lib2/Android.mk。

2.2.3:this-makefile
当前Makefile的路径。

2.2.4:
parent-makefile
返回include tree中父Makefile 路径。 也就是include 当前Makefile的Makefile Path。

2.2.5:import-module
允许寻找并inport其它modules到本Android.mk中来。 它会从NDK_MODULE_PATH寻找指定的模块名。
$(call import-module,<name>)
2.3: 模块描述变量: 
此类变量用来给Build System描述模块信息。在'include $(CLEAR_VARS)' 和 'include $(BUILD_XXXXX)'之间。必须定义此类变量。
include $(CLEAR_VARS) script用来清空这些变量。   
 
include $(BUILD_XXXXX)收集和使用这些变量。    

2.3.1: LOCAL_PATH
这个值用来给定当前目录。必须在Android.mk的开是位置定义之。
例如:
LOCAL_PATH := $(call my-dir) LOCAL_PATH不会被include $(CLEAR_VARS) 清理。

2.3.2: LOCAL_MODULE
modules名。在include $(BUILD_XXXXX)之前,必须定义这个变量。此变量必须唯一且不能有空格。
通常,由此变量名决定最终生成的目标文件名。

2.3.3: LOCAL_MODULE_FILENAME:
可选。用来override LOCAL_MODULE. 即允许用户重新定义最终生成的目标文件名。
LOCAL_MODULE := foo-version-1  LOCAL_MODULE_FILENAME := libfoo
2.3.4:LOCAL_SRC_FILES
为Build Modules而提供的Source 文件列表。不需要列出依赖文件。 注意:文件相对于LOCAL_PATH存放,
且可以提供相对路径。 例如:
LOCAL_SRC_FILES := foo.c               \ toto/bar.c
2.3.5: LOCAL_CPP_EXTENSION: 
指出C++ 扩展名。(可选)
LOCAL_CPP_EXTENSION := .cxx 从NDK R7后,可以写多个:  
LOCAL_CPP_EXTENSION := .cxx .cpp .cc      

2.3.6:LOCAL_CPP_FEATURES
可选。用来指定C++ features。
LOCAL_CPP_FEATURES := rtti  
LOCAL_CPP_FEATURES := exceptions

 

2.3.7:LOCAL_C_INCLUDES
一个可选的path列表。相对于NDK ROOT 目录。编译时,将会把这些目录附上。
LOCAL_C_INCLUDES := sources/foo  LOCAL_C_INCLUDES := $(LOCAL_PATH)/../foo
2.3.8: LOCAL_CFLAGS:
一个可选的设置,在编译C/C++ source 时添加如Flags。
用来附加编译选项。 注意:不要尝试在此处修改编译的优化选项和Debug等级。它会通过您Application.mk中的信息自动指定。
也可以指定include 目录通过:LOCAL_CFLAGS += -I<path>。 这个方法比使用LOCAL_C_INCLUDES要好。因为这样也可以被ndk-debug使用。

2.3.9: LOCAL_CXXFLAGS
LOCAL_CPPFLAGS的别名。          
2.3.10: LOCAL_CPPFLAGS
C++ Source 编译时添加的C Flags。这些Flags将出现在LOCAL_CFLAGS flags 的后面


2.3.11: LOCAL_STATIC_LIBRARIES:
要链接到本模块的静态库list。(built with BUILD_STATIC_LIBRARY)


2.3.12: LOCAL_SHARED_LIBRARIES
要链接到本模块的动态库。


2.3.13:LOCAL_WHOLE_STATIC_LIBRARIES

静态库全链接。 不同于LOCAL_STATIC_LIBRARIES,类似于使用--whole-archive

2.3.14:LOCAL_LDLIBS 

linker flags。 可以用它来添加系统库。 如 -lz: 
LOCAL_LDLIBS := -lz   

2.3.15: LOCAL_ALLOW_UNDEFINED_SYMBOLS:

2.3.16: LOCAL_ARM_MODE
缺省模式下,ARM目标代码被编译为thumb模式。每个指令16位。如果指定此变量为:arm。 则指令为32位。
LOCAL_ARM_MODE := arm   其实也可以指定某一个或者某几个文件的ARM指令模式。  
2.3.17: LOCAL_ARM_NEON
设置为true时,会讲浮点编译成neon指令。这会极大地加快浮点运算(前提是硬件支持)
只有targeting 为 'armeabi-v7a'时才可以。

2.3.18:LOCAL_DISABLE_NO_EXECUTE

2.3.19: LOCAL_EXPORT_CFLAGS:
定义这个变量用来记录C/C++编译器标志集合,
并且会被添加到其他任何以LOCAL_STATIC_LIBRARIES和LOCAL_SHARED_LIBRARIES的模块的LOCAL_CFLAGS定义中 
LOCAL_SRC_FILES := foo.c bar.c.arm 
注意:此处NDK版本为NDK R7C.(不同NDK版本,ndk-build所产生的Makefile并不完全相同 
============================================================================
其他一些有关mk文件资料:
1.Android JNI入门第四篇——Android.mk文件分析:http://blog.csdn.net/xyz_lmn/article/details/6966259
2.android编译系统makefile(Android.mk)写法:http://www.cnblogs.com/hesiming/archive/2011/03/15/1984444.html
3.android makefile(android.mk)分析(序):http://blog.csdn.net/chief1985/article/details/4699831
4.Android.mk的用法和基础:http://blog.csdn.net/zhandoushi1982/article/details/5316669
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Android.mk 语法详解 的相关文章

  • 为什么 cordova.file.documentsDirectory 为空?

    我正在尝试使用 cordova plugin file transfer 在http ngcordova com docs plugins fileTransfer http ngcordova com docs plugins fileT
  • BLE 外设支持 Android-L 示例 [关闭]

    Closed 这个问题需要调试细节 help minimal reproducible example 目前不接受答案 我希望有一个适用于 Android L 的 BLE 外设模式的示例 我的代码给了我奇怪的错误 即广告商太多 这没有任何意
  • 处理 Android 锁屏上的音量变化?

    我想做的是 能够在 android 4 4 上的锁屏上捕获音量增大 减小按钮操作 Google Cast 设计清单 https developers google com cast docs design checklist sender
  • Android向后兼容技术

    我现在在开发基于最新 API 15 ICS 的 15 项活动 Android 应用程序方面取得了进展 现在我发现应用程序的主要功能主义者即使支持 android v4 也不向后兼容 例如 1 fragment事务动画 2 将StringSe
  • Android Facebook sdk 3.5 分享对话框

    您好 我正在为 android sdk 3 5 实现 facebook 共享对话框 但是我按照指南没有取得任何成功 FacebookDialog shareDialog new FacebookDialog ShareDialogBuild
  • 如何忽略 LeakCanary 中的某些类?

    有人能给我一个如何忽略 LeakCanary 中的某些类的有效示例吗 我正在查看这个示例 以忽略 LeakCanary 中第三方库中的某些类 但我不知道将其放在应用程序中的何处 我把它放在我的应用程序类中 但这些变量和方法有错误 isInA
  • FLAG_ACTIVITY_REORDER_TO_FRONT 被忽略

    我有一个包含项目列表的 FragmentActivity 当应用程序处于后台时 可以推送该项目列表 发生这种情况时 我想创建一个状态栏通知并提醒用户更新 当用户单击通知时 活动应重新排序到前面并显示在屏幕上 同时在列表底部显示新项目 所以我
  • Android 8.1 中 Activity 自行旋转并恢复正常

    我的应用程序在所有 Android 版本上运行良好 但我注意到在 Android 8 1 0 Oreo 中 当我将屏幕从纵向活动转到横向活动时 以及当我按后退按钮时 它会显示异常行为 屏幕自动从横向旋转并恢复正常 看起来 Activity
  • Android 谷歌地图 V2 已停止

    我正在尝试构建地图应用程序并关注这个链接 https blog emildesign rhcloud com p 435一步步 我在这里找到了类似的主题 但对我没有帮助 我想显示地图 但是当我运行它时 它返回强制关闭和我的 Android
  • 在后台服务中持续获取位置更新

    我正在开发需要在后台服务中持续获取位置更新的应用程序 我已经使用了它正在使用的后台粘性服务 但是 即使我添加了启动广播并在那里启动了服务 启动完成后服务也没有启动 服务启动并立即被杀死 另外 这不适用于奥利奥 服务在应用程序关闭几分钟后停止
  • 将图像保存到内部存储器并将出现在图库中

    我搜索了很多与我的问题相关的问题 是否有办法将图像存储在内存中并且它也应该出现在图库中 这是完全有可能的 我以前也这么做过 在将图像保存到内存 或称为应用程序文件夹等 之前 您最好设置Context MODE WORLDREADABLE 虽
  • 如何在Android网格视图中设置单元格大小?

    我正在尝试为应用程序制作一个带有大图标的网格视图 但我找不到任何有关修改 Android 上网格布局上的单元格大小的教程 有人可以给我一个例子或相关链接吗 Thanks 就像另一个一样适配器视图 http developer android
  • 使用 UPI url 调用 PSP 应用程序

    我正在尝试创建一个商家应用程序 它将根据 NPCI 的指南生成一个 url 此 url 将作为意图共享 并且 PSP 应用程序 任何注册的银行应用程序 应该能够侦听该 url 并被调用 我已经形成了这样的网址 upi pay pa icic
  • 有没有办法在多个嵌套的 RecyclerView 之间共享同一个 LayoutManager

    我正在开发一个显示游戏列表的应用程序 在每个游戏的 itemView 内 我还有一个要显示的视频列表 预览和结构如下 我部署了一个RecyclerView作为窗口根视图 然后对于视频 我使用网格样式的RecyclerView来显示 所以这里
  • SDK尚未初始化,请务必先调用FacebookSdk.sdkInitialize()

    我在实现 Facebook SDK 时遇到此错误 并且我tried https stackoverflow com questions 15490399 error inflating class com facebook widget l
  • 如何在 onDraw() 方法中定义与像素无关的高度

    我扩展了 View 来构建自定义小部件 我想用独立的像素单位定义小部件的高度 我认为可以通过将像素密度乘以所需的高度来完成 但我不知道该怎么做 到目前为止我所拥有的 最小化 public class Timeline extends Vie
  • Android复杂布局线性和相对

    I have to implement a layout like shown in the diagram and I do not know the best combination to achieve the required de
  • 如何通过 AppCompatActivity 使用 YouTube Android 播放器 API

    为了在我的应用程序中播放视频 我决定扩展 YouTube Android Player API 但问题是我的菜单消失了 因为我没有从 AppCompatActivity 扩展 问题是 如何使用 YouTube Android Player
  • 动态创建 JSON 对象

    我正在尝试使用以下格式创建 JSON 对象 tableID 1 price 53 payment cash quantity 3 products ID 1 quantity 1 ID 3 quantity 2 我知道如何使用 JSONOb
  • 改造方法调用可能会产生“java.lang.NullPointerException”

    使用 Retrofit 2 3 0 我在 Android Studio 中收到以下消息 有关如何删除此 IDE 错误消息的任何建议 谢谢 来自Response文档 http square github io retrofit 2 x ret

随机推荐

  • 设置EntityFramework中decimal类型数据精度问题(EF默认将只会保留到2为精度)

    原文 设置EntityFramework中decimal类型数据精度 EF中默认的decimal数据精度为两位数 当我们数据库设置的精度大于2时 EF将只会保留到2为精度 e g 2 19990将会被保存为2 20 1 解决方案一是网上找到
  • js作用域、闭包和浏览器渲染原理

    一 js作用域 变量的作用域是指变量在整个程序中作用 可访问 的范围 1 作用域的类型 三个类型 全局作用域 局部作用域 函数作用域 块级作用域 ES6新增 1 全局作用域 如果一个变量为全局作用域 那么这个变量在程序的任意位置都可以访问
  • 主流显卡Linux系统驱动安装--intel、ATi篇

    Intel 集成显卡的Linux驱动安装 目前使用Intel 集成显卡的计算机主要集中在中低端商务台式机和中低端笔记本电脑 这里介绍一下Linux下显卡驱动安装方法 I ntel针对集成显示芯片提供了两种驱动程序 i915Graphics和
  • BigInteger和BigDecimal的使用

    1 BigInteger类的常用方法 java math BigInteger类表示一个超大的整数 而且支持任意精度整数的四则运算 加减乘除 常用方法 方法 含义 public BigInteger String val 将 BigInte
  • 模型与动画作业

    一 智能巡逻兵 游戏设计要求 创建一个地图和若干巡逻兵 使用动画 每个巡逻兵走一个3 5个边的凸多边型 位置数据是相对地址 即每次确定下一个目标位置 用自己当前位置为原点计算 巡逻兵碰撞到障碍物 则会自动选下一个点为目标 巡逻兵在设定范围内
  • canvas正交坐标系旋转--监听滚轮

    canvas 简单学习canvas 功能实现 效果 简单学习canvas
  • Java读取excel的方式,一篇文章看懂(详细)

    目录 一 excel读取的两种方式 1 1 jxl 和 poi 的区别和选择 二 jxl 的使用 2 1 导入相关依赖 2 2 操作 三 poi 的使用 3 1 导入相关依赖 3 2 操作 四 总结 一 excel读取的两种方式 Java中
  • Java 简单控制台项目之家庭记账本 --- 凌宸1642

    项目一 家庭记账本 模拟实现一个基于文本界面的 模拟实现一个基于文本界面的 家庭记账软件 家庭记账软件 主要涉及以下知识点 变量的定义 基本数据类型的使用 循环语句 分支语句 方法声明 调用和返回值的接收 简单的屏幕输出格式控制 该软件能够
  • Oracle VM Virtualbox虚拟机教程

    Oracle Virtualbox的下载 我们使用不太操作系统的电脑来运行不同的功能和应用 常见的操作系统有Windows MacOS Linux Crome等等 通常我们在电脑上安装一个系统就不动了 当然也有双系统 但是比较麻烦 废时费力
  • proteus中的标签的使用方法。

    我们在proteus中绘制原理图的时候常常会遇到元器件的连线比较繁杂 导致原理图看起来比较乱 或者不是太好看 我们一般采用两种比较典型的方式来解决 一 标签 1 终端模式下的标签 终端模式下的标签须确保我们已经选择了终端模式 如下图 双击终
  • 使用Flask-Migrate迁移数据库

    1 安装 pipenv install flask migrate from flask import Flask from flask sqlalchemy import SQLAlchemy from flask migrate imp
  • static作用(修饰函数、局部变量、全局变量)

    转载自 http www cnblogs com stoneJin archive 2011 09 21 2183313 html 在C语言中 static的字面意思很容易把我们导入歧途 其实它的作用有三条 1 先来介绍它的第一条也是最重要
  • C++面试题:虚函数(virtual)可以是内联函数(inline)吗?

    原文链接 https github com huihut interview 答案 虚函数可以是内联函数 内联是可以修饰虚函数的 但是当虚函数表现多态性的时候不能内联 理由如下 内联是在发生在编译期间 编译器会自主选择内联 而虚函数的多态性
  • python 通过文件头获取文件类型mimetype

    一 MIME Type是什么 资源的媒体类型 MIME Multipurpose Internet Mail Extensions 多用途互联网邮件扩展类型 是设定某种扩展名的文件用一种应用程序打开的方式类型 当该扩展名文件被访问时 浏览器
  • 设计模式——代理模式

    代理模式概述 代理模式是Java开发中使用较多的一种设计模式 代理设计就是为其他对象提供一种代理以控制对这个对象的访问 代理类似中介的身份 应用场景 安全代理 屏蔽对真实角色的直接访问 远程代理 通过代理类处理远程方法调用 RMI 延迟加载
  • 调试HX711

    体重电路板HX711 1 下载程序 如果不正常用万用表测量输出电压是否正常 看BOOT键是否打开 RX TX是否接对 2 首先确保程序正确 I O口对应正确 3 连接体重计 如果串口接收数据不正常 首先检查称重传感器连线问题 然后用万用表测
  • Linux入门笔记-尚硅谷韩顺平-基础篇&实操篇

    文章目录 课程导论 基础篇 Linux入门 Linux介绍 Linux和Unix的关系 Linux和Windows比较 基础篇 Linux的目录结构 基本介绍 具体的目录结构 实操篇 vi和vim的使用 vi和vim的基本介绍 vi和vim
  • 节点编译问题 | FISCO BCOS开发问题排查

    1 源码编译慢 1 1 case1 先前没有编译过源码 修改 etc hosts文件 添加如下内容可加速依赖包的下载 140 82 113 4 github com 185 199 108 153 assets cdn github com
  • 【科普贴】SIM卡接口协议(ISO7816-3)详解

    一 SIM卡介绍 SIM Subscriber Identity Module 卡是GSM系统的移动用户所持有的IC卡 称为身份识别卡 SIM卡内部含有微处理器 它由CPU 8位 RAM 工作存储器 6 16KB ROM 程序存储器 3 8
  • Android.mk 语法详解

    Android mk 语法详解 转 http blog sina com cn s blog 602f8770010148ce html 0 Android mk简介 Android mk文件用来告知NDK Build 系统关于Source