Android Building System 分析

想要了解一个系统,我常会从 makefile 或是building system 下手, 以了解系统组成元素为何? 目录结构为何? 对于 Android ,我也不例外。 透过了解building system ,我们能知道如何新增、修改、删除程序, 并保有完整性,顺利编译出结果。

配置文件

Android building system 包括几种重要的配置文件,

  • Android.mk
  • AndroidProducts.mk
  • target_<os>-<arch>.mk, host_<os>-<arch>.mk and <os>-<arch>.mk
  • BoardConfig.mk
  • buildspec.mk

Android.mk 是module 和 package 的配置文件,每个module/package 的目录下都会有一个 Android.mk。 所谓的 module 是指系统的 native code ,相对于用 Java 写成的 Android application 称为package。

AndroidProducts.mk 则设定 product 配置。 product 即特定 系统版本,透过编译不同 product ,产生不同软件配置内容,安装不同的 application。 Product 可视为特定项目,产生特定规格系统。

BoardConfig.mk 是为 product 主板做设定,像是 driver 选择、 设定。*<os>-<arch>.mk 则是针对选择的操作系统和 CPU 架构,进行相关设定。

buildspec.mk 是位于 source 根目录下,为进行编译者所做之额外设定。例如,可在此选择要产生的 product 、平台、额外的module/package 等。

参数

build/envsetup.sh 实作一个 mm 指令,以编译单一 module,不需编译整个 source tree。ONE_SHOT_MAKEFILE 这个 makefile 变量/参数就是用以实作这个功能。使用 方法是在执行 make 时,将该变量指定为 module 的 Android.mk。

  • make ONE_SHOT_MAKEFILE=<path to Androiod.mk>

透过定义 CREATE_MODULE_INFO_FILE , building system 会将所有 module 信息 列在 $(PRODUCT_OUT)/module-info.txt档案里。

  • make CREATE_MODULE_INFO_FILE=true

设定 BUILD_TINY_ANDROID=true , building system 产生一个简单的 image , 以测试硬件的可用度。此功能用于移植的早期阶段,以快速 bring up。

HOST_BUILD_TYPE 和TARGET_BUILD_TYPE 指定 building system 产生 binary 的目的为 debug 或release 。透过设定此二变量,能产生包含 debug information 的 binry 。

  • debug
  • release

这些参数,也可设于 buildspec.mk 里,以避免开发过程不断的重新指定。

Goals

一般编辑整个 Android 系统,就是使用 droid 这个 goal。 droid 会产生一个 完整的系统,包括 bootloader、kernel、系统程序、模块和应用程序。

showcommands 和 droid 功能相同,但 droid 在编译过程不显示所使用的指令。 透过 showcommands 这个 goal, building system 显示过程中每一个步骤的详细 指令。

Makefile 的流程

  • 初始化相关变数
  • 侦测编译环境和目标环境
  • 决定目标 product
  • 读取 product 的设定
  • 读取 product 所指定之目标平台架构设定
    • 选择 toolchain
    • 指定编译参数 (*<os>-<arch>.mk)
  • 清除输出目录
  • 设定/检查版本编号
  • 读取所有 BoardConfig.mk 档案
  • 读取所有 module 的设定
  • 根据设定,产生必需的 rule
  • 产生 image

以上的主要流程都是由 build/core/main.mk 所安排。

初始化和侦测

由build/core/config.mk 所进行。 build/core/envsetup.mk 检查 developer 的设定 (buildspec.mk) , 并检查执行环境,以决定输出目录、项目。

build/core/config.mk 本身还依据参数,决定解译时的相关参数。像是 compiler 的路径、flags,lex 、yacc 的路径参数等。

关于 product 的相关设定,则是由build/core/product_config.mk 所处理, 使用build/core/product.mk 提供之 macro 加载。根据 AndroidProduct.mk 的内容, product_config.mk 决定了

  • PRODUCT_TAGS
  • OTA_PUBLIC_KEYS
  • PRODUCT_POLICY
  • ......

Product 设定的读取

Android product 的设定来自于 build/target/product/AndroidProduct.mk 和vendor 子目录下的 AndroidProduct.mk 。 building system 透过 find 指令, 找出所有可能的 AndroidProduct.mk。 AndroidProduct.mk 里定义 PRODUCT_MAKEFILES 变量,列举所有实际定义 product 的 makefile。 这些 makefile 各自定义独立的 product 。product 相关参数,存成 PRODUCTS.<path of makefile>.<variable> 形式的变数。并将 makefile 路径 存在 PRODUCTS 变量。因此,透过 PRODUCTS 能取得所有的 product 路径/名称, 并透过 PRODUCTS.<path of makefile>.<variable>形式的变量取得内容。

Module 设定的读取

Module 是指 native code 的软件组件,而 Java application 则被称为 package。 build/core/definitions.mk 定义 module/package相关 macro ,读取、检查 module/package 定义档;分散 source tree 各处的 Android.mk 档案。build/core/main.mk 使用 find 指令,在这些子目录下找出所有 Android.mk , 并将路径存在subdir_makefiles 变量里。最后,include 这些档案。

这些 Android.mk 会 include 定义成变量 BUILD_SHARED_LIBRARY 、BUILD_PACKAGE 等,和其目的相配的 makefile。这些 makefile 会变Android.mk 定义之内容,存成ALL_MODULES.<path of Android.mk>.<variable> 形式。例如, Android.mk 定义了LOCAL_MODULE_SUFFIX ,变会存成 ALL_MODULES.<path of Android.mk>.LOCAL_MODULE_SUFFIX 。而 Android.mk 路径, 当样会存于ALL_MODULES 变量里。

Search Android.mk 的路径,基本上会是整个 source tree 。但会依特定的 goal , 选择性只找寻特定目录。例如 SDK 只需特定目录下的 Android.mk 。

Board Level 设定

和目标平台主板相关之设定,例如使用了什么装置、driver 等,或是是否需要编译 bootloader 、 kernel 等,都是在 BoardConfig.mk 里设定。同样,每张主板可以有不同设定,存在不同目录下的 BoardConfig.mk ,以find 寻找如下档案:

  • build/target/board/$(TARGET_DEVICE)/BoardConfig.mk
  • vendor/*/$(TARGET_DEVICE)/BoardConfig.mk

TARGET_DEVICE 是product 所定义,因此同一个 BoardConfig.mk 可被多个 product 所使用。一个 TARGET_DEVICE ,通常只有一个 BoardConfig.mk 。 BoardConfig.mk 会被直接 include 到 building system 的 name space 里。 因此,一些 module 的 enable/disable ,可以在 BoardConfig.mk 以对映不同的主板。

Rules

在module 的定义档 Android.mk 里,可定义 module 的 tag, LOCAL_MODULE_TAGS, 以分类这些 module。 每一个 product 可以指定需要的 tag (PRODUCT_TAGS),使 building system 只编译标示这些 tag 的 module。在build/core/main.mk 里,所有标示特定 tag 的 module 收集为 ALL_DEFAULT_INSTALLED_MODULES ,并 include build/core/Makefile 处理。

build/core/Makefile 为这些 module 产生 rule ,并使产生 image 的goal depend on 这些 rule ,使这些module 被编译。

结论

Android 的building system 其实不是那么复杂。在了解之后,也不是那么难修改。 但, GNU make 的一些语法,所 building system 使用一些不是那么直觉的用法, 使的 buildingsystem 较难了解。但,花点心思就能克服。

 


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值