初始化编译环境,选择产品

envsetup.sh脚本

不开启 subshell

接下来需要初始化编译环境,命令如下:

source命令就是用于运行shell脚本命令,功能等价于”.”,

# 不开启 子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变量。
  • 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函数

  • 扫描和加载所有可用的vendorsetup.sh文件。

  • 默认情况下,编译系统扫描:/vendor//device/ 目录下的 vendorsetup.sh脚本,

  • 并执行这些vendorsetup.sh脚本。

/build/envsetup.sh
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编译,大体流程是。具体流程见下文。

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

build/target
	/board
	/product

编译选项解析层级

配置文件可以按照层级进行分类

配置文件目录

AOSP 预制

Product 配置文件的目录:AOSP 预制 build/target

build/target
	/board
	/product

例如:对于 x86_64 模拟器

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

device/
	qcom/ # 公司名
		qssi_64/...	# 产品名
		pineapple/... # 产品名
	google/ # 公司名
		marlin/.. # 产品名
		wahoo/.. # 产品名
	... # 公司名
  • 若干厂商,例如 googleamlogicqcom
  • 以公司名和产品名划分两个子级目录

lunch命令

作用

lunch命令是envsetup.sh里定义的一个命令,source build/envsetup.sh命令执行成功后,可以使用。

lunch 的每一个选项就是一个 Product。用来让用户

  • 定义Product和编译过程中用到的全局变量,
  • 指定此次编译的目标设备,编译目标

例如:对于 x86_64 模拟器

source build/envsetup.sh
# Product 是 aosp_x86_64-eng
# 加载Product配置文件
lunch aosp_x86_64-eng
编译目标

编译目标由两部分组成:编译目标 BUILD - 编译类型 BUILDTYPE

lunch BUILD-BUILDTYPE

例如:

#  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

此外,还有一些单词代表了特定的设备

BUILDTYPE 编译类型
分类

BUILD TYPE 指的是编译类型,包括 useruserdebugeng

user:最终用户机,通常用来发布最终的上市版本。

  • 编译出的系统有一定的权限限制,(如没有root权限,没有dedug权限等

userdebug:调试测试机,通常用于调试目的

  • 在user版本的基础上,开放root权限和debug权限。

eng:工程机,开发工程师的版本

  • 拥有最大的权限(root等)
  • 附带许多debug工具。

-tests:测试机

详细功能差别
设定属性
lunch选单

如果不知道有哪些产品类型可选,可以:lunch命令,显示出当前工程已经配置过的所有产品类型

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.shadd_lunch_combo函数

过去:

  • vendorsetup.sh中调用,envsetup.shadd_lunch_combo函数
  • 现疑似被淘汰
# 添加到lunch 提供的选单
add_lunch_combo full_toro_userdebug
build/envsetup.sh
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
# 例如:x86_64 模拟器 对应 lunch aosp_x86_64-eng
/build/target/product/AndroidProducts.mk
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 \	# 关注的编译目标-编译类型
# 其他产品
/device/google/marlin/AndroidProducts.mk
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中)

示例

/device/google/marlin/AndroidProducts.mk
PRODUCT_MAKEFILES := \
	$(LOCAL_DIR)/aosp_marlin.mk \
	$(LOCAL_DIR)/aosp_sailfish.mk

COMMON_LUNCH_CHOICES := \
	aosp_marlin-userdebug \
	aosp_sailfish-userdebug
/device/qcom/lahaina/AndroidProducts.mk
PRODUCT_MAKEFILES := \
   $(LOCAL_DIR)/lahaina.mk

COMMON_LUNCH_CHOICES := \
        lahaina-userdebug
        # 还可以 有 lahaina-eng  lahaina-user etc...
编译目标.mk

这个PRODUCT_MAKEFILES就是 lunch 提到的 Product 名,BUILD.mk编译目标.mk

