构建系统支持在同一构建中为两个目标 CPU 架构(64 位和 32 位)构建二进制文件。这称为multilib 构建。
对于本机静态库和共享库,构建系统会设置规则来为这两种架构构建二进制文件。产品配置 ( PRODUCT_PACKAGES
) 与依赖关系图一起确定构建和安装到系统映像的二进制文件。
对于可执行文件和应用程序,构建系统默认仅构建 64 位版本,但您可以使用全局BoardConfig.mk
变量或模块范围变量覆盖此设置。
产品配置
BoardConfig.mk
包含以下变量来配置第二个 CPU 架构和 ABI:
-
TARGET_2ND_ARCH
-
TARGET_2ND_ARCH_VARIANT
-
TARGET_2ND_CPU_VARIANT
-
TARGET_2ND_CPU_ABI
-
TARGET_2ND_CPU_ABI2
您可以在build/target/board/generic_arm64/BoardConfig.mk
中看到一个示例。
在 multilib 构建中, PRODUCT_PACKAGES
中的模块名称涵盖 32 位和 64 位二进制文件,只要它们是由构建系统定义的。对于通过依赖项引入的库,仅当另一个 32 位库或可执行文件需要时才安装 32 位库。 64 位库也是如此。
但是, make
命令行上的模块名称仅涵盖 64 位版本。例如,在运行lunch aosp_arm64-eng
后, make libc
仅构建 64 位 libc。要构建 32 位 libc,您需要运行make libc_32
。
Android.mk 中的模块定义
您可以使用LOCAL_MULTILIB
变量为 32 位/64 位配置您的构建并覆盖全局TARGET_PREFER_32_BIT
变量。
将LOCAL_MULTILIB
设置为以下之一:
-
"both"
构建 32 位和 64 位。 -
"32"
仅构建 32 位。 -
"64"
仅构建 64 位。 -
"first"
仅针对第一个架构(32 位设备中的 32 位和 64 位设备中的 64 位)构建。 -
""
是默认值。构建系统根据模块类和其他LOCAL_
变量(例如LOCAL_MODULE_TARGET_ARCH
和LOCAL_32_BIT_ONLY
)决定构建哪个架构。
如果要为特定架构构建模块,请使用以下变量:
-
LOCAL_MODULE_TARGET_ARCH
将此变量设置为架构列表,例如arm x86 arm64
。如果正在构建的体系结构在该列表中,则当前模块包含在构建系统中。 -
LOCAL_MODULE_UNSUPPORTED_TARGET_ARCH
此变量与LOCAL_MODULE_TARGET_ARCH
相反。如果正在构建的体系结构不在该列表中,则当前模块包含在构建系统中。
这两个变量有一些小的变体:
-
LOCAL_MODULE_TARGET_ARCH_WARN
-
LOCAL_MODULE_UNSUPPORTED_TARGET_ARCH_WARN
如果由于列出的体系结构而跳过当前模块,构建系统会发出警告。
要为特定体系结构设置构建标志,请使用体系结构特定的LOCAL_
变量。特定于体系结构的LOCAL_
变量是具有体系结构后缀的普通LOCAL_
变量,例如:
-
LOCAL_SRC_FILES_arm, LOCAL_SRC_FILES_x86,
-
LOCAL_CFLAGS_arm, LOCAL_CFLAGS_arm64,
-
LOCAL_LDFLAGS_arm, LOCAL_LDFLAGS_arm64,
仅当当前正在为该架构构建二进制文件时才应用这些变量。
有时,根据二进制文件当前是为 32 位还是 64 位构建的,设置标志会更容易。使用带有_32
或_64
后缀的LOCAL_
变量,例如:
-
LOCAL_SRC_FILES_32, LOCAL_SRC_FILES_64,
-
LOCAL_CFLAGS_32, LOCAL_CFLAGS_64,
-
LOCAL_LDFLAGS_32, LOCAL_LDFLAGS_64,
安装路径
以前,您可以使用LOCAL_MODULE_PATH
将库安装到默认位置以外的位置。例如, LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
。
在 multilib 构建中,请改用LOCAL_MODULE_RELATIVE_PATH
:
LOCAL_MODULE_RELATIVE_PATH := hw
使用这种格式,64 位和 32 位库都安装在正确的位置。
如果您将可执行文件构建为 32 位和 64 位,请使用以下变量之一来区分安装路径:
-
LOCAL_MODULE_STEM_32, LOCAL_MODULE_STEM_64
指定安装的文件名。 -
LOCAL_MODULE_PATH_32, LOCAL_MODULE_PATH_64
指定安装路径。
生成的源
在 multilib 构建中,如果您将源文件生成到$(local-intermediates-dir)
(或带有显式变量$(intermediates-dir-for)
),它就不能可靠地工作。这是因为 32 位和 64 位构建都需要中间生成的源,但$(local-intermediates-dir)
仅指向两个中间目录之一。
构建系统提供了一个专用的、对多库友好的中间目录,用于生成源代码。您可以调用$(local-generated-sources-dir)
或$(generated-sources-dir-for)
来获取目录的路径。它们的用途类似于$(local-intermediates-dir)
和$(intermediates-dir-for)
。
如果在此专用目录中生成源文件并由LOCAL_GENERATED_SOURCES
拾取,则它在 multilib 构建中为 32 位和 64 位构建。
预制件
在 multilib 构建中,您不能使用TARGET_ARCH
(或与TARGET_2ND_ARCH
一起使用)来告诉构建系统预构建二进制目标的体系结构。相反,使用LOCAL_
变量LOCAL_MODULE_TARGET_ARCH
或LOCAL_MODULE_UNSUPPORTED_TARGET_ARCH
。
使用这些变量,构建系统可以选择相应的 32 位预构建二进制文件,即使它正在处理 64 位 multilib 构建。
如果您想使用所选架构来计算预构建二进制文件的源路径,请调用$(get-prebuilt-src-arch)
。
ODEX 文件生成
对于 64 位设备,默认情况下,我们会为启动映像和任何 Java 库生成 32 位和 64 位 ODEX 文件。对于 APK,默认情况下我们只为主要的 64 位架构生成 ODEX。如果应用程序将在 32 位和 64 位进程中启动,请使用LOCAL_MULTILIB := both
以确保生成 32 位和 64 位 ODEX 文件。如果应用程序有任何 32 位或 64 位 JNI 库,该标志也会告诉构建系统包含它们。