创建编译工程,这个说法可能不太准确,简单地说就是如何在device下面添加一个新的产品。

添加一个新产品

Android 采用的是 brand/device/product 这样一个三级的层次结构,编译系统根据相应的规则来搜索,加载编译项目。所以,建立新的工程,最重要的就是先定义好 'brand', 'device' 和'product'。

下面让我们来为华为的meta7_32G来创建一个产品配置吧:

brand = 'huawei'
device = 'meta7'
product = "meta7_32G"

1:  device下新建目录结构文件夹, device/huawei/meta7。

2:  /device/.../meta7/ 下创建文件 'vendorsetup.sh'。

source build/envsetup.sh后,应该可能看到 meta7_32-eng|user 了。

注意: 工程名是 "  'product'-{eng | user |  userdebug} " ,其中product名字中不能包含 '-'。'meta7-32-eng' 是错误的产品名称, 一旦product名称确定后,这个名字也被确定了。

3: /device/.../meta7/ 下创建文件 'AndroidProducts.mk'

命名方式是 'product'.mk

4: /device/.../meta7/ 下创建文件 'BoardConfig.mk'

编译系统在lunch的时候,需要include 这个文件。

至此,大工告成!我们增加了一个产品。

编译类型

一共是3种编译类型 user | eng | userdebug ,主要的区别是: 是否启用adb,是否root,以及一些对应的模块安装等等。

user

受限制访问系统,主要用于发布产品。

  • ro.secure=1

  • ro.debuggable=0

  • adb is disabled by default.

userdebug

其它与uer相同,除了下面2点:

  • ro.debuggable=1

  • adb is enabled by default.

eng

  • ro.secure=0

  • ro.debuggable=1

  • ro.kernel.android.checkjni=1

  • adb is enabled by default.

lunch编译工程的工作流程

前面已经简单提到过了,build系统使用了brand/device/product 这样一个三级的层次结构,它在lunch的时候,会计算这三个变量的值,如:

brand = 'huawei'
device = 'meta7'
product = "meta7_32G"

然后,根据他们的值来load一些固定的文件,如: "$(TARGET_BRAND)/$(TARGET_DEVICE)/BoardConfig.mk", 同时加载配置变量(如:TARGET_ARCH=xxx),如果有文件不存在或者某些变量未定义,编译系统会报错退出。

1: 加载 vendorsetup.sh

当运行 'source build/envsetup.sh', build系统会搜索,device和vendor目录下所有的envsetup.sh 文件。

所以添加的新产品,目录层次不要超过4层。

2load AndroidProducts.mk文件

当用户选择编译项目后,build系统就知道当前的 product的值是什么了,如:'TARGET_PRODUCT = meta7_32G', build系统会搜索device或vendor下面所有的AndroidProducts.mk文件,得到 PRODUCT_MAKEFILES 的值, 如:

device/huawei/meta7/meta7_32G.mk
device/htc/flounder/aosp_flounder_64_only.mk
device/generic/mips/mini_mips.mk

搜索了完所有的 PRODUCT_x.mk 文件后,build系统根据 TARGET_PRODUCT 的值来一一比对文件名,最终就可以确定目标的mk文件是 "device/...../meta7_32G.mk"。找到mk文件后,build系统会读取mk文件里面的 PRODUCT_NAME 变量,来与 TARGET_PRODUCT 再次进行匹配,成功后,产品的mk文件就加载成功了。所以,meta7_32G.mk里面定义的 PRODUCT_NAME ,必须是 'meta7_32G',否则,报错退出。

mk文件被确认后,根据目录结构,也就确定了 TARGET_BRAND  TARGET_DEVICE 的值,如:

device/huawei/meta7/meta7_32G.mk 匹配成功,那么 brand,device,product这三个值就都确定了:

brand = 'huawei'
device = 'meta7'
product = "meta7_32G"

源码主要在 build/core/product_config.mk:all_product_makefiles

搜索AndroidProducts.mk

总结一下,当用户lunch工程后,build 系统通过搜索,所有的PRODUCT_x.mk文件,根据工程名来同文件名和文件里面的PRODUCT_NAME变量来比对,匹配成功则load成功。

3: load BoardConfig.mk

build 系统直接load '$(TARGET_BRAND)/$(TARGET_DEVICE)/BoardConfig.mk'
到了这一步,一个最基本的编译配置,加载成功了。
注意:source build/env 和 lunch 这2个操作中 load的mk文件里面,不能使用 call my-dir等一些函数。

一些内置mk函数,变量

inherit-product: 这个函数只能用在定义产品的mk文件(meta7_32G.mk )里面, 可以使用的变量包括: PRODUCT_NAME, PRODUCT_RUNTIMES等,完整的列表在 build/core/product.mk:_product_var_list

build/core/config.mk, 包含一些系统配置变量, 如:

SRC_TARGET_DIR := $(TOPDIR)build/target

用户评论:
发表评论: (限500字)

注册 忘记密码 登录