11、Android SDK命令行工具d8

d8 是一種命令行工具,Android Studio 和 Android Gradle 插件使用該工具來將項目的 Java 字節碼編譯爲在 Android 設備上運行的 DEX 字節碼,該工具支持您在應用的代碼中使用 Java 8 語言功能。

d8 還作爲獨立工具納入了 Android 構建工具 28.0.1 及更高版本中:android_sdk/build-tools/version/

一般用法

d8 簡單易用,只需要指向要轉換爲 DEX 字節碼的已編譯 Java 字節碼的路徑即可,如下所示。

    d8 MyProject/app/build/intermediates/classes/debug/*/*.class

輸入字節碼可以是 *.class 文件或容器(例如 JAR、APK 或 ZIP 文件)的任意組合。您還可以添加 DEX 文件作爲 d8 的輸入,以將這些文件合併到 DEX 輸出中,這在包含增量構建的輸出時很有用。

默認情況下,d8 會將 Java 字節碼編譯爲優化的 DEX 文件,並在其中包含相關的調試信息,以供您在運行時用於調試代碼。然而,您也可以添加可選標記來執行各種操作,例如執行增量構建、指定應編譯到主 DEX 文件中的類,以及指定使用 Java 8 語言功能所需的其他資源對應的路徑。

    d8 path-to-input-files [options]

下表介紹了可與 d8 一起使用的可選標記。

選項 說明
--debug 編譯 DEX 字節碼以在其中包含調試信息,例如調試符號表。

此選項默認處於啓用狀態。要在 DEX 字節碼中包含調試信息,d8 要求輸入 Java 字節碼中包含此信息。例如,如果您使用 javac 編譯代碼,則需要傳遞 -g 標記,以在輸出的 Java 字節碼中包含調試信息。

 

當爲應用或庫的發佈版本編譯 DEX 文件時,請改用下述 --release 標記。

--release 編譯 DEX 字節碼,而不包含調試信息。不過,d8 包含在生成堆棧軌跡和記錄異常時使用的一些信息。

在爲公開發布版本編譯字節碼時,應該傳遞此標記。

--output path 爲 DEX 輸出指定所需的路徑。默認情況下,d8 會輸出當前工作目錄中的 DEX 文件。

如果您指定 ZIP 或 JAR 文件的路徑和名稱,則 d8 會創建指定的文件並將 DEX 輸出文件包含在其中。如果指定現有目錄的路徑,則 d8 會將 DEX 文件輸出到該目錄中。

--lib android_sdk/platforms/api-level/android.jar 指定指向 Android SDK 的 android.jar 的路徑。編譯使用 Java 8 語言功能的字節碼時需要使用此標記。
--classpath path 指定 d8 在編譯項目的 DEX 文件時可能需要使用的類路徑資源。特別是在編譯使用 Java 8 語言功能的字節碼時,d8 會要求您指定特定的資源。
--min-api number 指定您希望 DEX 輸出文件支持的最低 API 級別。
--intermediate 傳遞此標記,可告知 d8 您並非要編譯項目的全部 Java 字節碼集。此標記在執行增量構建(而不是編譯您想在設備上運行的優化 DEX 文件)時非常有用,d8 會創建中間 DEX 文件,並將其存儲在指定的輸出或默認路徑中。

如果要編譯要在設備上運行的 DEX 文件,請不要使用此標記,並指定中間 DEX 類的路徑作爲輸入。

--file-per-class 將每個類編譯到單獨的 DEX 文件中。

啓用此標記後,您只需重新編譯已更改的類,從而執行更多增量構建。使用 Android Gradle 插件執行增量構建時,此優化默認處於啓用狀態。

如果您還指定了 --main-dex-list,則無法使用此標記。

--no-desugaring 停用 Java 8 語言功能。僅當您不想編譯使用 Java 8 語言功能的 Java 字節碼時,纔可使用此標記。
--main-dex-list path 指定列出 d8 應包含在主 DEX 文件中的類的文本文件,該文件的名稱通常爲 classes.dex。也就是說,如果您不使用此標記指定類列表,d8 將無法保證主 DEX 文件中會包含哪些類。

由於 Android 系統在啓您應用時會先加載主 DEX 文件,因此您可以利用此標記將特定的類編譯到主 DEX 文件中,從而使它們在應用啓動時得到優先加載。這在支持舊版 multidex 時特別有用,因爲在加載舊版 multidex 庫之前,只有主 DEX 文件中的類在運行時可用。

請記住,該主 DEX 文件仍須滿足 64K 引用限制。因此,請確保不要爲主 DEX 文件指定太多類,否則會出現編譯錯誤。默認情況下,在使用 --main-dex-list 指定類時,d8 只會包含主 DEX 文件中的類,這是爲了便於調試與主 DEX 文件中缺少的類相關的問題。如果您指定的是 --release 模式,則 d8 會嘗試在主 DEX 文件中包含儘可能多的其他類(直到達到 64K 限制爲止),從而減少打包到應用發佈版本中的 DEX 文件的數量。

如果您還指定了 --file-per-class,則無法使用此標記。

--version 輸出您當前使用的 d8 版本。
--help 輸出與使用 d8 有關的幫助文本。

執行增量構建

爲了在開發過程中提高構建速度(例如提高持續集成構建的速度),您可以指示 d8 僅編譯項目的部分 Java 字節碼。例如,如果您啓用了按類 dexing 處理,則只需重新編譯自上次構建以來修改過的類。

注意d8 無法自動檢測哪些字節碼文件已被修改過,因此您需要手動指定類列表。

以下命令可執行幾個類的增量構建,並啓用按類 dexing 處理。該命令還可爲增量構建指定輸出目錄。

    d8 MainActivity.class R.class --intermediate --file-per-class --output ~/build/intermediate/dex

d8 在執行增量構建時,會將一些額外的信息存儲在 DEX 輸出中,等以後完整構建應用時,它會利用這些信息正確地處理 --main-dex-list 選項以及合併 DEX 文件。例如,d8 在處理 Java 8 lambda 類時,會記錄爲每個輸入類創建的 lamdba 類。在完整構建過程中,當 d8 在主 DEX 文件中包含某個類時,它會查詢元數據,以確保爲此類創建的所有 lambda 類也包含在主 DEX 文件中。

如果您已在多次增量構建中將項目的所有字節碼編譯到 DEX 文件中,則可以通過將中間 DEX 文件的目錄傳遞給 d8 來執行完整構建,如下所示。此外,您也可以使用 --main-dex-list 指定想讓 d8 編譯到主 DEX 文件中的類。由於輸入是已編譯爲 DEX 字節碼的一組文件,因此,完成此構建的速度應該比完成乾淨構建更快。

    d8 ~/build/intermediate/dex --release --main-dex-list ~/build/classes.txt --output ~/build/release/dex

編譯使用 Java 8 語言功能的字節碼

d8 通過一個叫做“脫糖”的編譯進程,使您能夠在代碼中使用 Java 8 語言功能,此進程會將這些實用的語言功能轉換爲可以在 Android 平臺上運行的字節碼。

Android Studio 和 Android Gradle 插件包含了 d8 爲您啓用脫糖所需的類路徑資源。不過,從命令行使用 d8 時,您需要手動添加這些資源。

其中一個資源就是目標 Android SDK 中的 android.jar。此資源包含一組 Android 平臺 API,您可以使用 --lib 標記來指定該資源的路徑。

另一個資源是您項目的部分已編譯的 Java 字節碼,您目前不打算將這部分字節碼編譯爲 DEX 字節碼,但在將其他類編譯爲 DEX 字節碼時需要用到這些字節碼。例如,如果代碼使用默認和靜態接口方法(一種 Java 8 語言功能),則您需要使用此標記來指定您項目的所有 Java 字節碼的路徑,即使您不打算將所有 Java 字節碼都編譯爲 DEX 字節碼也是如此。這是因爲 d8 需要根據這些信息來理解您項目的代碼並解析對接口方法的調用。

以下代碼示例對一個訪問默認接口方法的類執行增量構建:

    d8 MainActivity.class --intermediate --file-per-class --output ~/build/intermediate/dex
    --lib android_sdk/platforms/api-level/android.jar
    --classpath ~/build/javac/debug

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章