從構(gòu)建系統(tǒng)的觀點看,最顯著的更改是用同一個 build 就可以生成出可以支持在 2 個目標 CPU 架構(gòu)上(64 位和 32 位)的構(gòu)建文件。這就是被人們所知的多庫構(gòu)建。
為了構(gòu)建本地靜態(tài)庫和共享庫,構(gòu)建系統(tǒng)啟動規(guī)則去給兩個架構(gòu)的 CPU 生成二進制文件。產(chǎn)品配置(PRODUCT_PACKAGE),和圖形依賴,然后尋找到使用的是哪一個二進制文件,最后安裝進系統(tǒng)鏡像中。
構(gòu)建系統(tǒng)默認情況下只構(gòu)建 64 位版本給可執(zhí)行文件和應用程序,但是你可以重寫這個設(shè)置,通過一個全局的 BoardConfig.mk 參數(shù)或者一個局部的參數(shù)。
注意:如果一個應用要開放一個 API 給其他可能是 32 位或是 64 位的應用時,這個應用必須在 manifest 文件中有 android:multiarch 屬性,并且將其值設(shè)為 true ,這樣可以避免潛在的錯誤。
在 BoardConfig.mk 文件中,我們添加下面的參數(shù)來配置第二個 CPU 架構(gòu)和接口:
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 中查看事例。
如果你想默認構(gòu)建給 32 位的可執(zhí)行文件和應用,設(shè)置下面的參數(shù):
TARGET_PREFER_32_BIT := true
然而,你也可以在 Android.mk 文件中通過重寫 module-specific 參數(shù)來進行設(shè)置。
在一個多庫構(gòu)建中,只要他們被構(gòu)造系統(tǒng)定義了,命名在 PRODUCT_PACKAGES 中的模塊就可以同時覆蓋了 32 位和 64 位這兩種二進制文件。在依賴庫的獲取中,只有被另外一個 32 位的可執(zhí)行文件或庫所請求時才會安裝 32 位庫。在 64 位庫中也是一樣的情況。
但是,命名在 make 命令行中的模塊僅僅只覆蓋 64 位的版本。舉個例子,在執(zhí)行完 lunch aosp_arm64-eng,make libc 后,只構(gòu)建了 64 位的庫。要構(gòu)建 32 位的庫,你需要運行 make libc_32。
你可以使用 LOCAL_MULTILIB 變量中配置你要構(gòu)建的 32 位或者 64 位以及重寫全局的變量 TARGET_PREFER_32_BIT。
按照下列中的一個設(shè)置你的 LOCAL_MULTILIB:
在多庫構(gòu)建中,像 ifeq $(TARGET_ARCH) 這種附件條件將不再起作用。
如果你想給一些特殊的架構(gòu)上構(gòu)建你的模塊,下面的參數(shù)可能會幫助你:
這里有上面兩個變量的縮小版:
如果當前模塊跳出了應該有的架構(gòu)限制,那么構(gòu)建系統(tǒng)將會提出警告。
啟動 arch-specific 構(gòu)建標識,使用 arch-specific LOCAL 變量。一個 arch-specific LOACL 變量一般情況是 LOCAL_ 跟上一個架構(gòu)的后綴,比如:
需要注意的是:所有的 LOCAL_ 變量支持 arch-specific 變體。查看最新的相關(guān)列表,請看 build/core/clear_vars.mk。
在前面,你應該使用 LOCAL_MODULE_PATH 來替代默認的那個用于安裝一個庫到一個路徑。比如 LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
在多庫構(gòu)建中,使用 LOCAL_MODULE_RELATIVE_PATH 來替代:
LOCAL_MODULE_RELATIVE_PATH := hw
這樣就可以讓 64 位和 32 位都可以安裝在正確的路徑下了。
如果你想構(gòu)建一個同時在 32 位和 64 位下都可以運行的可執(zhí)行文件,你會都需要使用下面中的一個變量來區(qū)分你的安裝路徑:
在多庫構(gòu)建中,如果你在 $(local-intermediates-dir)(或者含有參數(shù)的 $(intermediates-dir-for))生成源文件,那么它將不會正常工作。這是因為32 位和 64 位會同時請求中間產(chǎn)生的源文件,但是 $(local-intermediates-dir) 只指向其中這兩個中的其中一個路徑。
值得高興的是,構(gòu)建系統(tǒng)現(xiàn)在為生成源文件提供可共享,對多庫友好的中間文件路徑。你可以使用 $(local-generated-sources-dir) 或者 $(generated-sources-dir-for) 來獲取一個文件路徑。他們的用法跟 $(local-intermediates-dir) 和 $(intermediates-dir-for) 類似。
如果源文件已經(jīng)在新的中間文件路徑中生成,并且被 LOCAL_GENERATED_SOURCES 所接管,那么它將在多庫構(gòu)建中生成 32 位和 64 位文件。
在多庫中,你不能用 TARGET_ARCH(或者連同 TARGET_2ND_ARCH 一塊使用)來告訴構(gòu)建系統(tǒng)要預構(gòu)建二進制文件的目標是什么。用之前提到的 LOCAL_ 變量 LOCAL_MODULE_TARGET_ARCH 或者是 LOCAL_MODULE_UNSUPPORTED_TARGET_ARCH 來替換。
用這些變量,構(gòu)建系統(tǒng)即使是在一個 64 位的多庫構(gòu)建中也能選擇匹配 32 位的預構(gòu)建二進制文件。
如果你想使用選擇的架構(gòu)來給預構(gòu)建的二進制文件計算出源文件路徑,你可以使用 $(get-prebuilt-src-arch)。
在 64 位設(shè)備上,默認情況下我們同時給系統(tǒng)鏡像生成 32 位和 64 位的 odex 文件以及一些 Java 庫。默認我們只給 64 位架構(gòu)生成 odex 文件給 APK 文件。如果某個應用可能會同時在 32 位和 64 位上登錄,請使用 LOCAL_MULTILIB := both 來確保 32 位和 64 位的 odex 文件都被生成。這個標識同樣也會告訴構(gòu)建系統(tǒng),如果有應用需要,就包括 32 位和 64 位的 JNI 庫。