使用此页面中的信息为您的设备和产品创建 makefile。
每个新的 Android 模块都必须有一个配置文件,以使用模块元数据、编译时依赖项和打包指令来指导构建系统。 Android 使用Soong 构建系统。有关 Android 构建系统的更多信息,请参阅构建 Android 。
了解构建层
构建层次结构包括与设备的物理构成相对应的抽象层。这些层在下表中描述。每一层都以一对多的关系与它上面的一层相关。例如,一个架构可以有多个板,每个板可以有多个产品。您可以将给定层中的元素定义为同一层中元素的特化,这消除了复制并简化了维护。
层 | 例子 | 描述 |
---|---|---|
产品 | myProduct, myProduct_eu, myProduct_eu_fr, j2, sdk | 产品层定义了运输产品的功能规范,例如要构建的模块、支持的语言环境以及各种语言环境的配置。换句话说,这是整个产品的名称。产品特定变量在产品定义生成文件中定义。一个产品可以从其他产品定义继承,这简化了维护。一种常见的方法是创建一个包含适用于所有产品的功能的基础产品,然后基于该基础产品创建产品变体。例如,两种仅在无线电方面不同的产品(CDMA 与 GSM)可以继承自未定义无线电的相同基础产品。 |
板/设备 | 马林鱼, blueline, 珊瑚 | 板/器件层代表器件上塑料的物理层(即器件的工业设计)。该层还代表了产品的裸示意图。其中包括板上的外围设备及其配置。使用的名称只是不同板/设备配置的代码。 |
拱 | 手臂,x86,手臂64,x86_64 | 架构层描述了板上运行的处理器配置和应用程序二进制接口 (ABI)。 |
使用构建变体
在为特定产品构建时,对最终版本构建进行细微更改很有用。在模块定义中,模块可以使用LOCAL_MODULE_TAGS
指定标签,标签可以是optional
(默认)、 debug
和eng
的一个或多个值。
如果模块未指定标签(通过LOCAL_MODULE_TAGS
),则其标签默认为optional
。仅当使用PRODUCT_PACKAGES
的产品配置需要时才安装可选模块。
这些是当前定义的构建变体。
变体 | 描述 |
---|---|
eng | 这是默认风味。
|
user | 该变体旨在成为最终版本。
|
userdebug | 与user 相同,但有以下例外:
|
用户调试指南
在测试中运行 userdebug 构建有助于设备开发人员了解开发中版本的性能和功能。为了保持 user 和 userdebug 构建之间的一致性,并在用于调试的构建中实现可靠的指标,设备开发人员应遵循以下准则:
- userdebug 被定义为启用 root 访问的用户构建,除了:
- 仅由用户按需运行的 userdebug-only 应用程序
- 仅在空闲维护期间运行的操作(在充电器上/充满电),例如使用
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
的主要设备配置实现。从此设备配置中,使用产品定义生成文件创建产品,该文件声明有关设备的产品特定信息,例如名称和型号。您可以查看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 的其他产品特定变量,请参阅设置产品定义变量。
- 创建指向产品生成文件的
AndroidProducts.mk
文件。在此示例中,只需要产品定义生成文件。下面的示例来自device/google/marlin/AndroidProducts.mk
(其中包含 marlin,Pixel 和sails,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
生成文件。例如,请参阅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 通过在PRODUCT_ADB_KEYS := $(LOCAL_PATH)/$(PLATFORM_VERSION).adb_key.pub
的密钥目录中添加一个Android.mk
文件来做到这一点,这有助于确保我们记住为每个操作系统版本生成一个新的密钥对。
这是 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
如果尚未设置)。