针对 32 位和 64 位架构进行构建

构建系统支持在一个 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 位库。如需构建 32 位库,您需要运行 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_ARCHLOCAL_32_BIT_ONLY)决定要构建哪个架构。

如果您希望针对特定架构构建模块,请使用以下变量:

  • LOCAL_MODULE_TARGET_ARCH - 将此变量设置为架构列表,例如 arm x86 arm64。如果构建的架构位于该列表中,构建系统会添加当前模块。

  • LOCAL_MODULE_UNSUPPORTED_TARGET_ARCH - 此变量与 LOCAL_MODULE_TARGET_ARCH 相反。如果构建的架构not该列表中,构建系统会添加当前模块。

上述两个变量具有小变体:

  • 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 调用,那么就意味着它在多库构建过程中是同时为 32 位和 64 位架构构建的。

指示预构建二进制文件目标的系统架构

在多库 build 中,不能将 TARGET_ARCHTARGET_ARCHTARGET_2ND_ARCH 结合使用来指示预构建二进制文件目标的系统架构。请改为使用 LOCAL_* 变量 LOCAL_MODULE_TARGET_ARCHLOCAL_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 库,该标志也会告知构建系统添加这些代码库。