本文主要讲解 AOSP 基于Makefile实现配置,AOSP的版本 7.0。
1. 目标: 利用mk实现配置
实现配置的意义在于在AOSP中利用几个特定的makefile实现一个"Product" 的多个"配置"。例如当获取到AOSP的源码后,经过 source build/envsetup.sh; lunch # 便可以选择 "Product"; 例如 aosp_arm64-eng。此处aosp_arm64便是指一个特定的"Product"。这个"Product"具体如何编译便认为是"配置"。
2. 查看配置
在AOSP 的编译系统中,可以通过make dump-products来查看"Product" 的具体"配置"。例如实际的输出可能类似于:
PRODUCTS.device/sample/products/sample_addon.mk.PRODUCT_NAME := aosp_arm64
PRODUCTS.device/sample/products/sample_addon.mk.PRODUCT_MODEL
PRODUCTS.device/sample/products/sample_addon.mk.PRODUCT_DEVICE := generic_arm64
PRODUCTS.device/sample/products/sample_addon.mk.PRODUCT_PACKAGES :=
输出的格式为 PRODUCTS."代表一个具体Product 的 Makefile".PRODUCT_XXX := "配置值"
在当前版本中还有一个特殊的目标 "product-graph" 可以输出 pdf文档,但是需要系统安装相应的软件包将dot格式转换为 pdf格式。
另外,在执行 make
dump-products或者make product-graph还可以通过makefile配置变量
ANDROID_DUMP_PRODUCTS := all(dump-products);
ANDROID_RPODUCT-GRAPH := --all(product-graph) ;
来查看当前AOSP中所有的"Product",而不是仅仅查看当前选择的"Product"。
具体情况:
load_all_product_makefiles :=
ifneq (,$(filter
dump-products,$(MAKECMDGOALS)))
ifeq ($(
ANDROID_DUMP_PRODUCTS),all)
load_all_product_makefiles := true
endif
endif
ifeq ($(load_all_product_makefiles),true)
# 此处实际代码省略, 会将当前AOSP中所有的"Product"导入
# Import all product makefiles.
else
#
会将当前AOSP中lunch 选择 的"Product"导入
endif # Import all or just the current product makefile
ifneq ($(filter
dump-products, $(MAKECMDGOALS)),)
$(dump-products) # 此处对已经导入的 "Product" 进行显示输出
$(error done) # 此处表示 make 执行到此结束
endif
如果希望输出全部"Product" 的"配置"信息,可以新建文件或者在已有的makefile : "AOSP/buildspec.mk" 即AOSP顶层目录的buildspec.mk文件中写入
ANDROID_DUMP_PRODUCTS := all
"AOSP/buildspec.mk" 在 build/core/config.mk文件中被引入, 且在引入build/core/product_config.mk之前。
(配置涉及到makefile在之后做一个总结,此处只要注意的是变量定义在配置之前)。
3. 配置
3.1 实例 (具体的文件内容可以以 build/target/product 做参考)
(1) 目录结构: mkidr -p device/liuz/chip/boarddir
(2)"Product" 说明文件: device/liuz/chip/AndroidProducts.mk
(3)"Product" 真实Makefile : /device/liuz/chip/myproduct.mk
(4)"Product" "Board"子目录及其说明makefile: /device/liuz/chip/boarddir/BoardConfig.mk
其中需要注意的
boarddir这个特殊目录需要在 "
/device/liuz/chip/myproduct.mk" 中用变量
PRODUCT_DEVICE := boarddir # 来说明
(5) 当前"Product" (myproduct)引入到 AOSP编译系统的入口SHELL脚本
/device/liuz/vendorsetup.sh # 此文件的内容 add_lunch_combo myproduct-eng
3.2 配置解析makefile
(1) 将"product" 引入到AOSP编译系统中: build/envsetup.sh
(2) 解析一个AOSP中定义的"Product":
build/core/config.mk; build/core/envsetup.mk; build/core/product_config.mk;
build/core/product.mk; build/core/node_fns.mk;
build/core/dumpvar.mk
3.3 配置解析过程
AOSP 的编译系统解析一个在AOSP中定义的 "Product",总体上是为一个所谓的"Product"的名称计算出对应一个标准的一系列变量。其中可以通过 make dump-products 来查看有哪些标准的变量。
AOSP解析配置过程中有1个SHELL数组全局变量 LUNCH_MENU_CHOICES,2个make全局变量: PRODUCTS, ALL_PRODUCTS;
其中PRODUCTS记录的是所有的"Product"的名称(简称),ALL_PRODUCTS则记录所有的对应的"Product" 的实际Makefile。
(1)向AOSP编译系统中加入"Product": 此功能是由build/envsetup.sh完成
可以搜索AOSP/build/envsetup.sh中对于"vendorsetup.sh"的定位。
AOSP编译系统搜索到特定目录(device, vendor, product)下特定的vendorsetup.sh并通过source命令加载。
vendorsetup.sh 一般完成向AOSP中"注册/告知"一个"Product": add_lunch_combo
这个SHELL函数的作用是向SHELL全局数组变量 LUNCH_MENU_CHOICES加入一个元素(即所谓的"Product")以供编译选择。
(9)当用户make时,通过lunch选择由vendorsetup.sh引入的"Product"
通过 LUNCH_MENU_CHOICES加入一个元素解析出2个特殊变量
TARGET_PRODUCT, TARGET_BUILD_VARIANT
这2个变量在dumpvar或者编译时有意义,配置"Product"时意义不大,因为AOSP会解析当前AOSP中的所有"Product"。
(2)获取/解析"Product" 入口在 build/core/config.mk,中间会使用使用到
build/core/envsetup.mk;build/core/product_config.mk; build/core/node_fns.mk; build/core/product.mk
1. 使用find查找出 AndroidProducts.mk :
参考: get-product-makefiles; get-all-product-makefiles;_find-android-products-files;
2. 将搜索到的所有AndroidProducts.mk依次导入(即make解析)
AndroidProducts.mk中定义特殊变量 PRODUCT_MAKEFILES表示"Product"的真实Makefile; 这样所有的AndroidProducts.mk就会引入多个"Product"(单个AndroidProducts.mk也允许定义多个"Product"),这样就形成一个"Product" 列表.
"什么是Product?" : 一个"Product" 可以认为是一个Makefile, 这个Makefile由AndroidProducts.mk注册。
(3)AOSP编译系统尝试导入所有 "Product"(对应的Makeifle)
可以参考 resolve-short-product-name; check-all-products; import-products; import-nodes;
(核心函数import-nodes,利用栈和递归算法实现多个"Product"可以继承,并完成AOSP中所有的"Product"的解析,并记录在全局表 PRODUCTS, ALL_PRODUCTS中,以及特定的格式变量"PRODUCTS.MAKEFILE.PRODUCT_XXX")
import-products/import-nodes实际上就是读取某个Makefile(此Makefile代表一个"Product"),并就地(make)解析此Makefile中的变量 (变量列表请参考_product_var_list,为AOSP build系统的要求/标准化)。然后将此"Product"(一个简称) 与当前Makefile、_product_var_list表中要求的变量列表关联。因此:
"什么是Product?" : 一个"Product" 可以认为是一个Makefile及其标准化的变量列表。
(4) 检查当前AOSP总的"Product"是否合法
$(check-all-products) # 检测名称是否定义,是否冲突,是否符合规范。
(5)解析 "Product"的中特殊变量(该变量与Board相关)
INTERNAL_PRODUCT := $(call resolve-short-product-name, $(TARGET_PRODUCT))
TARGET_DEVICE := $(PRODUCTS.$(INTERNAL_PRODUCT).PRODUCT_DEVICE)
TARGET_DEVICE_DIR := $(patsubst %/,%,$(dir $(board_config_mk)))
(6) 解析 "Product"的Board
同样的方法查找BoardConfig.mk(board_config_mk表示搜索到的与TARGET_DEVICE紧密关联的特殊文件"BoardConfig.mk", 具体细节参考 build/core/envsetup.mk关于 "BoardConfig.mk"文件查找)。
以"include $(board_config_mk)"语法就地导入该"BoardConfig.mk"。
(7)检测 TARGET_ARCH (即只要要求在 BoardConfig.mk中需要定义 TARGET_ARCH变量,是否可以在"product" 的Makefile中定义呢?)
"什么是Board?" :
一个"Board" 存在于一个"Product"之上。
且这个"Board"必须以"PRODUCT_DEVICE"登记于 "Product"的Makeifle中。
一个"Board"代表一个目录(目录名同PRODUCT_DEVICE),且该目录下必须有特殊Makefile : "BoardConfig.mk"
(8)因为AOSP 编译只会编译一个"Product", 因此在多个"Product"共存的AOSP中,通过lunch选择用户需要的编译的"Product": "TARGET_PRODUCT"
阅读(2810) | 评论(0) | 转发(0) |