把Android所有的Make文件分为4种:
1、For config
这类文件主要来配置product,board,以及根据你的Host和Target选择相应的工具以及设定相应的通用编译选项:
build/core/config.mk         summary of config
build/core/envsetup.mk    generate dir config and so on
build/target/product         product config
build/target/board            board config
build/core/combo              build flags config 
这里解释下这里的board和product。borad主要是涉及到硬件芯片的配置,比如是否提供硬件的某些功能,比如说GPU等等,或者芯片支持浮点运算等等。product是指针对当前的芯片配置定义你将要生产产品的个性配置,主要是指APK方面的配置,哪些APK会包含在哪个product中, 哪些APK在当前product中是不提供的。
config.mk是一个总括性的东西,它里面定义了各种module编译所需要使用的HOST工具以及如何来编译各种模块,比如说 BUILT_PREBUILT就定义了如何来编译预编译模块。
envsetup.mk主要会读取由envsetup.sh写入环境变量中的一些变量来配置 编译过程中的输出目录,combo里面主要定义了各种Host和Target结合的编译器和编译选项。
2. Module Compile
这类文件主要定义了如何来处理Module的Android.mk,以及采用何种方式来生成目标模块,这些模块生成规则都定义在config.mk里面,我们可以看看:
CLEAR_VARS:= $(BUILD_SYSTEM)/clear_vars.mk
BUILD_HOST_STATIC_LIBRARY:= $(BUILD_SYSTEM)/host_static_library.mk
BUILD_HOST_SHARED_LIBRARY:= $(BUILD_SYSTEM)/host_shared_library.mk
BUILD_STATIC_LIBRARY:= $(BUILD_SYSTEM)/static_library.mk
BUILD_RAW_STATIC_LIBRARY := $(BUILD_SYSTEM)/raw_static_library.mk
BUILD_SHARED_LIBRARY:= $(BUILD_SYSTEM)/shared_library.mk
BUILD_EXECUTABLE:= $(BUILD_SYSTEM)/executable.mk
BUILD_RAW_EXECUTABLE:= $(BUILD_SYSTEM)/raw_executable.mk
BUILD_HOST_EXECUTABLE:= $(BUILD_SYSTEM)/host_executable.mk
BUILD_PACKAGE:= $(BUILD_SYSTEM)/package.mk
BUILD_HOST_PREBUILT:= $(BUILD_SYSTEM)/host_prebuilt.mk
BUILD_PREBUILT:= $(BUILD_SYSTEM)/prebuilt.mk
BUILD_MULTI_PREBUILT:= $(BUILD_SYSTEM)/multi_prebuilt.mk
BUILD_JAVA_LIBRARY:= $(BUILD_SYSTEM)/java_library.mk
BUILD_STATIC_JAVA_LIBRARY:= $(BUILD_SYSTEM)/static_java_library.mk
BUILD_HOST_JAVA_LIBRARY:= $(BUILD_SYSTEM)/host_java_library.mk
BUILD_DROIDDOC:= $(BUILD_SYSTEM)/droiddoc.mk
BUILD_COPY_HEADERS := $(BUILD_SYSTEM)/copy_headers.mk
BUILD_KEY_CHAR_MAP := $(BUILD_SYSTEM)/key_char_map.mk
除了CLEAR_VARS是清楚本地变量之外,其他所有的都对应了一种模块的生成规则,每一个本地模块最后都会include其中的一种来生成目标模 块。大部分上面的.mk都会包含base_rules.mk,这是对模块进行处理的基础文件,建议要写本地模块的都去看看,看明白了为什么 Android.mk要这么写就会大致明白了。
3.Local Module
本地模块的Makefile文件就是我们在Android里面几乎上随处可见的Android.mk ,Android进行编译的时候会通过下面的函数来 遍历所有子目录中的Android.mk,一旦找到就不会再往层子目录继续寻找(所有你的模块定义的顶层Android.mk必须包含自己定义的子目录中的Android.mk)。
subdir_makefiles += \
$(shell build/tools/findleaves.py --prune=out --prune=.repo --prune=.git $(subdirs) Android.mk)
不同类型的本地模块具有不同的语法,但基本上是相通的,只有个别变量的不同。
Android通过LOCAL_MODULE_TAGS来决定哪些本地模块会不会编译进系统,通过PRODUCT和LOCAL_MODULE_TAGS来决定哪些应用包会编译进系统(默认情况是只要设置为tests则不编译进系统),如果用户不指定LOCAL_MODULE_TAGS,默认它的值是user。此外用户可以通过buildspec.mk来指定你需要编译进系统的模块。
用户也可以通过mm来编译指定模块,或者通过make clean-module_name来删除指定模块。
4.Package 
这主要指的是build/core/Makefile这个文件,它定义了生成各种img的方式,包括ramdisk.img   userdata.img  system.img  update.zip  recover.img等。我们可以看看这些img都是如何生成的,对应着我们常用的几个make goals:
在实际的过程中,我们也可以自己编辑out目录下的生成文件,然后手工打包相应生成相应的img,最常用的是加入一些需要集成进的prebuilt file。
所有的Makefile都通过build/core/main.mk这个文件组织在一起,它定义了一个默认goals:droid,当我们在TOP目录下 敲Make实际上就等同于我们执行make droid。当Make include所有的文件,完成对所有make我文件的解析以后就会寻找生成droid的规则,依次生成它的依赖,直到所有满足的模块被编译好,然后使用 相应的工具打包成相应的img。
基本上Android building system就是以这样一种方式组织在一起的了,下面说一点闲散的东西。首先是如何来加快Android的编译过程,因为每次Android都要遍历所有 的Android.mk,不管是编译整个工程还是只编译某个模块。所以可以将遍历的结果保存下来,下次直接从文件读就好了,但是这里容易出错,所以一定要 确认是否正确包含了所有的.mk,当新加入文件的时候确认将原来保存的文件删除。下面是我写的加快编译的一个makefile,将下面的语句替换掉 main.mk中的相应部分就可以了:
FROM:
subdir_makefiles += \
$(shell build/tools/findleaves.sh --prune="./out" $(subdirs) Android.mk)
TO:
ifneq ($(ONE_SHOT_MAKEFILE),)
else
ifneq ($(CASH_MK),true)
subdir_makefiles += \
$(shell build/tools/findleaves.sh --prune="./out" $(subdirs) Android.mk)
else
subdir-makefiles-cash := $(shell cat build/subdir_mk_cash)
ifeq ($(subdir-makefiles-cash),)
$(warning No .mk cash ,create now !)
subdir_makefiles += \
$(shell build/tools/findleaves.sh --prune="./out" $(subdirs) Android.mk)
mk-to-file := $(shell echo $(subdir_makefiles) > build/subdir_mk_cash) 
else
$(warning Using cash mk !)
subdir_makefiles := $(shell cat build/subdir_mk_cash)
endif
endif
endif
通过CASH_MK=true来打开快速编译的功能,因为没有对错误进行检测的操作,所以使用的时候一定要特别小心。
总起来说,Android的Makefile的引用关系是这样的,
Makfile-->build/core/main.mk-->build/core/config.mk--->build/core/envsetup.mk-->build/core/product_config.mk
在build/core/product_config.mk中编译系统首先调用build/core/product.mk/中定义的函数get-all-product-makefiles来遍历整个vendor的子目录,找到vendor下所有的AndroidProduct.mk,不同子目录下的AndroidProduct.mk中不同的PRODUCT_NAME,PRODUCT_DEVICE等信息(可以通过打开build/core/product_config.mk中的#$(dump-products)语句使控制台编译的时候输出都有的product信息),接着build/core/product_config.mk会调用resolve-short-product-name将TARGET_PRODUCT匹配的的AndroidProduct.mk总定义的PRODUCT_DEVICE赋值给TARGET_DEVICE。
在回到build/core/config.mk, include $(TARGET_DEVICE)/BoardConfig.mk
board_config_mk := \
$(strip $(wildcard \
$(SRC_TARGET_DIR)/board/$(TARGET_DEVICE)/BoardConfig.mk \
device/*/$(TARGET_DEVICE)/BoardConfig.mk \
vendor/*/$(TARGET_DEVICE)/BoardConfig.mk \
))
.....
include $(board_config_mk)
而这个BoardConfig.mk决定了目标系统的属性,比如使用ALSA还是GENERIC_AUDIO等等,另外在这里TARGET_DEVICE宏也决定了TARGET_DEVICE_DIR,(TARGET_DEVICE_DIR := $(patsubst %/,%,$(dir $(board_config_mk))))
当然Android的obj目标输出也是由TARGET_DEVICE决定,见build/core/envsetup.mk。再回到build/core/main.mk,编译系统接着做的一件事情是,遍历所有的子目录,找到所有的Android.mk文件,并将这些Android.mk文件include进来:
subdir_makefiles := \
$(shell build/tools/findleaves.py --prune=out --prune=.repo --prune=.git $(subdirs) Android.mk)
include $(subdir_makefiles)
我们再来看其中的./build/target/board/Android.mk,对它引用了include $(TARGET_DEVICE_DIR)/AndroidBoard.mk,由上面TARGET_DEVICE_DIR的定义可知,这下又进入了vendor下TARGET_DEVICE指向的目录了,这个mk文件中定义了特定Product需要编译和安装的app和script.

Android 编译系统分析(二)相关推荐

  1. Android编译系统分析二:mm编译单个模块

    因为Android的编译系统不同于Linux Kernel的递归式的编译系统,它的编译系统是一种称之为independent的模式,每个模块基本独立(它有可能依赖其他模块),每个模块都可以单独编译,这 ...

  2. Android编译系统分析四:实战-新增一个产品

    通过上一节"android编译系统(三)-make"的分析,初步理清楚了编译初期加载产品相关信息的流程,整个过程主要涉及三个文件:1.AndroidProducts.mk,2.具体 ...

  3. Android 编译系统分析之lunch分析

    已开通新的博客,后续文字都会发到新博客 http://www.0xfree.top Android 编译系统解析系列文档 编译系统入口envsetup.sh解析 source build/envset ...

  4. Android编译系统分析五:system.img的生成过程

    Android编译系统分析系列文章: android编译系统分析(一)-source build/envsetup.sh与lunch Android编译系统(二)-mm编译单个模块 android编译 ...

  5. Android 编译系统分析(三)

    自Android开源以来,引起了嵌入式行业一股热潮,很多嵌入式开发者表示对Android有很强的兴趣,并下载Android源码进行编译和移植.Android源码的巨大(repo下来,大概2G)给人以A ...

  6. Android编译系统分析三:make完整编译android系统

    这篇博客的目标是摸清楚默认编译整个android系统时代码的流程. 当我们执行make的时候,会查找当前的Makefie文件或者makefile文件并且执行,在android顶级源码目录下面,确实有个 ...

  7. Android 编译系统分析(一)

    一.Makefile的主要流程 以下主要流程都在build/core/main.mk里安排. 初始化相关的参数设置(buildspec.mk.envsetup.mk.config.mk) 检测编译环境 ...

  8. Android编译笔记二

    对比了RK3288的Ubuntu14.04和按官网编译的Android的log信息后发现很多不一样,鉴于官网上的编译方法是针对开发板的,所以烧录后内核起不来,也要查看一下硬件,先查一下各路电压. 节点 ...

  9. Android10.0 日志系统分析(二)-logd、logcat架构分析及日志系统初始化-[Android取经之路]

    摘要:本节主要来讲解Android10.0 日志系统的架构分析,以及logd.logcat的初始化操作 阅读本文大约需要花费15分钟. 文章首发微信公众号:IngresGe 专注于Android系统级 ...

最新文章

  1. django 使用Ajax方式POST JSON数据包
  2. c++求平均值_云顶之弈S4:六射手娱乐吃鸡!人均刮痧王,每个人都是主C
  3. SQLite 入门教程(一)基本控制台(终端)命令
  4. SQL Server 2008如何创建定期自动备份任务
  5. A Full Hardware Guide to Deep Learning
  6. SQL求一个表中非重复数据及其出现的次数
  7. LeetCode 109. Convert Sorted List to Binary Search Tree
  8. 特殊字符的html编码转化
  9. apicloud 请删除手机中的apploader后在尝试
  10. postman插件4.1.3的安装(亲测,可以用)
  11. 【Unity3D】3dsmax中带Vray材质的3D模型的导入
  12. 10电脑睡眠后自动关机怎么回事 win_win10睡眠变自动关机怎么办
  13. php需要做临时表嘛,php中使用临时表查询数据的一个例子
  14. 质量检验中那些不为人所知的事儿
  15. 利用7-zip软件压缩并加密自己的保密文件
  16. Qt5笔记之Qt5插件的生成与加载及json文件的读取
  17. Springboot实现登录拦截的三种方式
  18. Nginx通过ip和user_gent限制访问
  19. 如何选择一台适合Java开发的电脑
  20. 冷凝器胶球自动在线清洗装置

热门文章

  1. 业务订单号生成算法,每秒50W左右,不同机器保证不重复,包含日期可读性好...
  2. MySQL 的 RowNum 实现
  3. 火星人乘坐核动力飞船回故乡
  4. asp.net mvc源码分析-DefaultModelBinder 自定义的普通数据类型的绑定和验证
  5. 易度甘特图的功能介绍和开发手册
  6. step4 . day4 库函数和库函数的制作
  7. 用servlet校验密码2
  8. the little schemer 笔记(7)
  9. loj #6235. 区间素数个数
  10. linux查看文件和文件夹大小