如果您沒有使用 CMake 或 ndk-build,但想要完全整合 Android Gradle 外掛程式 (AGP) C/C++ 版本和 Android Studio,您可以建立自訂的 C/C++ 建構系統,方法是打造出利用 Ninja 建構檔案格式寫入建構資訊的殼層指令碼。
Android Studio 和 AGP 新增了針對自訂 C/C++ 建構系統的實驗性支援。這項功能是從 Android Studio Dolphin 開始提供 |2021.3.1 Canary 4。
總覽
C/C++ 專案的常見模式 (尤其是指定多個平台的專案) 是透過一些基礎表示法為每個平台產生專案,
CMake 便是該模式其中一個顯著的例子。CMake 可針對儲存在 CMakeLists.txt
檔案中的單一基礎表示法,為 Android、iOS 及其他平台產生專案。
雖然 AGP 直接支援 CMake,但還有其他不受直接支援的專案產生器:
這些類型的專案產生器支援 Ninja 做為 C/C++ 版本的後端表示法,也可以加以調整,產生 Ninja 做為後端表示法。
如果設定正確,含有整合式 C/C++ 專案系統產生器的 AGP 專案可讓使用者執行以下動作:
透過指令列和 Android Studio 建構。
在 Android Studio 中編輯具有完整語言服務 (例如前往定義) 的來源。
使用 Android Studio 偵錯工具進行原生和混合程序偵錯。
如何修改建構作業,以便使用自訂 C/C++ 建構設定指令碼
本節逐步說明使用 AGP 的自訂 C/C++ 建構設定指令碼。
步驟 1:修改模組層級的 build.gradle
檔案,以參照設定指令碼
如要在 AGP 中啟用 Ninja 支援,請在模組層級 build.gradle
檔案中設定 experimentalProperties
:
android {
defaultConfig {
externalNativeBuild {
experimentalProperties["ninja.abiFilters"] = [ "x86", "arm64-v8a" ]
experimentalProperties["ninja.path"] = "source-file-list.txt"
experimentalProperties["ninja.configure"] = "configure-ninja"
experimentalProperties["ninja.arguments"] = [
"\${ndk.moduleMakeFile}",
"--variant=\${ndk.variantName}",
"--abi=Android-\${ndk.abi}",
"--configuration-dir=\${ndk.configurationDir}",
"--ndk-version=\${ndk.moduleNdkVersion}",
"--min-sdk-version=\${ndk.minSdkVersion}"
]
}
}
AGP 會解讀屬性,如下所示:
ninja.abiFilters
是要建構的 ABI 清單。有效值為x86
、x86-64
、armeabi-v7a
和arm64-v8a
。ninja.path
是 C/C++ 專案檔案的路徑。這個檔案的格式不限,且檔案變更會在 Android Studio 中觸發 Gradle 同步處理作業的提示。ninja.configure
是指令碼檔案路徑,在需要設定 C/C++ 專案時,Gradle 將執行這個指令碼檔案。專案會在第一次建構期間、Android Studio 中的 Gradle 同步處理期間,或是其中一個設定指令碼輸入內容變更時設定。ninja.arguments
這個引數清單會傳遞到由 ninja.configure 定義的指令碼。這份清單中的元素可以參照一組巨集,其值會受到 AGP 目前的設定內容影響:${ndk.moduleMakeFile}
是ninja.configure
檔案的完整路徑。在這個範例中,我們使用的是C:\path\to\configure-ninja.bat
。${ndk.variantName}
是目前正在建構的 AGP 版本名稱。例如偵錯或發布版本。${ndk.abi}
是目前正在建構的 AGP ABI 的名稱。例如x86
或arm64-v8a
。
${ndk.buildRoot}
是由 AGP 產生的資料夾名稱,這是指令碼寫入其輸出內容的資料夾。詳細步驟請參閱步驟 2:建立設定指令碼。${ndk.ndkVersion}
是要使用的 NDK 版本。通常是傳送至build.gradle
檔案中的 android.ndkVersion 的值;如果不存在,則為預設值。${ndk.minPlatform}
是 AGP 要求的最低目標 Android 平台。
ninja.targets
是應建構的特定 Ninja 目標清單。
步驟 2:建立設定指令碼
設定指令碼 (前例中為 configure-ninja.bat
) 的最低責任是產生 build.ninja
檔案,在使用 Ninja 建構時,會編譯並連結專案的所有原生輸出內容。通常是 .o
(物件)、.a
(封存) 和 .so
(共用物件) 檔案。
設定指令碼可根據需求,在兩個不同位置撰寫 build.ninja
檔案。
如果 AGP 能夠選擇位置,則設定指令碼就會在
${ndk.buildRoot}
巨集中設定的位置寫入build.ninja
。如果設定指令碼必須選擇
build.ninja
檔案的位置,那麼系統也會在${ndk.buildRoot}
巨集中設定的位置寫入名為build.ninja.txt
的檔案。這個檔案內含設定指令碼所寫入的build.ninja
檔案完整路徑。
build.ninja
檔案的結構
一般來說,大多數能夠準確反映 Android C/C++ 版本的結構通常都能正常運作。AGP 和 Android Studio 需要的主要元素包括:
C/C++ 來源檔案清單以及 Clang 編譯所需的標記。
輸出程式庫的清單。這通常是
.so
(共用物件) 檔案,但也可以是.a
(封存) 或執行檔 (無副檔名)。
如果您需要產生 build.ninja
檔案的範例,可以在使用 build.ninja
產生器時查看 CMake 輸出結果。
以下列舉幾個最小限度 build.ninja
範本的範例。
rule COMPILE
command = /path/to/ndk/clang -c $in -o $out {other flags}
rule LINK
command = /path/to/ndk/clang $in -o $out {other flags}
build source.o : COMPILE source.cpp
build lib.so : LINK source.o
最佳做法
除了使用規定 (來源檔案和輸出程式庫清單),建議您參考下列最佳做法。
使用 phony
規則宣告已命名的輸出內容
建議您盡可能讓 build.ninja
結構使用 phony
規則,為建構作業輸出的名稱提供使用者可理解的名稱。舉例來說,如果輸出名稱是 c:/path/to/lib.so
,您可以按照以下方式為其提供使用者可理解的名稱。
build curl: phony /path/to/lib.so
這麼做的好處是,您可以將這個名稱指定為 build.gradle
檔案中的建構目標。例如:
android {
defaultConfig {
externalNativeBuild {
...
experimentalProperties["ninja.targets"] = [ "curl" ]
指定「全部」目標
如果指定 all
目標,在 build.gradle
檔案中未明確指定任何目標時,這是 AGP 建構的預設程式庫組合。
rule COMPILE
command = /path/to/ndk/clang $in -o $out {other flags}
rule LINK
command = /path/to/ndk/clang $in -o $out {other flags}
build foo.o : COMPILE foo.cpp
build bar.o : COMPILE bar.cpp
build libfoo.so : LINK foo.o
build libbar.so : LINK bar.o
build all: phony libfoo.so libbar.so
指定替代的建構方法 (選用)
更進階的方法,就是納入非以 Ninja 為基礎的現有建構系統。在這種情況下,您還是必須以所有標記和輸出程式庫來代表所有來源,以便 Android Studio 提供適當語言服務功能,例如「自動完成」和「前往定義」。不過,您希望 AGP 在實際建構期間推遲到基礎建構系統。
如要完成這項操作,您可以使用具備特定擴充功能 .passthrough
的 Ninja 建構作業輸出內容。
以更具體的例子來說,假設您想包裝 MSBuild。您的設定指令碼仍會照常產生 build.ninja
,但也會新增可定義 AGP 叫用 MSBuild 的直通目標。
rule COMPILE
command = /path/to/ndk/clang $in -o $out {other flags}
rule LINK
command = /path/to/ndk/clang $in -o $out {other flags}
rule MBSUILD_CURL
command = /path/to/msbuild {flags to build curl with MSBuild}
build source.o : COMPILE source.cpp
build lib.so : LINK source.o
build curl : phony lib.so
build curl.passthrough : MBSUILD_CURL
提供意見
這項功能仍在實驗階段,因此非常歡迎您提供意見。您可以透過下列管道提供意見:
如需查看一般意見回饋,請在這個錯誤中新增註解。
如要回報錯誤,請開啟 Android Studio,然後依序點選「Help」>「Help」提供意見。請務必提及「自訂 C/C++ 建構系統」協助引導錯誤
如要回報錯誤,但您尚未安裝 Android Studio,請使用這個範本回報錯誤。