剖析安卓build系统的设计思想以及案例模拟

1.引言

安卓系统在根目录中只有一个Makefile文件,每个模块只有一个android.mk文件,这是Makefile文件的一个片段,为什么要这么设计呢?这种设计方式解决了什么问题呢?相信读完本文将会找到这些问题的答案。

2.问题的提出

对于一个小菜鸟来说,最先想到的方案是为每个模块写一个makefile,示例工程如下:

Project
  ----Makefile
  ----ant
       ----Makefile
       ----main.c
  ----bee
       ----Makefile
       ----parse.c
       ----parse.h

顶级目录的makefile内容如下:

MODULES = ant bee
all:
    for dir in $(MODULES); do         (cd $$dir; $(MAKE) all);     done

ant目录下的makefile内容如下:

all: main.o
main.o: main.c ../bee/parse.h
    $(CC) -I../bee -c main.c

bee目录下的makefile内容如下:

OBJ = ../ant/main.o parse.o
all: prog
prog: $(OBJ)
    $(CC) -o [email protected] $(OBJ)
parse.o: parser.c parse.h
    $(CC) -c parse.c

我们使用DAG来描述ant模块文件依赖关系:

同样的,bee模块的文件依赖关系如下:

这样我们就构建好2个模块的编译系统,只要make一下就能够得到我们想要的结果,不知道细心的读者是否发现了一个问题:main.o是依赖parse.h的,但是main.o并不清楚parse.h是如何诞生的,毕竟他们是处于两个模块的,两个makefile就像两个房间一样,他们各自身处于自己的空间当中,所以为了暴露这个问题,我们增加如下情景:

bee目录的parse.h和parse.c文件是通过yacc工具自动生成的,也就是我们在bee/Makefile文件增加以下内容来生成parse.h和parse.c文件。依赖关系现在如下:

假如我们修改了parse.y文件,然后在工程的根目录下执行make指令,得到的结果是否是我们想要的呢?答案是否定的,且听我细细道来。

make指定一旦执行,就会分别进入每个模块分别进行编译,即执行里面的makefile,那么这里首先进入ant模块,由于仅仅修改parse.y文件,所以main.o不会更新,完蛋啦,因为实际上parse.y更新,parse.h就要更新,进而main.o也是需要更新的,但这里却没有更新,也就是说,prog使用了陈旧的main.o。

问题出在哪里?还是每个模块一个makefile的方案是不对的。

每个模块一个makefile就需要依次编译每个模块,但是模块间又太过于松散,也就是一个模块中的目标可能无法感知依赖的变化,比如ant模块无法感知其依赖的变化(依赖由bee模块生成),一旦先编译了ant模块,那么就会出现我们不想要的结果。

3.改进实现

找到原因之后,那么如何解决呢?其实就是增加模块之间的耦合度,本质上就是让模块之间能够互相感知变化,下面将改进上面的设计,从而帮助我们理解安卓编译系统的设计思想。

改进以后的工程结构如下:

示例代码地址如下:

http://download.csdn.net/detail/getnextwindow/9063217

根目录下面只有一个Makefile文件,ant和bee模块下只有一个makefile片段,depend.sh自动生成头文件依赖的脚本。

Makefile实现如下:

MODULES :=ant bee
CFLAGS +=$(patsubst %,-I %,$(MODULES))
LIBS :=
SRC :=
include $(patsubst %,%/module.mk,$(MODULES))
OBJ:=$(patsubst %.c,%.o,$(filter %.c,$(SRC)))
prog:$(OBJ)
        $(CC) -o [email protected] $(OBJ) $(LIBS)
include $(OBJ:.o=.d)
%.d: %.c
        depend.sh `dirname $*.c` $(CFLAGS) $*.c >[email protected]
.PHONY :clean
clean:
        rm -f prog $(OBJ) $(OBJ:.o=.d)

bee模块的module.mk文件如下:

SRC += bee/parse.y
LIBS += -ly
%.c %.h: %.y
$(YACC) -d $*.y
mv y.tab.c $*.c
mv y.tab.h $*.h

现在来分析新设计是如何解决前面的问题的,假如我们现在仅仅修改了parse.y文件。

一旦开始执行make命令,会将所有include指令中的文件加载进来,然后才开始根据所有规则产生目标文件。加载进来bee模块的module.mk以后,就会更新parse.c和parse.h,接着就会更新依赖parse.c和parse.h的目标文件,即parse.o、parse.d和main.o,所以这里main.o感知到了变化。

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-08-02 16:12:55

剖析安卓build系统的设计思想以及案例模拟的相关文章

《深入理解Android内核设计思想》

<深入理解Android内核设计思想> 基本信息 作者: 林学森 出版社:人民邮电出版社 ISBN:9787115348418 上架时间:2014-4-25 出版日期:2014 年5月 开本:16开 页码:687 版次:1-1 所属分类:计算机 > 软件与程序设计 > 移动开发 > Android 更多关于>>><深入理解Android内核设计思想> 编辑推荐 基于Android SDK最新版本 全面细致地剖析了进程/线程模型.内存管理.Bind