device/qcom/lahaina/lahaina.mk
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)
#if defined(PXLW_IRIS)
-include vendor/pixelworks/libirisservice/config/pixelworks_iris.mk
#endif /* defined(PXLW_IRIS) */
PRODUCT_ 变量
分类

其中定义了一些 PRODUCT_ 变量,可分为一下几类:

  • 通用变量
PRODUCT_BRAND := Android
PRODUCT_NAME := sdk_phone_x86_64
PRODUCT_DEVICE := generic_x86_64
PRODUCT_MODEL := Android SDK built for x86_64
  • 路径变量
SRC_TARGET_DIR # 其值为 build/target
LOCAL_DIR # 当前目录
  • 自定义变量,表示该变量如何使用, 取决于自己,如:
BOARD_DDR_VAR_ENABLED := true
  • 功能变量:表示改变量有特殊功能
# 拷贝,将源码中的文件拷贝到编译好的分区文件中
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 \
常用
示例
device/qcom/lahaina/lahaina.mk
# 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

# device/qcom/lahaina/lahaina.mk
-include vendor/pixelworks/libirisservice/config/pixelworks_iris.mk
# vendor/pixelworks/libirisservice/config/pixelworks_iris.mk
BOARD_HAS_PXLW_IRIS := true

具体内容看下一大章。

mtk
# alps/device/mediatek/vendor/common/device.mk
-include vendor/pixelworks/libirisservice/config/mtk_pixelworks_iris.mk
# alps/vendor/pixelworks/libirisservice/config/mtk_pixelworks_iris.mk
-include vendor/pixelworks/libirisservice/config/pixelworks_iris_enable.mk
# alps/vendor/pixelworks/libirisservice/config/pixelworks_iris_enable.mk

# Comment this line to disable pixelworks iris
BOARD_HAS_PXLW_IRIS := true
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
device/mediatek/vendor/common/device.mk
device/mediatek/vendor/common/device-vext.mk
vendor/pixelworks/libirisservice/config/mtk_pixelworks_iris_vext.mk
vendor/pixelworks/libirisservice/config/pixelworks_iris_enable.mk
# Comment this line to disable pixelworks iris
BOARD_HAS_PXLW_IRIS := true

BoardConfig.mk 硬件

BoardConfig.mk 用于硬件相关配置,有一个基本的了解即可一般很少改动。

# ...
include build/make/target/board/BoardConfigGsiCommon.mk
include build/make/target/board/BoardConfigEmuCommon.mk
# ...

通过 include 包含了 两个配置文件

  • BoardConfigGsiCommon.mk 用于通用系统映像的配置,
  • BoardConfigEmuCommon.mk 用于模拟器的配置

对于 aosp_x86_64 模拟器而言,其硬件配置如下:

build/target/board/generic_arm64/BoardConfig.mk

添加产品示例

流程

复习一下:假设我开了一家叫pxlw的公司,希望添加产品irisX。那么我需要准备

  • 选择目标目录
#一般选择/device目录下
/device/pxlw/irisX
  • lunch 选单
# 在目标目录下放置 AndroidProducts.mk
# # 其中添加
COMMON_LUNCH_CHOICES := \
    irisX-eng \
    irisX-userdebug \
    irisX-user \
  • lunch 编译选项
# 同样是在 AndroidProducts.mk 中
# # 指定 product名.mk
PRODUCT_MAKEFILES := \
    $(LOCAL_DIR)/irisX.mk \
  • 板级特性
# 刚刚设置的 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
  • 硬件特性
# 在目标目录下放置 BoardConfig.mk
# 例如,这里我们直接使用 aosp_x86_64 的 BoardConfig.mk
# 拷贝 build/target/board/generic_x86_64/BoardConfig.mk 至
/device/pxlw/irisX/BoardConfig.mk

命令

source build/envsetup.sh
lunch irisX-eng
# # 这里照抄的Product 是 aosp_x86_64-eng
# 实际约等于 lunch aosp_x86_64-eng
make
emulator
02-27 03:08