Android构建系统 - 02 初始化编译环境,添加产品

发布于:2025-02-26 ⋅ 阅读:(21) ⋅ 点赞:(0)

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

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

查找vendor/<-厂商目录>/和vendor/<厂商目录>/build/目录下的vendorsetup.sh

如果存在的话,加载执行它,添加厂商自己定义产品的编译选项

  • 扫描和加载所有可用的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

编译选项解析层级

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

层级 作用 目录
芯片架构层(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

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

    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 指的是编译类型,包括 useruserdebugeng

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命令,显示出当前工程已经配置过的所有产品类型

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 \
常用
变量 含义
PRODUCT_NAME 产品名称。显示在系统设置中的“关于设备”选项卡中
PRODUCT_DEVICE 设备名称
PRODUCT_BRAND 产品所属品牌
PRODUCT_MANUFACTURER 产品生产商
PRODUCT_MODEL 产品型号
PRODUCT_OVERRIDES 用于重载系统属性。格式:key=valuero.product.firmware=v0.4rc1。属性最终被存储在系统设备的/system/build.prop文件中
PRODUCT_PACKAGES 系统需要预装的一系列程序,如 APKs
PRODUCT_LOCALES 所支持的国家语言 [两字节语言码]-[两字国家码]en_GB de_DE
PRODUCT_TAGS 一系列以空格分隔的产品标签描述
PRODUCT_POLICY 本产品遵循的策略。如:android.policy_phoneandroid.policy_mid
示例
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 用于硬件相关配置,有一个基本的了解即可一般很少改动。

定义和硬件相关的底层特性和变量,比如当前源码支持的 cpu 位数(64/32位),bootloader 和 kernel, 是否支持摄像头,GPS导航等一些板级特性。

# ...
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
  • 硬件特性

具体见后续 执行编译 - vendor编译 - BoardConfig.mk。涉及到编译流程,放在后续介绍。

# 在目标目录下放置 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

网站公告

今日签到

点亮在社区的每一天
去签到