Delphi 包的设计思想及它与PAS、BPL、DCU、DLL、OXC的关系。

DCP ,BPL分别是什么文件,起什么作用?你在DELPHI中建立一个package然后保存一下,看看. bpl和Dll比较相似.只是BPL是BORLAND自己弄出来的东西!!!调用也和调用DLL相似,loadpackage()...DCP:delphi编辑软件包:一种包含关于被编译进软件包当中的代码符号信息的文件. 这种文件并不包含编译代码,这些代码实际上存贮在dcu或bpl文件中: BPL:Borland程序包库:在delphi环境设计或应用程序运行时用到的包含有vcl组件的一种文件(这种文

React框架为什么这么火:React的设计思想

原文链接:http://mp.weixin.qq.com/s?__biz=MzA5Njc3Njk5NA==&mid=2650528748&idx=1&sn=4d3093e963ce76c642eb0c5d9a97625b#rd React的起源 React来自于Facebook,是的,就是那个你们听说过但是打不开的网站.Facebook的开发者当时在开发一个广告系统,因为对当前所有的MVC框架不满意,所以就自己写了一个UI框架,于是就有了React.后来因为觉得实在是好用,所以在2

中文翻译为&quot;具象状态传输&quot;的RESTful的架构风格和设计思想

本文标签:  具象状态传输 RESTful架构 RESTful理解 REST   服务器 REST 定义了一组体系架构原则,您可以根据这些,包括使用不同语言编写的客户端如何通过 HTTP 处理和传输资源状态.所以在事实上,REST 对 Web的影响非常大,由于其使用相当方便,已经普遍地取代了基于 SOAP 和 WSDL 的接口设计.在多年以后的今天,REST的主要框架已经开始雨后春笋般的出现. REST(Representational State Transfer ),有中文翻译为"具象状态传

Linux/Unix设计思想

Mike Gancarz 1.Unix开发基于Multics分时操作系统 2.NIH(Not invented here,非我发明) 3.GPL:GUN公共授权协议,适用于软件的法律协议.开源 4.Unix哲学: 1)小即是美:易理解.维护.低消耗系统资源.易于其他工具结合 2)让每一个程序制作好一件事 3)尽快建立原型(prototyping):"第三个系统"概念 4)舍高效而取可移植性 5)使用纯文本文件来存储数据:二进制严格禁止 6)充分利用软件的杠杆效应:借用代码模块;将一切自

《世界杯彩票竞猜系统》设计报告

目录 1 文档介绍    4 1.1 文档目的    4 1.2 文档范围    4 1.3 读者对象    4 1.4 参考文献    5 1.5 术语与缩写解释    5 2 系统环境说明    6 3 需求分析    7 3.1 功能需求分析    7 3.2 非功能需求分析    7 4 数据库的命名规则    8 5 概念结构设计    9 6 逻辑结构设计    9 7 物理结构设计    11 7.1 表汇总    11 7.2 表VS    11 7.3 表team    12

kafka入门二:Kafka的设计思想、理念

本节主要从整体角度介绍Kafka的设计思想,其中的每个理念都可以深入研究,以后我可能会发专题文章做深入介绍,在这里只做较概括的描述以便大家更好的理解Kafka的独特之处.本节主要涉及到如下主要内容: Kafka设计基本思想 Kafka中的数据压缩 Kafka消息转运过程中的可靠性 Kafka集群镜像复制 Kafka 备份机制 一.kafka由来 由于对JMS日常管理的过度开支和传统JMS可扩展性方面的局限,LinkedIn(www.linkedin.com)开发了Kafka以满足他们对实时数据流

FPGA重要设计思想

FPGA重要设计思想 ? 1.速度和面积互换原则.以面积换速度可以实现很高的数据吞吐率,其实串/并转换.就是一种以面积换速度的思想 2.乒乓操作. 3.串/并转换的思想. 高速数据处理的重要技巧之一.这里我来举一个多相滤波器抽取的例子: 抽取之后,两路数据以二分频的速度进行处理即可 4.流水线设计(在fir滤波器中表现很突出,一个时钟输出一个数据) 流水线设计可以从某种程度上提高系统频率..前提是:设计可以分为若干步骤进行处理,而且整个数据处理的过程是单向的,即没有反馈或者逆运算.前一个步骤的输

理解 Android Build 系统

http://www.ibm.com/developerworks/cn/opensource/os-cn-android-build/ Android Build 系统是用来编译 Android 系统,Android SDK 以及相关文档的一套框架.众所周知,Android 是一个开源的操作系统.Android 的源码中包含了许许多多的模块. 不同产商的不同设备对于 Android 系统的定制都是不一样的.如何将这些模块统一管理起来,如何能够在不同的操作系统上进行编译,如何在编译时能够支持面向