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