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