Android.mk文件分析

转载 2016年05月31日 14:49:04

从对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文件分析

http://blog.csdn.net/a345017062/article/details/6130264 从对Makefile一无所知开始,折腾了一个多星期,终于对Android.mk有了一个...
  • zangchaodotcnatgmail
  • zangchaodotcnatgmail
  • 2013年08月16日 16:34
  • 500

android.mk文件分析

 一个Android.mk file用来向编译系统描述你的源代码。具体来说:该文件是GNU Makefile的一小部分,会被编译系统解析一次或多次。你可以在每一个Android.mk file中定义一...
  • swliao
  • swliao
  • 2011年06月23日 10:26
  • 925

Android.mk文件简单分析

Android.mk文件简单分析 一个Android.mk文件用来向编译系统描述需要编译的源代码。具体来说:该文件是GNUMakefile的一小部分,会被编译系统解析一次或多次。可以在每一个And...
  • netwalk
  • netwalk
  • 2014年10月23日 19:49
  • 2234

Android.mk文件的分析

环境变量的作用: 方便的在任何目录下 都可以使用 指定目录里面的工具 LOCAL_PATH := $(call my-dir)  # 交叉编译器 在编译c代码/c++代码依赖的配置文件    ...
  • caihongshijie6
  • caihongshijie6
  • 2013年12月02日 16:07
  • 1314

Android.mk文件简要分析

Android.mk文件简要分析 LOCAL_PATH:= $(call my-dir) LOCAL_PATH表示此时位于工程目录的根目录中,(call my-dir)是调用了my-dir函数...
  • wodesteve
  • wodesteve
  • 2012年05月17日 11:38
  • 350

Android.mk 实例详解

LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := fp_identify LOCAL_SRC_F...
  • ymangu
  • ymangu
  • 2014年04月14日 09:36
  • 1674

jni Android.mk文件分析

在一个Android.mk中可以生成多个可执行程序、动态库和静态库。 1,编译应用程序的模板: #Test Exe LOCAL_PATH := $(call my-dir) #includ...
  • aiqing0119
  • aiqing0119
  • 2012年08月09日 16:06
  • 432

android.mk中添加目录中所有cpp

android开发中,经常遇到需要在andoid.mk文件中包含特定的cpp文件(或c文件) LOCAL_SRC_FILES := hellocpp/main.cpp \ ../../Cla...
  • dxpqxb
  • dxpqxb
  • 2015年01月06日 18:32
  • 2705

android使用mk文件的进阶

最近在搞android上的rtmp协议的播放,将ffmpeg编译成几个.so动态链接库之后(后面再说如何在android下编译ffmpeg源代码),就可以引用头文件并直接写自己的jni接口了,做完这些...
  • zcl1359205840
  • zcl1359205840
  • 2016年08月18日 17:45
  • 1174

【Android7.1.2源码解析系列】android init目录下的Android.mk编译文件分析

上一篇文章对于源码中的安卓编译系统文档进行了翻译,本文就以android当中的init模块作为例子,对其中的Android.mk文件进行分析,读者可以在阅读本文的同时查看我的译文:http://blo...
  • class_brick
  • class_brick
  • 2017年04月28日 11:47
  • 667
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Android.mk文件分析
举报原因:
原因补充:

(最多只允许输入30个字)