了解 64 位構建

構建系統支持在同一構建中為兩個目標 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_ARCHLOCAL_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_ARCHLOCAL_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 庫,該標誌也會告訴構建系統包含它們。