1.理解构建层
构建层次结构包括与设备的物理结构对应的抽象层。下表中介绍了这些层。每一层都与上一层存在一对多的关系。例如,一个架构(ARCH)可以有多个主板(Board/device),一个主板可以有多个产品(Product)。您可以将指定层中的某个元素定义为同一层中某个元素的特化元素,这样可以免去复制操作并简化维护工作。
Layer | Example | Description |
---|---|---|
Product | myProduct, myProduct_eu, myProduct_eu_fr, j2, sdk | The product layer defines the feature specification of a shipping product such as the modules to build, locales supported, and configuration for various locales. In other words, this is the name of the overall product. Product-specific variables are defined in product definition makefiles. A product can inherit from other product definitions, which simplifies maintenance. A common method is to create a base product that contains features that apply to all products, then create product variants based on that base product. For example, two products that differ only by their radios (CDMA versus GSM) can inherit from the same base product that doesn't define a radio. |
Board/device | marlin, blueline, coral | The board/device layer represents the physical layer of plastic on the device (that is, the industrial design of the device). This layer also represents the bare schematics of a product. These include the peripherals on the board and their configuration. The names used are merely codes for different board/device configurations. |
Arch | arm, x86, arm64, x86_64 | The architecture layer describes the processor configuration and application binary interface (ABI) running on the board. |
2.使用build variants
在针对特定产品进行构建时,如果能在最终发布 build 的基础上有细微的变化,会非常有用。在模块定义中,模块可以通过 LOCAL_MODULE_TAGS 指定标记,这些标记可以是以下一个或多个值:optional(默认值)、debug 和 eng。
如果某个模块没有通过 LOCAL_MODULE_TAGS 指定标记,则其标记默认设置为 optional。仅当 PRODUCT_PACKAGES 的产品配置需要可选模块时,系统才会安装可选模块。
下面是当前定义的构建变体(build variants)。
Variant | Description |
---|---|
eng | This is the default flavor. - Installs modules tagged with eng or debug. - Installs modules according to the product definition files, in addition to tagged modules. - ro.secure=0 - ro.debuggable=1 - ro.kernel.android.checkjni=1 - adb is enabled by default. |
user | The variant intended to be the final release bits. - Installs modules tagged with user. - Installs modules according to the product definition files, in addition to tagged modules. - ro.secure=1 - ro.debuggable=0 - adb is disabled by default. |
userdebug | The same as user, with these exceptions: - Also installs modules tagged with debug. - ro.debuggable=1 - adb is enabled by default. |
aosp为build系统提供三种Product配置,文档里叫做build variants,分别是:
- eng : 对应到工程版。编译打包所有模块。表示adbd处于ROOT状态,所有调试开关打开
- userdebug : 对应到用户调试版。打开调试开关,但并没有放开ROOT权限
- user : 对应到用户版。关闭调试开关,关闭ROOT权限。最终发布到用户手上的版本,通常都是user版。
2.1 userdebug的准则
在测试中运行 userdebug build 有助于设备开发者了解开发中版本的性能和功耗。为了让 user build 和 userdebug build 保持一致,并在用于调试的 build 中获得可靠的指标,设备开发者应遵循以下准则:
userdebug 定义为已启用 root 权限的 user build,但以下情况除外:
- 仅由用户视需要运行且仅用于 userdebug build 的应用
- 仅在空闲维护(连接充电器/充满电)期间执行的操作,例如,使用 dex2oatd 而不是 dex2oat 来进行后台编译
- 不要添加根据构建类型默认启用/停用的功能。建议开发者不要使用任何影响电池续航时间的日志记录形式(例如调试日志记录或堆转储)。
- 在 userdebug build 中默认启用的任何调试功能都应明确定义,并告知处理相关项目的所有开发者。您应该只在限定的时间内启用调试功能,直到您尝试调试的问题得到解决。
3. Customizing the build with resource overlays(利用资源叠加层自定义build)
Android 构建系统会在构建时使用资源叠加层来自定义产品。资源叠加层用于指定在默认文件之上应用的资源文件。如需使用资源叠加层,请修改项目构建文件,将 PRODUCT_PACKAGE_OVERLAYS 设为相对于顶级目录的路径。当构建系统搜索资源时,该路径会变为影子根目录,系统除了在当前根目录中进行搜索外,还会一并在该路径中进行搜索。
最常自定义的设置包含在 frameworks/base/core/res/res/values/config.xml 文件中。
如需在此文件上设置资源叠加层,请使用以下某个命令将叠加层目录添加到项目构建文件:
PRODUCT_PACKAGE_OVERLAYS := device/device-implementer/device-name/overlay
例如:
或
PRODUCT_PACKAGE_OVERLAYS := vendor/vendor-name/overlay
然后,将一个叠加层文件添加到该目录下,例如:
vendor/foobar/overlay/frameworks/base/core/res/res/config.xml
在叠加层 config.xml 文件中找到的所有字符串或字符串数组都会替换在原始文件中找到的对应字符串或字符串数组。
4. 构建产品
您可以通过多种不同的方式来组织设备的源文件。下面简要说明了 Pixel 实现的一种组织方式。
为 Pixel 实现名为 marlin 的主设备配置。根据此设备配置,为产品创建产品定义 Makefile,用于声明关于设备的产品特定信息,例如名称和型号。您可以查看 device/google/marlin 目录,了解所有相关配置的具体设置方式。
4.1 编写产品Makefile
以下步骤介绍了如何采用与设置 Pixel 产品线类似的方式设置产品 Makefile:
- 为您的产品创建一个
device/<company-name>/<device-name>
目录。例如,device/google/marlin。此目录将包含您设备的源代码以及构建这些代码所需的 Makefile。 - 创建一个 device.mk Makefile,用来声明设备所需的文件和模块。有关示例,请查看
device/google/marlin/device-marlin.mk
。 - 创建一个产品定义 Makefile,以便基于设备创建具体产品。以下示例 Makefile 来自于 device/google/marlin/aosp_marlin.mk。请注意,该产品会通过 Makefile 沿用 device/google/marlin/device-marlin.mk 和 vendor/google/marlin/device-vendor-marlin.mk 文件中的设置,同时还会声明产品特定信息,例如名称、品牌和型号。
# Inherit from the common Open Source product configuration
$(call inherit-product, $(SRC_TARGET_DIR)/product/core_64_bit.mk)
$(call inherit-product, $(SRC_TARGET_DIR)/product/aosp_base_telephony.mk)
PRODUCT_NAME := aosp_marlin
PRODUCT_DEVICE := marlin
PRODUCT_BRAND := Android
PRODUCT_MODEL := AOSP on msm8996
PRODUCT_MANUFACTURER := Google
PRODUCT_RESTRICT_VENDOR_FILES := true
PRODUCT_COPY_FILES += device/google/marlin/fstab.common:$(TARGET_COPY_OUT_VENDOR)/etc/fstab.marlin
$(call inherit-product, device/google/marlin/device-marlin.mk)
$(call inherit-product-if-exists, vendor/google_devices/marlin/device-vendor-marlin.mk)
PRODUCT_PACKAGES += \
Launcher3QuickStep \
WallpaperPicker
如需了解可添加到 Makefile 的其他产品特定变量,请参阅设置产品定义变量(4.2小节)。
- 创建一个指向产品的 Makefile文件AndroidProducts.mk。在此示例中,仅需要产品定义 Makefile。以下示例来自于 device/google/marlin/AndroidProducts.mk(该文件同时包含 marlin (Pixel) 和 sailfish (Pixel XL),它们共享大部分配置):
PRODUCT_MAKEFILES := \
$(LOCAL_DIR)/aosp_marlin.mk \
$(LOCAL_DIR)/aosp_sailfish.mk
COMMON_LUNCH_CHOICES := \
aosp_marlin-userdebug \
aosp_sailfish-userdebug
- 创建一个包含主板特定配置的Makefile文件BoardConfig.mk 。如需查看示例,请查看 device/google/marlin/BoardConfig.mk。
创建一个 vendorsetup.sh 文件,以便将您的产品(“午餐套餐”)与构建变体(使用短划线将两者分隔开)一起添加到 build 中。例如:
add_lunch_combo <product-name>-userdebug
这一步显得多余了,谷歌已经不建议这样了
- 这时,您就可以基于同一设备创建更多产品变体了。
4.2 设置产品定义变量
产品特定变量在产品的 Makefile 中进行定义。下表显示了在产品定义文件中维护的部分变量。
变量 | 说明 | 示例 |
---|---|---|
PRODUCT_AAPT_CONFIG | aapt configurations to use when creating packages. | |
PRODUCT_BRAND | The brand (for example, carrier) the software is customized for, if any. | |
PRODUCT_CHARACTERISTICS | aapt characteristics to allow adding variant-specific resources to a package. | tablet, nosdcard |
PRODUCT_COPY_FILES | List of words like source_path:destination_path . The file at the source path should be copied to the destination path when building this product. The rules for the copy steps are defined in config/makefile. | |
PRODUCT_DEVICE | Name of the industrial design. This is also the board name, and the build system uses it to locate BoardConfig.mk. | tuna |
PRODUCT_LOCALES | A space-separated list of two-letter language code, two-letter country code pairs that describe several settings for the user, such as the UI language and time, date, and currency formatting. The first locale listed in PRODUCT_LOCALES is used as the product's default locale. | en_GB, de_DE, es_ES, fr_CA |
PRODUCT_MANUFACTURER | Name of the manufacturer. | acme |
PRODUCT_MODEL | End-user-visible name for the end product. | |
PRODUCT_NAME | End-user-visible name for the overall product. Appears in the Settings > About screen. | |
PRODUCT_OTA_PUBLIC_KEYS | List of over-the-air (OTA) public keys for the product. | |
PRODUCT_PACKAGES | List of the APKs and modules to install. | Calendar contacts |
PRODUCT_PACKAGE_OVERLAYS | Indicates whether to use default resources or add any product specific overlays. | vendor/acme/overlay |
PRODUCT_SYSTEM_PROPERTIES | List of the system property assignments in the format "key=value" for the system partition. System properties for other partitions can be set via PRODUCT_<PARTITION>_PROPERTIES as in PRODUCT_VENDOR_PROPERTIES for the vendor partition. Supported partition names: SYSTEM, VENDOR, ODM, SYSTEM_EXT, and PRODUCT. |
4.3 设置ADB_VENDOR_KEYS以通过USB进行连接
借助 ADB_VENDOR_KEYS 环境变量,设备制造商无需手动授权,即可通过 adb 访问可调试的 build(userdebug build 和 eng build,但不能访问 user build)。通常,adb 会为每台客户端计算机生成一个唯一的 RSA 身份验证密钥,并将其发送到所有已连接的设备。这就是 adb 授权对话框中显示的 RSA 密钥。或者,您也可以将已知密钥构建到系统映像中,并将其分享给相应的 adb 客户端。这对于操作系统开发来说很有用,对测试来说尤其有用,因为此做法无需与 adb 授权对话框手动进行交互。
如需创建供应商密钥,应安排一个人(通常为发布管理员)执行以下操作:
- 使用 adb keygen 生成密钥对。对于 Google 设备,Google 会为每个新操作系统版本生成一个新密钥对。
- 将密钥对签入源代码树中的某个位置。例如,Google 会将其存储在 vendor/google/security/adb/ 中。
- 设置构建变体 PRODUCT_ADB_KEYS,使其指向您的密钥目录。为此,Google 会在密钥目录中添加一个 Android.mk 文件,其内容为 PRODUCT_ADB_KEYS := $(LOCAL_PATH)/$(PLATFORM_VERSION).adb_key.pub,以帮助确保我们记得为每个操作系统版本生成新的密钥对。
以下是 Google 在该目录(我们将各版本的已签入密钥对存储在此处)中使用的 Makefile:
PRODUCT_ADB_KEYS := $(LOCAL_PATH)/$(PLATFORM_VERSION).adb_key.pub
ifeq ($(wildcard $(PRODUCT_ADB_KEYS)),)
$(warning ========================)
$(warning The adb key for this release)
$(warning )
$(warning $(PRODUCT_ADB_KEYS))
$(warning )
$(warning does not exist. Most likely PLATFORM_VERSION in build/core/version_defaults.mk)
$(warning has changed and a new adb key needs to be generated.)
$(warning )
$(warning Please run the following commands to create a new key:)
$(warning )
$(warning make -j8 adb)
$(warning LOGNAME=android-eng HOSTNAME=google.com adb keygen $(patsubst %.pub,%,$(PRODUCT_ADB_KEYS)))
$(warning )
$(warning and upload/review/submit the changes)
$(warning ========================)
$(error done)
endif
如需使用这些供应商密钥,工程师只需将 ADB_VENDOR_KEYS 环境变量设为指向存储相应密钥对的目录。这会告知 adb 先尝试这些规范密钥,然后回退到需要手动授权的已生成主机密钥。当 adb 无法连接到未获授权的设备时,系统会显示错误消息,提示您设置 ADB_VENDOR_KEYS(如果尚未设置)。
参考:
评论 (0)