文章目录
- 初始化编译环境,选择产品
-
- envsetup.sh脚本
-
- [不开启 subshell](#不开启 subshell)
- 作用
-
- 提供实用函数
- 添加编译选项
- [查找/执行 其它vendorsetup.sh](#查找/执行 其它vendorsetup.sh)
- [lunch Product](#lunch Product)
-
- [Product 概念](#Product 概念)
- 编译选项解析层级
- 配置文件目录
-
- [AOSP 预制](#AOSP 预制)
- 芯片及方案厂商
- lunch命令
- [板级特性 AndroidProducts.mk](#板级特性 AndroidProducts.mk)
-
- [人工添加 lunch选单列表](#人工添加 lunch选单列表)
- [人工添加 编译选项](#人工添加 编译选项)
-
- PRODUCT_MAKEFILES
- 编译目标.mk
- [PRODUCT_ 变量](#PRODUCT_ 变量)
- 分类
- 常用
- 示例
- inherit-product
- [pxlw include](#pxlw include)
- [BoardConfig.mk 硬件](#BoardConfig.mk 硬件)
- 添加产品示例
初始化编译环境,选择产品
envsetup.sh脚本
不开启 subshell
接下来需要初始化编译环境,命令如下:
source命令就是用于运行shell脚本命令,功能等价于".",
sh
# 不开启 子shell
source build/envsetup.sh
. build/envsetup.sh
# 开启 子shell
bash build/envsetup.sh
sh build/envsetup.sh
./build/envsetup.sh
注释:不使用source或.
会启用一个子shell
-
source
和.
执行脚本,只在当前的shell环境中生效 -
开启subshell
- 开启subshell运行命令
- 指定解释器运行脚本(
bash, sh
),开启子shell运行脚本命令 ./脚本
,通过解释器运行,
- 指定解释器运行脚本(
- 子shell,不保留当前的shell变量。
- 开启subshell运行命令
-
source build/envsetup.sh
命令:将envsetup.sh里的所有命令加载到环境变量里去。
作用
提供实用函数
可以根据需求修改envsetup.sh
-
将envsetup.sh里的所有命令加载到环境变量里去。
-
文件
envsetup.sh
中的内容:记录着编译过程中所需的各种函数实现,所有的编译命令都在
envsetup.sh
文件能找到相对应的function其中就包括编译时使用到的函数命令,如:help,lunch,描述编译的命令:m,mm,mmm等,
-
声明 当前会话终端可用的命令,其他终端仍然不可使用。
- 这里需要注意的是当前会话终端,也就意味着每次新打开一个终端都必须再一次执行这些指令。
- 新开的终端不能直接执行make指令。
添加编译选项
添加了两个编译选项
- generic-eng和simulator
- 这两个选项是系统默认选项
查找/执行 其它vendorsetup.sh
扫描 执行 vendorsetup.sh
在envsetup.sh
末尾执行source_vendorsetup函数
。
查找vendor/<-厂商目录>/和vendor/<厂商目录>/build/目录下的vendorsetup.sh
如果存在的话,加载执行它,添加厂商自己定义产品的编译选项
-
扫描和加载所有可用的
vendorsetup.sh
文件。 -
默认情况下,编译系统扫描:
/vendor/
,/device/
目录下的vendorsetup.sh
脚本, -
并执行这些
vendorsetup.sh
脚本。
sh
/build/envsetup.sh
makefile
function source_vendorsetup() {
for f in $(cd "$T" && find -L device vendor product -maxdepth 4 -name 'allowed-vendorsetup_sh-files' 2>/dev/null | sort); do
# ...
}
# 文件结尾,执行该函数 调用 vendorsetup.sh 们
source_vendorsetup
这就到了下一大章节的 Iris vendor qcom编译,大体流程是。具体流程见下文。
sh
envsetup.sh::source_vendorsetup # 执行扫描到的 vendorsetup.sh 们
build/soong/ui/build/finder.go # 找到 AndroidProducts.mk
# 添加到选单, 为lunch命令添加一条加载项
AndroidProducts.mk::COMMON_LUNCH_CHOICES
AndroidProducts.mk::PRODUCT_MAKEFILES
lahaina.mk
pixelworks_iris.mk
lunch Product
Product 概念
什么是 Product
- Product是一系列的配置文件,通过配置文件实现 "分包" 。
- 巨大的Makefile,类似于CMAKE,Gradle的巨大plus mix版本
- 这一系列的配置文件我们称为 Product。
作用:
- 将同一套Android 系统源码,编译成不同的系统镜像文件img,用于不同的硬件产品。
- 将源码配置为不同的 Product,每一个 Product 适用于特定的硬件产品
- 例如
- 小米 12s,小米12s pro,小米12s ultra 均源于骁龙8+平台。
- 对应于 x86_64 模拟器,选择的是 aosp_x86_64-eng
AOSP 预制了很多 Product。 build/target
芯片及方案厂商也提供了很多Product device
shell
build/target
/board
/product
编译选项解析层级
配置文件可以按照层级进行分类
层级 | 作用 | 目录 |
---|---|---|
芯片架构层(Architecture) | 产品所采用的硬件架构(arm,x86) | |
核心板层(Board) | 硬件电路的核心板层配置 | board |
设备层(Device) | 外围设备的配置(有没有键盘) | device |
产品层(Product) | 最终生成的系统需要包含的软件模块和配置(是否有摄像头应用程序,默认支持哪些语言) | product |
/device/vendor company1 - qcom company2 company3 procuct - lahaina procuct2 AndroidProducts.mk BoardConfig.mk vendorsetup.sh device.mk 配置文件...
配置文件目录
AOSP 预制
Product 配置文件的目录:AOSP 预制 build/target
shell
build/target
/board
/product
例如:对于 x86_64 模拟器
shell
source build/envsetup.sh
# Product 是 aosp_x86_64-eng
# 加载Product配置文件
lunch aosp_x86_64-eng
# # build/target/product/AndroidProducts.mk
# # build/target/product/aosp_x86_64.mk
芯片及方案厂商
Product 配置文件的目录:芯片及方案厂商提供 device
shell
device/
qcom/ # 公司名
qssi_64/... # 产品名
pineapple/... # 产品名
google/ # 公司名
marlin/.. # 产品名
wahoo/.. # 产品名
... # 公司名
- 若干厂商,例如
google
,amlogic
,qcom
... - 以公司名和产品名划分两个子级目录
lunch命令
作用
lunch
命令是envsetup.sh
里定义的一个命令,source build/envsetup.sh
命令执行成功后,可以使用。
lunch 的每一个选项就是一个 Product。用来让用户
- 定义Product和编译过程中用到的全局变量,
- 指定此次编译的目标设备,编译目标
例如:对于 x86_64 模拟器
shell
source build/envsetup.sh
# Product 是 aosp_x86_64-eng
# 加载Product配置文件
lunch aosp_x86_64-eng
编译目标
编译目标由两部分组成:编译目标
BUILD - 编译类型
BUILDTYPE
sh
lunch BUILD-BUILDTYPE
例如:
sh
# BUILD编译目标:aosp_arm
# BUILDTYPE类型:eng
lunch aosp_arm-eng
BUILD
编译目标
特定功能的组合的特定名称
BUILD
指的是特定功能的组合的特定名称,即表示编译出的镜像可以运行在什么环境。
-
aosp(Android Open Source Project)代表Android开源项目
-
处理器
- arm表示系统是运行在arm架构的处理器上
- arm64则是指64位arm架构处理器,
- x86则表示x86架构的处理器;
-
lahaina
lunch lahaina-userdebug
BUILD是lahaina,BUILDTYPE是userdebug.
此外,还有一些单词代表了特定的设备
BUILD | 设备 | 备注 |
---|---|---|
Full | 模拟器 | 全编译,包括所有的语言、应用程序、输入法等 |
full_maguro | maguro | 全编译,并且运行于 Galaxy Nexus GSM/HSPA+("maguro") |
full_panda | panda | 全编译,并且运行于 PandaBoard("panda") |
BUILDTYPE
编译类型
分类
BUILD TYPE 指的是编译类型,包括 user
,userdebug
,eng
user
:最终用户机,通常用来发布最终的上市版本。
- 编译出的系统有一定的权限限制,(如没有root权限,没有dedug权限等
userdebug
:调试测试机,通常用于调试目的
- 在user版本的基础上,开放root权限和debug权限。
eng
:工程机,开发工程师的版本
- 拥有最大的权限(root等)
- 附带许多debug工具。
-tests
:测试机
详细功能差别
编译类型 | 模块的安装标签 |
adb功能(默认) | Proguard 混淆器 | Proguard DEXPREOPT 预先编译优化 |
---|---|---|---|---|
user | user | 关闭 | 打开 | 打开 |
userdebug | user、debug | 打开 | 打开 | 打开 |
eng | user、debug、eng | 打开 | 关闭 | 关闭 |
设定属性
属性 | 用途 |
---|---|
ro.secure | 安全检查功能 |
ro.debuggable | 应用调试功能 |
ro.kernel.android.checkjni | JNI 调用检查 |
编译类型 | ro.secure | ro.debuggable | ro.kernel.android.checkjni |
---|---|---|---|
user | 1 | 0 | 0 |
userdebug | 1 | 1 | 0 |
eng | 0 | 1 | 1 |
lunch选单
如果不知道有哪些产品类型可选,可以:lunch
命令,显示出当前工程已经配置过的所有产品类型
sh
lunch
lunch提供的列表是由开发者在 vendorsetup.sh 或 其他文件中提供的,这个列表不是必须的。
那么怎么添加这个列表选单呢?怎么执行lunch之后的编译呢?见下文 ------ COMMON_LUNCH_CHOICES
那么不管能不能在选单里找到,新问题是一个编译选项是怎么被解析的呢?换句话说lunch BUILD-BUILDTYPE
是如何验证/解析 BUILD 和BUILDTYPE 的呢? 见下文 ------ PRODUCT_MAKEFILES
板级特性 AndroidProducts.mk
人工添加 lunch选单列表
为lunch命令添加一条加载项,lunch 提供的选单是基于如下系统变量产生。
[depracate]add_lunch_combo
envsetup.sh
的 add_lunch_combo函数
过去:
vendorsetup.sh
中调用,envsetup.sh
的add_lunch_combo函数
- 现疑似被淘汰
makefile
# 添加到lunch 提供的选单
add_lunch_combo full_toro_userdebug
sh
build/envsetup.sh
makefile
function add_lunch_combo()
{
if [ -n "$ZSH_VERSION" ]; then
echo -n "${funcfiletrace[1]}: "
else
echo -n "${BASH_SOURCE[1]}:${BASH_LINENO[0]}: "
fi
echo "add_lunch_combo is obsolete. Use COMMON_LUNCH_CHOICES in your AndroidProducts.mk instead."
}
COMMON_LUNCH_CHOICES
在 板级特性 AndroidProducts.mk
中 添加 COMMON_LUNCH_CHOICES,以支持某样Product出现在lunch展示的选单中:
实际上不止存在一个 AndroidProducts.mk
,但每个中都需要指明两项:
- COMMON_LUNCH_CHOICES -
编译目标-编译类型
即BUILD-BUILDTYPE
:aosp_arm- 这里就是
lunch
时,出现的选单列表
- PRODUCT_MAKEFILES
编译目标.mk
- 选单列表执行后,去进一步查找的 makefile
shell
# 例如:x86_64 模拟器 对应 lunch aosp_x86_64-eng
/build/target/product/AndroidProducts.mk
shell
ifneq ($(TARGET_BUILD_APPS),) # app开发
# ...
else # 系统开发 全编译,走这里
PRODUCT_MAKEFILES := \
# ...
# # 关注的编译目标.mk
# # /build/target/product/aosp_x86_64.mk
$(LOCAL_DIR)/aosp_x86_64.mk \
# 前文提到的 COMMON_LUNCH_CHOICES
COMMON_LUNCH_CHOICES := \
# ...
aosp_x86_64-eng \ # 关注的编译目标-编译类型
shell
# 其他产品
/device/google/marlin/AndroidProducts.mk
shell
PRODUCT_MAKEFILES := \
$(LOCAL_DIR)/aosp_marlin.mk \
COMMON_LUNCH_CHOICES := \
aosp_marlin-userdebug \
人工添加 编译选项
PRODUCT_MAKEFILES
那么不管能不能在选单里找到,新问题是一个编译选项是怎么被解析的呢?换句话说lunch BUILD-BUILDTYPE
是如何验证/解析 BUILD 和BUILDTYPE 的呢?
这就是刚刚在AndroidProducts.mk
中同时出现的 PRODUCT_MAKEFILES
AndroidProducts.mk中,
-
通过
PRODUCT_MAKEFILES
来指向 指定商品的属性的makefile -
为了便于维护,存在(新增)若干个以Product命名的 makefile
- 实现涉及到的某产品专用的makefile文件
- 与 lunch 的 BUILD 相对应(在这里就是 lahaina.mk)
其中,可以使用编译系统提供的全局变量或函数来完成所需功能。
- 编译结束后复制到设备系统中的文件
- 设置系统属性(/system下build.prop中)
- ...
示例
shell
/device/google/marlin/AndroidProducts.mk
shell
PRODUCT_MAKEFILES := \
$(LOCAL_DIR)/aosp_marlin.mk \
$(LOCAL_DIR)/aosp_sailfish.mk
COMMON_LUNCH_CHOICES := \
aosp_marlin-userdebug \
aosp_sailfish-userdebug
sh
/device/qcom/lahaina/AndroidProducts.mk
makefile
PRODUCT_MAKEFILES := \
$(LOCAL_DIR)/lahaina.mk
COMMON_LUNCH_CHOICES := \
lahaina-userdebug
# 还可以 有 lahaina-eng lahaina-user etc...
编译目标.mk
这个PRODUCT_MAKEFILES就是 lunch 提到的 Product 名,BUILD.mk
即 编译目标.mk
。
sh
device/qcom/lahaina/lahaina.mk
sh
BUILD_BROKEN_DUP_RULES := true
TEMPORARY_DISABLE_PATH_RESTRICTIONS := true
# Default Android A/B configuration
ENABLE_AB ?= true
ENABLE_VIRTUAL_AB := true
$(call inherit-product, $(SRC_TARGET_DIR)/product/virtual_ab_ota.mk)
#Enable vm support
TARGET_ENABLE_VM_SUPPORT := true
$(call inherit-product, $(SRC_TARGET_DIR)/product/emulated_storage.mk)
makefile
#if defined(PXLW_IRIS)
-include vendor/pixelworks/libirisservice/config/pixelworks_iris.mk
#endif /* defined(PXLW_IRIS) */
PRODUCT_ 变量
分类
其中定义了一些 PRODUCT_ 变量,可分为一下几类:
- 通用变量:
makefile
PRODUCT_BRAND := Android
PRODUCT_NAME := sdk_phone_x86_64
PRODUCT_DEVICE := generic_x86_64
PRODUCT_MODEL := Android SDK built for x86_64
- 路径变量:
shell
SRC_TARGET_DIR # 其值为 build/target
LOCAL_DIR # 当前目录
- 自定义变量,表示该变量如何使用, 取决于自己,如:
shell
BOARD_DDR_VAR_ENABLED := true
- 功能变量:表示改变量有特殊功能
makefile
# 拷贝,将源码中的文件拷贝到编译好的分区文件中
PRODUCT_COPY_FILES += vendor/rockchip/common/phone/etc/spn-conf.xml:system/etc/spn-conf.xml
# 设置系统属性(覆盖)
PRODUCT_PROPERTY_OVERRIDES += \
ro.product.version = 1.0.0 \
常用
变量 | 含义 |
---|---|
PRODUCT_NAME |
产品名称。显示在系统设置中的"关于设备"选项卡中 |
PRODUCT_DEVICE |
设备名称 |
PRODUCT_BRAND |
产品所属品牌 |
PRODUCT_MANUFACTURER |
产品生产商 |
PRODUCT_MODEL |
产品型号 |
PRODUCT_OVERRIDES |
用于重载系统属性。格式:key=value 。 ro.product.firmware=v0.4rc1 。属性最终被存储在系统设备的/system/build.prop 文件中 |
PRODUCT_PACKAGES |
系统需要预装的一系列程序,如 APKs |
PRODUCT_LOCALES |
所支持的国家语言 [两字节语言码]-[两字国家码] 如en_GB de_DE |
PRODUCT_TAGS |
一系列以空格分隔的产品标签描述 |
PRODUCT_POLICY |
本产品遵循的策略。如:android.policy_phone ,android.policy_mid |
示例
sh
device/qcom/lahaina/lahaina.mk
makefile
# privapp-permissions whitelisting (To Fix CTS :privappPermissionsMustBeEnforced)
PRODUCT_PROPERTY_OVERRIDES += ro.control_privapp_permissions=enforce
TARGET_DEFINES_DALVIK_HEAP := true
$(call inherit-product, device/qcom/vendor-common/common64.mk)
$(call inherit-product, frameworks/native/build/phone-xhdpi-6144-dalvik-heap.mk)
# beluga settings
PRODUCT_PROPERTY_OVERRIDES += \
ro.vendor.beluga.p=0x3 \
ro.vendor.beluga.c=0x4800 \
ro.vendor.beluga.s=0x900 \
ro.vendor.beluga.t=0x240
###########
# Target naming
PRODUCT_NAME := lahaina
PRODUCT_DEVICE := lahaina
PRODUCT_BRAND := qti
PRODUCT_MODEL := Lahaina for arm64
inherit-product
假设 PRODUCT_VAR := a 在 A.mk 中, PRODUCT_VAR := b 在 B.mk 中。
在 A.mk 中
-
include B.mk
,得到PRODUCT_VAR := b
-
inherit-product B.mk
,-
得到 PRODUCT_VAR := a b
-
并确保不会两次包含同一个 makefile
-
pxlw include
qcom
pixelworks_iris.mk
在 lahaina.mk中,pixelworks_iris.mk
被引入编译。设置了BOARD_HAS_PXLW_IRIS
此时的调用栈为 AndroidProducts.mk::PRODUCT_MAKEFILES
lahaina.mk
pixelworks_iris.mk
sh
# device/qcom/lahaina/lahaina.mk
-include vendor/pixelworks/libirisservice/config/pixelworks_iris.mk
shell
# vendor/pixelworks/libirisservice/config/pixelworks_iris.mk
BOARD_HAS_PXLW_IRIS := true
具体内容看下一大章。
mtk
sh
# alps/device/mediatek/vendor/common/device.mk
-include vendor/pixelworks/libirisservice/config/mtk_pixelworks_iris.mk
sh
# alps/vendor/pixelworks/libirisservice/config/mtk_pixelworks_iris.mk
-include vendor/pixelworks/libirisservice/config/pixelworks_iris_enable.mk
sh
# alps/vendor/pixelworks/libirisservice/config/pixelworks_iris_enable.mk
# Comment this line to disable pixelworks iris
BOARD_HAS_PXLW_IRIS := true
sh
device/mediatek/system/common/device.mk
vendor/pixelworks/libirisservice/config/mtk_pixelworks_iris_sys.mk
vendor/pixelworks/libirisservice/config/pixelworks_iris_enable.mk
设置 BOARD_HAS_PXLW_IRIS
sh
device/mediatek/vendor/common/device.mk
sh
device/mediatek/vendor/common/device-vext.mk
sh
vendor/pixelworks/libirisservice/config/mtk_pixelworks_iris_vext.mk
sh
vendor/pixelworks/libirisservice/config/pixelworks_iris_enable.mk
sh
# Comment this line to disable pixelworks iris
BOARD_HAS_PXLW_IRIS := true
BoardConfig.mk 硬件
BoardConfig.mk 用于硬件相关配置,有一个基本的了解即可一般很少改动。
定义和硬件相关的底层特性和变量,比如当前源码支持的 cpu 位数(64/32位),bootloader 和 kernel, 是否支持摄像头,GPS导航等一些板级特性。
makefile
# ...
include build/make/target/board/BoardConfigGsiCommon.mk
include build/make/target/board/BoardConfigEmuCommon.mk
# ...
通过 include 包含了 两个配置文件
- BoardConfigGsiCommon.mk 用于通用系统映像的配置,
- BoardConfigEmuCommon.mk 用于模拟器的配置
对于 aosp_x86_64 模拟器而言,其硬件配置如下:
shell
build/target/board/generic_arm64/BoardConfig.mk
添加产品示例
流程
复习一下:假设我开了一家叫pxlw的公司,希望添加产品irisX。那么我需要准备
- 选择目标目录
shell
#一般选择/device目录下
/device/pxlw/irisX
- lunch 选单
shell
# 在目标目录下放置 AndroidProducts.mk
# # 其中添加
COMMON_LUNCH_CHOICES := \
irisX-eng \
irisX-userdebug \
irisX-user \
- lunch 编译选项
shell
# 同样是在 AndroidProducts.mk 中
# # 指定 product名.mk
PRODUCT_MAKEFILES := \
$(LOCAL_DIR)/irisX.mk \
- 板级特性
shell
# 刚刚设置的 product名.mk 即 irisX.mk
# 这里拷贝自 build/make/target/product/aosp_x86_64.mk
# 其中,需要额外指定一系列 PRODUCT_ 变量
# Overrides
PRODUCT_BRAND := pxlw
PRODUCT_NAME := irisX
PRODUCT_DEVICE := irisX
PRODUCT_MODEL := Android SDK built for x86_64 irisX
- 硬件特性
具体见后续
执行编译
-vendor编译
-BoardConfig.mk
。涉及到编译流程,放在后续介绍。
shell
# 在目标目录下放置 BoardConfig.mk
# 例如,这里我们直接使用 aosp_x86_64 的 BoardConfig.mk
# 拷贝 build/target/board/generic_x86_64/BoardConfig.mk 至
/device/pxlw/irisX/BoardConfig.mk
命令
shell
source build/envsetup.sh
lunch irisX-eng
# # 这里照抄的Product 是 aosp_x86_64-eng
# 实际约等于 lunch aosp_x86_64-eng
make
emulator