Android.mk文件详解(转)
从对Makefile一无所知开始,折腾了一个多星期,终于对Android.mk有了一个全面些的了解。了解了标准的Makefile后,发现Android.mk其实是把真正的Makefile包装起来,做成了一个对使用者来说很简单的东西。使用它来编译程序时,不管是动态库、可执行的二进制文件,还是Jar库、APK包,只要沿着一个简单的思路来做三大步就可以了:清除旧变量,设置新变量,调用编译函数。
明白了以后,发现Makefile语法不是问题,有很多教程和高手。编译模块时如何清除变量、调用编译函数等也不是问题,源码当中无处不在这样的例子。而对初学者来说,更需要明白的可能是,Android如何让使用脚本的人从Makefile语法当中解放出来,简单地按照上面的三大步就可以编译出任何模块。
拿AlarmClock来做例子的话:
//清除旧变量
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
//设置新变量
LOCAL_SRC_FILES := $(call all-subdir-java-files)
LOCAL_PACKAGE_NAME := AlarmClock
//调用编译函数
include $(BUILD_PACKAGE)
下面简单解释一下这三步:
1、清除旧变量,是因为Android.mk中所有的变量都是全局的,编译函数在编译时会调用这些变量。为了防止编译函数使用了编译其它模块时设置的变量,每次开始编译一个新的模块时清除所有的变量是个好习惯。
2、设置新变量就是把本次编译时用到的源码地址,包名等设置好。
3、调用编译函数其实就是include一个固定的mk文件,这个mk文件会根据设置的变量提取出编译模块需要的target,Command等信息并执行固定的编译命令。
看明白Android.mk后,最深的感受还是Android的这种封装思想,让我想起了很多以前没有思考过的东西。呵。。。
我会一些个人的理解记录Android一步步地演化出这种封装思想。真诚地欢迎批评指正。
Makefile这个东西,往最简单处说,就是这样的模式:
目标:信赖文件
执行命令
这里暂不考虑它的语法细节,举个不完整的例子,就是这样的:
AlarmClock.apk:AlarmClock.java
javac AlarmClock.java
java AlarmClock.class
要生成AlarmClock.apk,就需要AlarmClock.java这个信赖文件,然后执行后面两行的两个命令。假如我们简单粗暴地用这种写法去编译Android系统的话,会相当累。Android.mk就很巧妙地把它们进行了抽象。我们现在来模拟一下:
定义三个变量target,source,command,分别代表编译目标、信赖文件和编译命令,就成了这样:
$(target):$(source)
$(command)
这三个变量的值分别是:
target := AlarmClock.apk
source := AlarmClock.java
commnd := /
javac AlarmClock.java/
java AlarmClock.class
这样的话,在编译每个APK时,只要分别给target、source、command赋值,然后再这样写就可以了:
$(target):$(source)
$(command)
嗯,还是有点儿麻烦,那再抽象一次。定义一个变量name,让它存放要编译的模块的名字:
name := AlarmClock
然后再更改一下前面的三个变量:
target := $(name).apk
source := $(name).java
commnd := /
javac $(name).java/
java $(name).class
现在要编译一个模块Contacts需要做些什么呢?
name := Contacts
$(target):$(source)
$(command)
三行代码就可以了,很简单,对吧?但后面两行还是每次都要写,那再抽象。把后面两行放到一个build_apk.mk文件当中。然后定义一个变量:
BUILD_PACKAGES := build_apk.mk
全部完了,这回编译一个模块Contacts时只要这样做就可以了:
name := Contacts
include $(BUILD_PACKAGES)
一个不够复杂,那就多点儿:
name := Contacts
include $(BUILD_PACKAGES)
name := Phone
include $(BUILD_PACKAGES)
name := Email
include $(BUILD_PACKAGES)
//================强壮的分隔线=========
现在我们来完善一下上面的过程,把它系统化。
定义一个专门用来清除变量的clear_vars.mk里面的内容如下:
name :=
target :=
source :=
command :=
再定义一个变量CLEAR_VARS := clear_vars.mk。上面的编译脚本就变成了这样:
include $(CLEAR_VARS)
name := Contacts
include $(BUILD_PACKAGES)
include $(CLEAR_VARS)
name := Phone
include $(BUILD_PACKAGES)
include $(CLEAR_VARS)
name := Email
include $(BUILD_PACKAGES)
这回,清除旧变量、设置新变量、调用编译函数三大步全都有了。
好了,现在我们进入到Android源码的build/core/目录下。先看其中的main.mk,config.mk这两个文件。
main.mk里面是具体的脚本,在这里控制编译模块。
config.mk中定义了下面这样的文件调用:
CLEAR_VARS:= $(BUILD_SYSTEM)/clear_vars.mk
BUILD_HOST_STATIC_LIBRARY:= $(BUILD_SYSTEM)/host_static_library.mk
编译模块时,每一个include其实都是一次功能调用,或者对mk文件的调用,或者对变量和函数的调用。做为单独的功能模块抽象出来的mk文件都在build/core/目录下,而函数的定义全部在definitions.mk中。
万事开头难,有了上面的思路,再看这些脚本就很简单了。一路顺风,呵。。。
Android.mk文件详解(转)的更多相关文章
- Android编译系统(Android.mk文件详解)
[Android-NDK(Native Development Kit) docs文档] NDK提供了一系列的工具,帮助开发者快速开发C(或C++)的动态库,并能自动将so和java应用一起打包成a ...
- Android.mk文件和Application.mk文件详解
Android.mk文件和Application.mk文件详解 相同点:都是轻量级 Makefile(Makefile文件定义一些列指令,指定文件编译顺序,类似shell脚本) Application ...
- Android.mk用法详解
一.Android.mk介绍 Android.mk是Android提供的一种makefile文件,用来指定诸如编译生成so库名.引用的头文件目录.需要编译的.c/.cpp文件和.a静态库文件等.要掌握 ...
- NDK开发之Application.mk文件详解
做过NDK开发的同学应该都知道有个Application.mk文件,这是android NDK构建系统使用的一个可选构建文件.它的目的是描述应用程序需要哪些模块,也定义了所有模块的一些通用变量.主要有 ...
- Android清单文件详解(三)----应用程序的根节点<application>
<application>节点是AndroidManifest.xml文件中必须持有的一个节点,它包含在<manifest>节点下.通过<application>节 ...
- Android.mk 文件语法详解
0. Android.mk简介: Android.mk文件用来告知NDK Build 系统关于Source的信息. Android.mk将是GNU Makefile的一部分,且将被Build Syst ...
- Android.mk 文件语法详解 转:http://blog.sina.com.cn/s/blog_602f8770010148ce.html
0. Android.mk简介: Android.mk文件用来告知NDK Build 系统关于Source的信息. Android.mk将是GNU Makefile的一部分,且将被Build Syst ...
- Android JNI的Android.mk文件语法详解
Android.mk简介: Android.mk文件用来告知NDK Build 系统关于Source的信息. Android.mk将是GNU Makefile的一部分,且将被Build System解 ...
- Android编译过程详解(一)
Android编译过程详解(一) 注:本文转载自Android编译过程详解(一):http://www.cnblogs.com/mr-raptor/archive/2012/06/07/2540359 ...
随机推荐
- 直接拿来用!Facebook移动开源项目大合集
直接拿来用!Facebook移动开源项目大合集 时间:2014-04-22 15:37 作者:唐小引 随着iOS依赖管理工具CocoaPods和大量第三方开源库成熟起来,业界积累了大量的优秀开源项目. ...
- g++ 编译c文件
//编译c文件为.o文件 g++ -c virify.c //打包.o文件为.a静态库文件 ar crv libandroid_um36_virify.a virify.o //将静态库.a文件编译进 ...
- w3chtml页面和css书写规范
http://www.cnblogs.com/Wenwang/archive/2011/09/07/2169881.html
- 清北学堂入学测试P4751 H’s problem(h)
P4751 H’s problem(h) 时间: 1000ms / 空间: 655360KiB / Java类名: Main 背景 冬令营入学测试 描述 小H是一个喜欢逛街的女孩子,但是由于上了大学 ...
- Json.net对数据的解析
在官网下载Json.net文件后,解压完将Net20下面的DLL复制到Assets目录下. using UnityEngine; using System.Collections; using New ...
- 未能读取并闩锁页 (1:xxxxx)(用闩锁类型 SH)
设置数据库为紧急模式 停掉SQL Server服务: 把应用数据库的数据文件XXX_Data.mdf移走: 重新建立一个同名的数据库XXX: 停掉SQL服务: 把原来的数据文件再覆盖回来: 运行以下语 ...
- 注意:MainActivity的oncreate方法里不要再inflate布局了(MainActivity里的点击事件无响应)
activity_main已经通过setContentView(R.layout.activity_main);设置给MainActivity, 不要再inflate出新布局,然后findviewby ...
- Android面试经验2
1,android如何更换主题: 2,如何设计软件: 3,代码中用到那些设计模式: 4,c++和java有那些不同: 一,指针: 二,多重继承: 三,数据类型和类: 四,自动内存管理: 五,操作符重载 ...
- android:分享 一个很强大的LOG开关---Log.isLoggable
标签:android分享 一个很强大的log开 1.API亮点: 此API可以实现不更换APK,在出问题的手机上就直接能抓到有效log,能提升不少工作效率. 2.API介绍 最近在解决短信问题时,看到 ...
- FusionCharts生成报表应用
1.需要组装要展示的数据,至于如何怎样去设计数据模型,看你要展示的图形和需要的数据就行了.来个简单的. 实体类,只有两个属性,也可以使用Bean里面的实体类,无所谓了. package com.gol ...