Starting from having no idea about makefile, I had to spend more than a week and finally had a comprehensive understanding of Android. mk. After learning about the standard makefile, we found that android. mk actually wraps the real makefile into something very simple for users. When using it to compile a program, whether it is a dynamic library, executable binary files, a jar library, or an APK package, you just need to take three steps along a simple idea: clear old variables, set new variables, and call the compile function.
After understanding it, I found that the makefile syntax is not a problem. There are many tutorials and experts. How to clear variables and call compilation functions during compilation is not a problem. Such examples are everywhere in the source code. For beginners, it is even more important to understand how Android frees the script users from the makefile syntax and compiles any modules simply following the three steps above.
Use alarmclock as an example:
// Clear old Variables
Local_path: = $ (call my-DIR)
Include $ (clear_vars)
// Set new variables
Local_src_files: = $ (call all-subdir-Java-files)
Local_package_name: = alarmclock
// Call the compile Function
Include $ (build_package)
The following three steps are briefly explained:
1. Clear the old variables because all the variables in Android. mk are global and the compiled functions call these variables during compilation. To prevent compilation functions from using the variables set when compiling other modules, it is a good habit to clear all variables every time a new module is compiled.
2. Set the new variable to set the Source Code address and package name used in this compilation.
3. Calling the compilation function is actually to include a fixed MK file. This MK file extracts the target, command, and other information required by the compilation Module Based on the set variables and runs the fixed compilation command.
After I understood Android. mk, my deepest feeling was Android's encapsulation thought, which reminds me of many things I have never thought about before. Oh...
My personal understanding records Android's step-by-step evolution of this encapsulation concept. Sincerely welcome criticism and correction.
Makefile:
Target: Trusted File
Execute Command
The syntax details are not considered here. An incomplete example is as follows:
Alarmclock.apk: alarmclock. Java
Javac alarmclock. Java
Java alarmclock. Class
To generate alarmclock.apk, you need the trusted file alarmclock. Java and then execute the two commands in the next two lines. It would be quite tiring to use this method to compile the Android system. Android. mk cleverly abstracts them. Let's simulate it now:
Define three variables: Target, source, and command, which respectively represent the compilation target, trusted file, and compilation command:
$ (Target): $ (source)
$ (Command)
The values of these three variables are:
Target: = alarmclock.apk
Source: = alarmclock. Java
Commnd: =/
Javac alarmclock. Java/
Java alarmclock. Class
In this way, when compiling each APK, you only need to assign values to target, source, and command respectively, and then write them like this:
$ (Target): $ (source)
$ (Command)
Well, it's still a little troublesome, so we can abstract it again. Define a variable name to store the name of the module to be compiled:
Name: = alarmclock
Then, change the preceding three variables:
Target: = folder (name).apk
Source: = $ (name). Java
Commnd: =/
Javac $ (name). Java/
Java $ (name). Class
What do I need to do to compile a module contacts?
Name: = contacts
$ (Target): $ (source)
$ (Command)
Three lines of code are enough. It's easy, right? However, the next two rows must be written every time, and then abstracted. Put the following two lines in a build_apk.mk file. Then define a variable:
Build_packages: = build_apk.mk
All completed. This time, you only need to do this when compiling a module contacts:
Name: = contacts
Include $ (build_packages)
If it is not complex enough, You need:
Name: = contacts
Include $ (build_packages)
Name: = phone
Include $ (build_packages)
Name: = Email
Include $ (build_packages)
// ======================== Strong separator ==========
Now let's improve the above process and systematize it.
Define the content of clear_vars.mk specifically used to clear the variable as follows:
Name: =
Target: =
Source: =
Command: =
Define another variable clear_vars: = clear_vars.mk. The above compilation script becomes like this:
Include $ (clear_vars)
Name: = contacts
Include $ (build_packages)
Include $ (clear_vars)
Name: = phone
Include $ (build_packages)
Include $ (clear_vars)
Name: = Email
Include $ (build_packages)
This time, all three major steps are available: clearing old variables, setting new variables, and calling compile functions.
Now, go to the build/CORE/directory of the android source code. First look at the main. mk, config. mk files.
Main. mk contains a specific script, which controls the compilation module here.
Config. mk defines the following file calls:
Clear_vars: = $ (build_system)/clear_vars.mk
Build_host_static_library: = $ (build_system)/host_static_library.mk
During module compilation, each include is actually a function call, a call to the MK file, or a call to variables and functions. MK files abstracted as separate function modules are all under the build/CORE/directory, and function definitions are all in definitions. mk.
Everything is hard at the beginning. With the above ideas, it is easy to read these scripts again. A pleasant journey, oh...
From: http://blog.csdn.net/a345017062/article/details/6130264