1. Introduction
Android system in the root directory only one makefile file, each module only one android.mk file, which is a fragment of the makefile file, why so design it? What is the problem with this design approach? I believe the answers to these questions will be found after reading this article.
2. The question was raised
For a small rookie, the first idea is to write a makefile for each module, the example works as follows:
Project ----Makefile ----ant ----Makefile ----main.c ----bee ----Makefile ----parse.c ----parse.h
The makefile content of the top-level directory is as follows:
MODULES = ant beeall: forindo (cd $$dir; $(MAKE) all); done
The makefile content in the Ant directory is as follows:
all: main.omain.o: main.c ../bee/parse.h $(CC) -I../bee -c main.c
The makefile content under the Bee directory is as follows:
OBJ = ../ant/main.o parse.oall: progprog: $(OBJ) $(CC) -o [email protected] $(OBJ)parse.o: parser.c parse.h $(CC) -c parse.c
We use Dags to describe the ant module file dependencies:
Similarly, the file dependencies of the Bee module are as follows:
So we build 2 modules of the compilation system, just make a bit to get the results we want, Do not know whether the attentive reader has found a problem: MAIN.O is dependent on parse.h, but MAIN.O is not clear how Parse.h was born, after all, they are in two modules, two makefile like two rooms, they are in their own space, so in order to expose this problem, I The following scenarios are added:
The parse.h and parse.c files of the Bee directory are generated automatically by the YACC tool, which is where we add the following content in the Bee/makefile file to generate Parse.h and parse.c files. The dependencies are now as follows:
If we modify the Parse.y file and then execute the make command at the root of the project, will we get the result we want? The answer is no, and listen to me carefully.
make specifies that once executed, it will go into each module separately to compile, that is, to execute the inside of the makefile, then here first into the Ant module, Because only modify the Parse.y file, so MAIN.O will not update, finished, because in fact parse.y update, parse.h will be updated, and MAIN.O also need to update, but here is not updated, that is, prog used the old main.o.
Where is the problem? It is not right to have a makefile scheme for each module.
Each module will need to compile each module in turn, but the module is too loose, that is, the target in a module may not be aware of changes in dependencies, such as the Ant module is unable to perceive the change of its dependencies (relying on the Bee module Generation), once the Ant module is compiled, the first time, the makefile Then there will be results that we do not want.
3. Improved implementation
After finding the reason, then how to solve it? In fact, it is to increase the coupling between the modules, essentially to allow the module to perceive the changes between each other, the following will improve the above design, so as to help us understand the Android compiler system design ideas.
The following engineering structures are improved:
The sample code addresses are as follows:
http://download.csdn.net/detail/getnextwindow/9063217
There is only one makefile file under the root directory, and there is only one makefile fragment under the Ant and Bee modules, and depend.sh automatically generates a script that is dependent on the header file.
The makefile is implemented as follows:
MODULES: =ant beecflags + =$(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:cleanclean:rm-f Prog$(OBJ)$(OBJ:.O=.D)
The module.mk file for the Bee module is as follows:
SRC += bee/parse.yLIBS += -ly%.c %.h: %.y$(YACC) -d $*.yy.tab.c $*.cy.tab.h $*.h
Now to analyze how the new design solves the previous problem, if we just modified the Parse.y file now.
Once the make command is started, the files in all include directives are loaded and then the target file is generated based on all rules. After loading the module.mk in the Bee module, the parse.c and parse.h are updated, and the target files that depend on parse.c and parse.h are updated, namely PARSE.O, PARSE.D, and MAIN.O, So here main.o perceive the change.
Copyright NOTICE: This article for Bo Master original article, without Bo Master permission not reproduced.
Anatomy of the design of the Android build system and the case simulation