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

news/2025/2/26 13:48:55

文章目录

  • 初始化编译环境,选择产品
    • envsetup.sh脚本
      • 不开启 subshell
      • 作用
        • 提供实用函数
        • 添加编译选项
        • 查找/执行 其它vendorsetup.sh
    • lunch Product
      • Product 概念
      • 编译选项解析层级
      • 配置文件目录
        • AOSP 预制
        • 芯片及方案厂商
      • lunch命令
        • 作用
        • 编译目标
          • `BUILD` 编译目标
          • `BUILDTYPE` 编译类型
            • 分类
            • 详细功能差别
            • 设定属性
        • lunch选单
      • 板级特性 AndroidProducts.mk
        • 人工添加 lunch选单列表
          • [depracate]add_lunch_combo
          • COMMON_LUNCH_CHOICES
        • 人工添加 编译选项
          • PRODUCT_MAKEFILES
          • 编译目标.mk
          • PRODUCT_ 变量
          • 分类
          • 常用
          • 示例
          • inherit-product
        • pxlw include
          • qcom
          • mtk
      • BoardConfig.mk 硬件
    • 添加产品示例
      • 流程
      • 命令

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

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_maguromaguro全编译,并且运行于 Galaxy Nexus GSM/HSPA+(“maguro”)
full_pandapanda全编译,并且运行于 PandaBoard(“panda”)
BUILDTYPE 编译类型
分类

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

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

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

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

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

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

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

-tests:测试机

详细功能差别
编译类型模块的安装标签adb功能(默认)Proguard 混淆器Proguard DEXPREOPT 预先编译优化
useruser关闭打开打开
userdebuguser、debug打开打开打开
enguser、debug、eng打开关闭关闭
设定属性
属性用途
ro.secure安全检查功能
ro.debuggable应用调试功能
ro.kernel.android.checkjniJNI 调用检查
编译类型ro.securero.debuggablero.kernel.android.checkjni
user100
userdebug110
eng011
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

http://www.niftyadmin.cn/n/5868791.html

相关文章

React + TypeScript 复杂布局开发实战

React TypeScript 复杂布局开发实战 一、项目架构设计&#xff08;基于最新技术栈&#xff09; 1.1 技术选型与工程创建 # 使用Vite 5.x React 19 TypeScript 5.4 npx create-vitelatest power-designer-ui --template react-ts cd power-designer-ui && npm inst…

Python代码片段-断点任务

使用Python处理一堆长耗时任务的时候&#xff0c;为了防止异常退出程序或者手动退出程序后丢失任务进度&#xff0c;可用使用断点的方式记录任务进度&#xff0c;下次重载任务后&#xff0c;继续运行上次未完成的任务即可。 这里用json文件作为数据持久化的方式&#xff0c;免…

YOLOv10 解析与地平线 征程 6 模型量化

一&#xff0c;YOLOv10 解析 1.简介 近些年来&#xff0c;研究人员对 YOLO 的架构设计、优化目标、数据增强策略等进行了探索&#xff0c;取得了显著进展。然而&#xff0c;后处理对非极大值抑制&#xff08;NMS&#xff09;的依赖阻碍了 YOLO 的端到端部署&#xff0c;并对推…

一个std::async的示例

目录 一、问题引出 二、关键点解释 1.生成随机数 2.异步启动两个操作 3.检查异步任务是否为延迟执行并轮询任务状态 4.等待所有任务完成并处理异常 三、总结 一、问题引出 从《c标准库》&#xff08;第2版&#xff09;看到一个std::async的例子。演示了使用 std::async…

《零基础学会!如何用 sql+Python 绘制柱状图和折线图,数据可视化一看就懂》

在数据驱动的时代&#xff0c;MySQL 是最常用的关系型数据库管理系统之一&#xff0c;广泛应用于各类数据存储和处理场景。数据分析的过程不仅仅是收集数据&#xff0c;还包括数据的清洗、转换、查询以及最终的报告和可视化。在本文中&#xff0c;我们将通过实际案例来介绍如何…

Java+SpringBoot+Vue+数据可视化的音乐推荐与可视化平台(程序+论文+讲解+安装+调试+售后)

感兴趣的可以先收藏起来&#xff0c;还有大家在毕设选题&#xff0c;项目以及论文编写等相关问题都可以给我留言咨询&#xff0c;我会一一回复&#xff0c;希望帮助更多的人。 系统介绍 在互联网技术以日新月异之势迅猛发展的浪潮下&#xff0c;5G 通信技术的普及、云计算能力…

Golang适配达梦数据库连接指定模式

1、达梦官方适配文档&#xff1a;https://eco.dameng.com/document/dm/zh-cn/start/GO_DM_NEW.html 2、连接指定模式方式&#xff1a;dataSourceName : “dm://SYSDBA:*****192.168.40.1:5237?schemaTESTDB” 3、beego orm适配遇到问题&#xff1a; 3.1、q:同一用户下不同模式…

Go Channel 高级模式实战:超时控制与广播机制的深度解析

1. 前言 在 Go 语言的并发世界中&#xff0c;channel 是我们手中的一把利器&#xff0c;它让 goroutine 间的通信变得优雅而高效。如果你已经用 channel 实现过简单的生产者-消费者模型&#xff0c;或者在 select 中处理过并发任务&#xff0c;那么恭喜你&#xff0c;你已经迈…