Wenn Sie CMake oder ndk-build nicht verwenden, aber eine vollständige Integration des C/C++-Builds des Android Gradle-Plug-ins (AGP) und Android Studio wünschen, können Sie ein benutzerdefiniertes C/C++-Build-System erstellen. Erstellen Sie dazu ein Shell-Script, das Build-Informationen im Build-Dateiformat Ninja schreibt.
Android Studio und AGP unterstützen jetzt experimentell benutzerdefinierte C/C++-Build-Systeme. Diese Funktion ist ab Android Studio Dolphin | 2021.3.1 Canary 4 verfügbar.
Übersicht
Ein gängiges Muster für C/C++-Projekte, insbesondere für solche, die auf mehrere Plattformen ausgerichtet sind, besteht darin, Projekte für jede dieser Plattformen aus einer zugrunde liegenden Darstellung zu generieren.
Ein prominentes Beispiel für dieses Muster ist CMake. CMake kann Projekte für Android, iOS und andere Plattformen aus einer einzigen zugrunde liegenden Darstellung generieren, die in der Datei CMakeLists.txt
gespeichert ist.
CMake wird von AGP direkt unterstützt. Es gibt jedoch andere Projektgeneratoren, die nicht direkt unterstützt werden:
Diese Arten von Projektgeneratoren unterstützen entweder Ninja als Backend-Darstellung des C/C++-Builds oder können so angepasst werden, dass Ninja als Backend-Darstellung generiert wird.
Bei richtiger Konfiguration ermöglicht ein AGP-Projekt mit einem integrierten C/C++-Projektsystemgenerator Nutzern Folgendes:
Builds über die Befehlszeile und Android Studio ausführen
Quellen mit vollständiger Sprachdienstunterstützung (z. B. „Zur Definition springen“) in Android Studio bearbeiten
Verwenden Sie die Debugger von Android Studio, um native und gemischte Prozesse zu debuggen.
Build so ändern, dass ein benutzerdefiniertes C/C++-Build-Konfigurationsskript verwendet wird
In diesem Abschnitt wird beschrieben, wie Sie ein benutzerdefiniertes C/C++-Build-Konfigurationsskript aus AGP verwenden.
Schritt 1: build.gradle
-Datei auf Modulebene so ändern, dass sie auf ein Konfigurationsskript verweist
Wenn du die Ninja-Unterstützung in AGP aktivieren möchtest, konfiguriere experimentalProperties
in der Datei build.gradle
auf Modulebene:
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}"
]
}
}
Die Eigenschaften werden von AGP so interpretiert:
ninja.abiFilters
ist eine Liste der zu erstellenden ABIs. Gültige Werte sindx86
,x86-64
,armeabi-v7a
undarm64-v8a
.ninja.path
ist der Pfad zu einer C/C++-Projektdatei. Das Format dieser Datei kann beliebig sein. Änderungen an dieser Datei lösen eine Aufforderung zur Gradle-Synchronisierung in Android Studio aus.ninja.configure
ist der Pfad zu einer Scriptdatei, die von Gradle ausgeführt wird, wenn das C/C++-Projekt konfiguriert werden muss. Ein Projekt wird beim ersten Build, während einer Gradle-Synchronisierung in Android Studio oder bei einer Änderung einer der Eingaben des Konfigurationsscripts konfiguriert.ninja.arguments
ist eine Liste von Argumenten, die an das von ninja.configure definierte Script übergeben werden. Elemente in dieser Liste können auf eine Reihe von Makros verweisen, deren Werte vom aktuellen Konfigurationskontext in AGP abhängen:${ndk.moduleMakeFile}
ist der vollständige Pfad zurninja.configure
-Datei. Im Beispiel wäre dasC:\path\to\configure-ninja.bat
.${ndk.variantName}
ist der Name der aktuellen AGP-Variante, die erstellt wird. Beispiel: „debug“ oder „release“.${ndk.abi}
ist der Name des aktuellen AGP ABI, das erstellt wird. Zum Beispiel:x86
oderarm64-v8a
.
${ndk.buildRoot}
ist der Name eines von AGP generierten Ordners, in den das Script seine Ausgabe schreibt. Weitere Informationen dazu finden Sie unter Schritt 2: Konfigurationsskript erstellen.${ndk.ndkVersion}
ist die zu verwendende NDK-Version. Dies ist normalerweise der Wert, der in der Dateibuild.gradle
an „android.ndkVersion“ übergeben wird, oder ein Standardwert, falls keiner vorhanden ist.${ndk.minPlatform}
ist die von AGP angeforderte Mindest-Android-Zielplattform.
ninja.targets
ist eine Liste der spezifischen Ninja-Ziele, die erstellt werden sollen.
Schritt 2: Konfigurationsskript erstellen
Das Konfigurationsskript (configure-ninja.bat
im vorherigen Beispiel) muss mindestens eine build.ninja
-Datei generieren, die beim Erstellen mit Ninja alle nativen Ausgaben des Projekts kompiliert und verknüpft. In der Regel sind das .o
- (Objekt), .a
- (Archiv) und .so
-Dateien (freigegebenes Objekt).
Das Konfigurationsskript kann die Datei build.ninja
je nach Bedarf an zwei verschiedenen Stellen schreiben.
Wenn AGP einen Speicherort auswählen darf, schreibt das Konfigurationsskript
build.ninja
an der im Makro${ndk.buildRoot}
festgelegten Stelle.Wenn das Konfigurationsskript den Speicherort der Datei
build.ninja
auswählen muss, wird auch eine Datei namensbuild.ninja.txt
an dem im Makro${ndk.buildRoot}
festgelegten Speicherort geschrieben. Diese Datei enthält den vollständigen Pfad zurbuild.ninja
-Datei, die vom Konfigurationsskript erstellt wurde.
Struktur der build.ninja
-Datei
Im Allgemeinen funktioniert die meisten Strukturen, die einen Android-C/C++-Build korrekt darstellen. Die wichtigsten Elemente, die für AGP und Android Studio erforderlich sind:
Die Liste der C/C++-Quelldateien mit den Flags, die Clang zum Kompilieren benötigt.
Die Liste der Ausgabebibliotheken. In der Regel sind dies
.so
-Dateien (Shared Object), es können aber auch.a
-Dateien (Archiv) oder ausführbare Dateien (ohne Erweiterung) sein.
Wenn Sie Beispiele zum Generieren einer build.ninja
-Datei benötigen, können Sie sich die Ausgabe von CMake ansehen, wenn der build.ninja
-Generator verwendet wird.
Hier ein Beispiel für eine minimale build.ninja
-Vorlage:
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
Best Practices
Zusätzlich zu den Anforderungen (Liste der Quelldateien und Ausgabebibliotheken) finden Sie hier einige empfohlene Best Practices.
Benannte Ausgaben mit phony
-Regeln deklarieren
Nach Möglichkeit sollten für die build.ninja
-Struktur phony
-Regeln verwendet werden, um Build-Ausgaben visuell lesbare Namen zu geben. Wenn Sie beispielsweise eine Ausgabe namens c:/path/to/lib.so
haben, können Sie ihr einen für Menschen lesbaren Namen geben.
build curl: phony /path/to/lib.so
Der Vorteil dabei ist, dass Sie diesen Namen dann in der Datei build.gradle
als Build-Ziel angeben können. Beispiel:
android {
defaultConfig {
externalNativeBuild {
...
experimentalProperties["ninja.targets"] = [ "curl" ]
„Alle“ als Ziel festlegen
Wenn Sie ein all
-Ziel angeben, wird dies von AGP als Standardsatz von Bibliotheken erstellt, wenn in der build.gradle
-Datei keine Ziele explizit angegeben sind.
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
Alternative Build-Methode angeben (optional)
Ein erweiterter Anwendungsfall besteht darin, ein vorhandenes Build-System zu verpacken, das nicht auf Ninja basiert. In diesem Fall müssen Sie alle Quellen mit ihren Flags zusammen mit den Ausgabebibliotheken angeben, damit Android Studio die entsprechenden Sprachdienstfunktionen wie die automatische Vervollständigung und die Definition aufrufen kann. Sie möchten jedoch, dass AGP während des eigentlichen Builds auf das zugrunde liegende Buildsystem verweist.
Dazu können Sie eine Ninja-Build-Ausgabe mit einer bestimmten Erweiterung .passthrough
verwenden.
Angenommen, Sie möchten ein MSBuild-Objekt einbinden. Ihr Konfigurationsskript generiert die build.ninja
wie gewohnt, fügt aber auch ein Passthrough-Ziel hinzu, das definiert, wie AGP MSBuild aufruft.
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
Feedback geben
Diese Funktion befindet sich in der Testphase. Dein Feedback ist uns sehr wichtig. Sie können uns Feedback über die folgenden Kanäle geben:
Allgemeines Feedback kannst du in diesem Kommentar hinterlassen.
Wenn Sie einen Fehler melden möchten, öffnen Sie Android Studio und klicken Sie auf Hilfe > Feedback geben. Machen Sie unbedingt einen Verweis auf „Benutzerdefinierte C/C++-Build-Systeme“, um den Fehler zu leiten.
Wenn Sie Android Studio nicht installiert haben, können Sie einen Fehler mit dieser Vorlage melden.