构建系统支持在一个 build 中为两种目标 CPU 架构(64 位和 32 位)构建二进制文件。这称为多库构建过程。
对于原生静态库和共享库,构建系统设置了为两种架构构建二进制文件的规则。产品配置 (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
中查看示例。
在多库 build 中,PRODUCT_PACKAGES
中的模块名称同时涵盖 32 位和 64 位二进制文件,但前提是它们是由构建系统定义的。对于通过依赖关系提取而来的库,只有在另一个 32 位库或可执行文件要求使用时,系统才会安装 32 位库。64 位库也遵循同样的规则。
不过,make
命令行中的模块名称仅涵盖 64 位版本。例如,在运行 lunch aosp_arm64-eng
之后,make libc
仅构建 64 位库。如需构建 32 位库,您需要运行 make libc_32
。
Android.mk 中的模块定义
您可以使用 LOCAL_MULTILIB
变量将 build 配置为适用于 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
如果由于列出的架构而跳过当前模块,构建系统将发出警告。
如需为特定架构设置 build 标志,请使用针对特定架构的 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
。
在多库构建过程中,改为使用 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
指定安装路径。
生成的源代码
在多库构建过程中,在 $(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
调用,那么就意味着它在多库构建过程中是同时为 32 位和 64 位架构构建的。
预构建
在多库构建过程中,您无法使用 TARGET_ARCH
(或加上 TARGET_2ND_ARCH
)来告知构建系统,预构建的二进制文件是以哪种架构为目标。请改为使用 LOCAL_
变量 LOCAL_MODULE_TARGET_ARCH
或 LOCAL_MODULE_UNSUPPORTED_TARGET_ARCH
。
利用这些变量,即使构建系统正在进行 64 位多库构建,也可以选择对应的 32 位预构建二进制文件。
如果您想使用所选架构计算预构建二进制文件的源代码路径,请调用 $(get-prebuilt-src-arch)
。
生成 ODEX 文件
对于 64 位设备,我们会默认为启动映像及任何 Java 库同时生成 32 位和 64 位 ODEX 文件。对于 APK,我们默认仅为主要的 64 位架构生成 ODEX 文件。如果某个应用将同时在 32 位和 64 位进程中启动,请使用 LOCAL_MULTILIB := both
确保同时生成 32 位和 64 位 ODEX 文件。如果应用包含任何 32 位或 64 位 JNI 库,该标志也会告知构建系统添加代码库。