构建系统支持在同一次 build 中为两种目标 CPU 架构(32 位和 64 位)构建二进制文件。这种双目标 build 也称为多库 build。
对于内置静态库和共享库,构建系统会设置规则,以便为两种架构构建二进制文件。产品配置 (PRODUCT_PACKAGES
) 与依赖关系图共同决定了要构建哪些二进制文件以及要将其安装到哪个系统映像。
对于可执行文件和应用,构建系统默认仅构建 64 位版本,但您可以使用全局 BoardConfig.mk
变量或模块作用域变量来替换此设置。
确定第二个 CPU 架构和 ABI
BoardConfig.mk
包含以下变量来配置第二个 CPU 架构和应用二进制接口 (ABI):
TARGET_2ND_ARCH
TARGET_2ND_ARCH_VARIANT
TARGET_2ND_CPU_VARIANT
TARGET_2ND_CPU_ABI
TARGET_2ND_CPU_ABI2
如需查看使用这些变量的示例 makefile,请参阅 build/make/target/board/generic_arm64/BoardConfig.mk
。
在多库 build 中,PRODUCT_PACKAGES
中的模块名称涵盖 32 位和 64 位二进制文件,只要它们是由构建系统定义的即可。对于依赖项包含的库,仅当另一个 32 位或 64 位库或可执行文件需要某个 32 位或 64 位库时,才会安装该库。
但是,make
命令行中的模块名称仅涵盖 64 位版本。例如,在运行 lunch aosp_arm64-eng
后,make libc
仅构建 64 位 libc。要构建 32 位 libc,您需要运行 make libc_32
。
在 Android.mk 中定义模块架构
您可以使用 LOCAL_MULTILIB
变量来配置 32 位和 64 位的 build,并替换全局 TARGET_PREFER_32_BIT
变量。
要替换 TARGET_PREFER_32_BIT
,请将 LOCAL_MULTILIB
设置为以下值之一:
both
构建 32 位和 64 位版本。32
仅构建 32 位版本。64
仅构建 64 位版本。first
仅为第一个架构构建(在 32 位设备中为 32 位,在 64 位设备中为 64 位)。
默认情况下,未设置 LOCAL_MULTILIB
,并且构建系统会根据模块类和其他 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
如果由于列出的架构而跳过当前模块,构建系统会发出警告。
要为特定架构设置 build 标志,请使用特定于架构的 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,
设置库安装路径
对于非多库 build,您可以使用 LOCAL_MODULE_PATH
将库安装到默认位置以外的位置。例如,LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
。
但是,在多库 build 中,请改用 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
- 指定安装路径。
获取源文件的中间目录
在多库 build 中,如果您将源文件生成到 $(local-intermediates-dir)
(或带有显式变量的 $(intermediates-dir-for)
),则它无法可靠地工作。这是因为 32 位和 64 位 build 都需要中间生成的源文件,但 $(local-intermediates-dir)
仅指向两个中间目录之一。
构建系统为生成源文件提供了专用的、多库友好的中间目录。要检索中间目录的路径,请使用 $(local-generated-sources-dir)
或 $(generated-sources-dir-for)
宏。这些宏的用法类似于 $(local-intermediates-dir)
和 $(intermediates-dir-for)
。
如果源文件生成到此专用目录并被 LOCAL_GENERATED_SOURCES
拾取,则会在多库 build 中为 32 位和 64 位构建该文件。
指示预编译二进制目标文件的系统架构
在多库 build 中,您不能使用 TARGET_ARCH
或 TARGET_ARCH
与 TARGET_2ND_ARCH
的组合来指示预编译二进制目标文件的系统架构。而应使用 LOCAL_*
变量 LOCAL_MODULE_TARGET_ARCH
或 LOCAL_MODULE_UNSUPPORTED_TARGET_ARCH
。
借助这些变量,即使构建系统正在处理 64 位多库 build,它也可以选择相应的 32 位预编译二进制文件。
如果您想使用选定的架构来计算预编译二进制文件的源路径,请调用 $(get-prebuilt-src-arch)
。
确保生成 32 位和 64 位 ODEX 文件
对于 64 位设备,默认情况下,Google 会为启动映像和任何 Java 库生成 32 位和 64 位 ODEX 文件。对于 APK,默认情况下,Google 仅为主 64 位架构生成 ODEX。如果应用在 32 位和 64 位进程中启动,请使用 LOCAL_MULTILIB := both
以确保生成 32 位和 64 位 ODEX 文件。如果应用有任何 32 位或 64 位 JNI 库,此标志还会告知构建系统包含这些库。