使用此页面中的信息为您的设备和产品创建 makefile。
每个新的 Android 模块都必须有一个配置文件,以使用模块元数据、编译时依赖项和打包指令来指导构建系统。 Android 使用Soong 构建系统。有关 Android 构建系统的更多信息,请参阅构建 Android 。
了解构建层
构建层次结构包括与设备的物理构成相对应的抽象层。下表描述了这些层。每一层都与它上面的一层以一对多的关系相关。例如,一个架构可以有多个板,每个板可以有多个产品。您可以将给定层中的元素定义为同一层中元素的特化,这消除了复制并简化了维护。
层 | 例子 | 描述 |
---|---|---|
产品 | myProduct、myProduct_eu、myProduct_eu_fr、j2、sdk | 产品层定义了运输产品的功能规范,例如要构建的模块、支持的区域设置以及各种区域设置的配置。换句话说,这是整个产品的名称。产品特定的变量在产品定义 makefile 中定义。一个产品可以继承其他产品的定义,从而简化维护。常见的方法是创建包含适用于所有产品的功能的基础产品,然后基于该基础产品创建产品变体。例如,仅无线电功能不同(CDMA 与 GSM)的两种产品可以继承未定义无线电功能的同一基本产品。 |
板卡/设备 | 马林鱼、蓝线、珊瑚 | 板/设备层代表设备上塑料的物理层(即设备的工业设计)。该层还代表产品的裸原理图。其中包括板上的外围设备及其配置。使用的名称仅仅是不同板/设备配置的代码。 |
拱 | 臂、x86、arm64、x86_64 | 架构层描述了板上运行的处理器配置和应用程序二进制接口(ABI)。 |
使用构建变体
在针对特定产品进行构建时,对最终版本进行细微的修改很有用。在模块定义中,模块可以使用LOCAL_MODULE_TAGS
指定标签,该标签可以是optional
(默认)、 debug
和eng
中的一个或多个值。
如果模块未指定标签(通过LOCAL_MODULE_TAGS
),则其标签默认为optional
。仅当PRODUCT_PACKAGES
的产品配置需要时,才会安装可选模块。
这些是当前定义的构建变体。
变体 | 描述 |
---|---|
eng | 这是默认的口味。
|
user | 该变体旨在成为最终版本。
|
userdebug | 与user 相同,但有以下例外:
|
用户调试指南
在测试中运行 userdebug 构建可以帮助设备开发人员了解开发版本的性能和功能。为了保持用户和 userdebug 版本之间的一致性,并在用于调试的版本中实现可靠的指标,设备开发人员应遵循以下准则:
- userdebug 被定义为启用 root 访问权限的用户构建,但以下情况除外:
- 仅由用户按需运行的仅用于 userdebug 的应用程序
- 仅在空闲维护期间运行的操作(充电器上/充满电),例如使用
dex2oatd
与dex2oat
进行后台编译
- 不包括根据构建类型默认启用/禁用的功能。不鼓励开发人员使用任何影响电池寿命的日志记录形式,例如调试日志记录或堆转储。
- 应明确定义 userdebug 中默认启用的任何调试功能,并与参与该项目的所有开发人员共享。您应该仅在有限的时间内启用调试功能,直到您尝试调试的问题得到解决。
使用资源覆盖自定义构建
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/values/config.xml
在覆盖config.xml
文件中找到的任何字符串或字符串数组都会替换在原始文件中找到的字符串或字符串数组。
构建一个产品
您可以通过多种不同的方式组织设备的源文件。以下是组织 Pixel 实现的一种方法的简要描述。
Pixel 是通过名为marlin
主要设备配置来实现的。根据此设备配置,使用产品定义 makefile 创建产品,该文件声明有关设备的产品特定信息,例如名称和型号。您可以查看device/google/marlin
目录以了解所有这些是如何设置的。
编写产品 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 中的其他特定于产品的变量,请参阅设置产品定义变量。
- 创建指向产品 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
- 创建包含板特定配置的
BoardConfig.mk
makefile。有关示例,请参阅device/google/marlin/BoardConfig.mk
。 - 仅适用于 Android 9 及更低版本,创建一个
vendorsetup.sh
文件,将您的产品(“午餐组合”)以及由破折号分隔的构建变体添加到构建中。例如:add_lunch_combo <product-name>-userdebug
- 此时,您可以基于同一设备创建更多产品变体。
设置产品定义变量
产品特定的变量在产品的 makefile 中定义。该表显示了产品定义文件中维护的一些变量。
多变的 | 描述 | 例子 |
---|---|---|
PRODUCT_AAPT_CONFIG | 创建包时使用的aapt 配置。 | |
PRODUCT_BRAND | 软件定制的品牌(例如运营商)。 | |
PRODUCT_CHARACTERISTICS | aapt 特性允许将特定于变体的资源添加到包中。 | tablet nosdcard |
PRODUCT_COPY_FILES | 像source_path:destination_path 这样的单词列表。构建此产品时,应将源路径中的文件复制到目标路径。复制步骤的规则在config/makefile 中定义。 | |
PRODUCT_DEVICE | 工业品外观设计名称。这也是板名称,构建系统使用它来定位BoardConfig.mk 。 | tuna |
PRODUCT_LOCALES | 以空格分隔的两个字母语言代码、两个字母国家/地区代码对的列表,描述用户的多种设置,例如 UI 语言和时间、日期和货币格式。 PRODUCT_LOCALES 中列出的第一个区域设置用作产品的默认区域设置。 | en_GB 、 de_DE 、 es_ES 、 fr_CA |
PRODUCT_MANUFACTURER | 制造商名称。 | acme |
PRODUCT_MODEL | 最终产品的最终用户可见的名称。 | |
PRODUCT_NAME | 整个产品的最终用户可见的名称。显示在“设置”>“关于”屏幕中。 | |
PRODUCT_OTA_PUBLIC_KEYS | 产品的无线 (OTA) 公钥列表。 | |
PRODUCT_PACKAGES | 要安装的 APK 和模块的列表。 | 日历联系人 |
PRODUCT_PACKAGE_OVERLAYS | 指示是否使用默认资源或添加任何特定于产品的覆盖。 | vendor/acme/overlay |
PRODUCT_SYSTEM_PROPERTIES | 系统分区的系统属性分配列表,格式为"key=value" 。其他分区的系统属性可以通过PRODUCT_<PARTITION>_PROPERTIES 设置,就像供应商分区的PRODUCT_VENDOR_PROPERTIES 中一样。支持的分区名称: SYSTEM 、 VENDOR 、 ODM 、 SYSTEM_EXT 和PRODUCT 。 |
配置默认系统语言和区域设置过滤器
使用此信息配置默认语言和系统区域设置过滤器,然后为新设备类型启用区域设置过滤器。
特性
使用专用系统属性配置默认语言和系统区域设置过滤器:
-
ro.product.locale
:用于设置默认区域设置。它最初设置为PRODUCT_LOCALES
变量中的第一个区域设置;您可以覆盖该值。 (有关详细信息,请参阅设置产品定义变量表。) -
ro.localization.locale_filter
:用于设置区域设置过滤器,使用应用于区域设置名称的正则表达式。例如:- 包含过滤器:
^(de-AT|de-DE|en|uk).*
- 仅允许德语(奥地利和德国变体)、英语的所有英语变体和乌克兰语 - 独家过滤器:
^(?!de-IT|es).*
- 排除德语(意大利变体)和西班牙语的所有变体。
- 包含过滤器:
启用区域设置过滤器
要启用过滤器,请设置ro.localization.locale_filter
系统属性字符串值。
通过在工厂校准期间通过oem/oem.prop
设置过滤器属性值和默认语言,您可以配置限制,而无需将过滤器烘焙到系统映像中。您可以通过将这些属性添加到PRODUCT_OEM_PROPERTIES
变量来确保从 OEM 分区获取这些属性,如下所示:
# Delegation for OEM customization PRODUCT_OEM_PROPERTIES += \ ro.product.locale \ ro.localization.locale_filter
然后在生产中,实际值被写入oem/oem.prop
,以反映目标要求。通过这种方法,在恢复出厂设置期间会保留默认值,因此初始设置对于用户来说看起来与首次设置完全相同。
设置 ADB_VENDOR_KEYS 通过 USB 连接
ADB_VENDOR_KEYS
环境变量使设备制造商能够通过 adb 访问可调试版本(-userdebug 和 -eng,但不是 -user),而无需手动授权。通常,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
如果尚未设置)。