Jeśli nie używasz CMake ani ndk-build, ale chcesz w pełni zintegrować kompilację w C/C++ w ramach wtyczki Android Gradle (AGP) i Android Studio, możesz utworzyć niestandardowy system kompilacji C/C++, tworząc skrypt powłoki, który zapisuje informacje o kompilacji w formacie pliku kompilacji Ninja.
Do Android Studio i AGP dodaliśmy eksperymentalną obsługę niestandardowych systemów kompilacji C/C++. Ta funkcja jest dostępna od wersji Android Studio Dolphin | 2021.3.1 Canary 4.
Omówienie
Typowym wzorcem w przypadku projektów C/C++, zwłaszcza tych przeznaczonych na wiele platform, jest generowanie projektów dla każdej z tych platform na podstawie pewnej reprezentacji podstawowej.
Wyraźnym przykładem tego wzorca jest CMake. CMake może generować projekty na Androida, iOS i inne platformy na podstawie pojedynczej reprezentacji zapisanej w pliku CMakeLists.txt
.
CMake jest bezpośrednio obsługiwany przez AGP, ale istnieją też inne generatory projektów, które nie są obsługiwane bezpośrednio:
Takie generatory projektów obsługują Ninja jako backendową reprezentację kompilacji C/C++ lub mogą być dostosowane do generowania Ninja jako backendowej reprezentacji.
Po prawidłowej konfiguracji projekt AGP z zintegrowanym systemem generatora projektów C/C++ umożliwia użytkownikom:
Kompilowanie z poziomu wiersza poleceń i Android Studio.
Edytuj źródła z pełną obsługą usług językowych (np. definicji „go-to”) w Android Studio.
Debugowanie procesów natywnych i mieszanych za pomocą debugerów Androida Studio.
Jak zmodyfikować kompilację, aby używać niestandardowego skryptu konfiguracji kompilacji C/C++
W tej sekcji opisaliśmy, jak używać niestandardowego skryptu konfiguracji kompilacji C/C++ z AGP.
Krok 1. Zmodyfikuj plik build.gradle
na poziomie modułu, aby odwoływał się do skryptu konfiguracji
Aby włączyć obsługę Ninja w AGP, skonfiguruj experimentalProperties
w pliku build.gradle
na poziomie modułu:
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}"
]
}
}
Usługa AGP interpretuje te właściwości w ten sposób:
ninja.abiFilters
to lista interfejsów ABI do utworzenia. Prawidłowe wartości tox86
,x86-64
,armeabi-v7a
iarm64-v8a
.ninja.path
to ścieżka do pliku projektu C/C++. Format tego pliku może być dowolny. Zmiany w tym pliku spowodują wyświetlenie w Android Studio prośby o synchronizację Gradle.ninja.configure
to ścieżka do pliku skryptu, który zostanie wykonany przez Gradle, gdy będzie to konieczne do skonfigurowania projektu C/C++. Projekt jest konfigurowany podczas pierwszej kompilacji, podczas synchronizacji Gradle w Android Studio lub gdy zmieni się jeden z wejść skryptu konfiguracyjnego.ninja.arguments
to lista argumentów, które zostaną przekazane do skryptu określonego przez ninja.configure. Elementy na tej liście mogą odwoływać się do zestawu makr, których wartości zależą od bieżącego kontekstu konfiguracji w AGP:${ndk.moduleMakeFile}
to pełna ścieżka do plikuninja.configure
. W tym przykładzie będzie toC:\path\to\configure-ninja.bat
.${ndk.variantName}
to nazwa bieżącego wariantu AGP, który jest tworzony. Na przykład debugowanie lub wydanie.${ndk.abi}
to nazwa bieżącego ABI AGP, który jest kompilowany. na przykładx86
lubarm64-v8a
.
${ndk.buildRoot}
to nazwa folderu wygenerowanego przez AGP, do którego skrypt zapisuje dane wyjściowe. Szczegółowe informacje na ten temat znajdziesz w kroku 2. Tworzenie skryptu konfiguracji.${ndk.ndkVersion}
to wersja NDK, której należy użyć. Jest to zwykle wartość przekazana do android.ndkVersion w plikubuild.gradle
lub wartość domyślna, jeśli nie ma żadnej.${ndk.minPlatform}
to minimalna docelowa platforma Android, o którą prosi AGP.
ninja.targets
to lista konkretnych celów Ninja, które należy utworzyć.
Krok 2. Utwórz skrypt konfiguracji
Minimalnym zadaniem skryptu konfiguracyjnego (configure-ninja.bat
w poprzednim przykładzie) jest wygenerowanie pliku build.ninja
, który po skompilowaniu za pomocą Ninja skompiluje i połączy wszystkie natywne dane wyjściowe projektu. Zwykle są to pliki .o
(obiekt), .a
(archiwum) i .so
(udostępniony obiekt).
Skrypt konfiguracji może zapisać plik build.ninja
w 2 różnych miejscach w zależności od potrzeb.
Jeśli AGP może wybrać lokalizację, skrypt konfiguracji zapisuje wartość
build.ninja
w miejscu określonym w makro${ndk.buildRoot}
.Jeśli skrypt konfiguracji musi wybrać lokalizację pliku
build.ninja
, zapisuje też plik o nazwiebuild.ninja.txt
w lokalizacji określonej w makro${ndk.buildRoot}
. Ten plik zawiera pełną ścieżkę do plikubuild.ninja
zapisanego przez skrypt konfiguracji.
Struktura pliku build.ninja
Zazwyczaj działa większość struktur, które dokładnie odzwierciedlają kompilację w C/C++ na Androida. Najważniejsze elementy potrzebne do AGP i Androida Studio:
Lista plików źródłowych C/C++ wraz z flagami potrzebnymi do ich skompilowania przez Clang.
Lista bibliotek wyjściowych. Zwykle są to pliki
.so
(obiekty współdzielone), ale mogą to być też pliki.a
(archiwum) lub pliki wykonywalne (bez rozszerzenia).
Jeśli potrzebujesz przykładów generowania pliku build.ninja
, możesz sprawdzić dane wyjściowe CMake, gdy używany jest generator build.ninja
.
Oto przykład minimalnego szablonu 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
Sprawdzone metody
Oprócz wymagań (lista plików źródłowych i bibliotek wyjściowych) podajemy kilka sprawdzonych metod.
Deklarowanie nazwanych danych wyjściowych za pomocą reguł phony
Zalecamy, aby w miarę możliwości w strukturze build.ninja
były używane reguły phony
, które nadają wynikom kompilacji czytelne nazwy. Jeśli na przykład masz dane wyjściowe o nazwie c:/path/to/lib.so
, możesz nadać im czytelną nazwę w ten sposób:
build curl: phony /path/to/lib.so
Dzięki temu możesz określić tę nazwę jako docelowy proces kompilacji w pliku build.gradle
. Na przykład
android {
defaultConfig {
externalNativeBuild {
...
experimentalProperties["ninja.targets"] = [ "curl" ]
Określanie docelowego „wszystkich”
Gdy określisz wartość docelową all
, będzie to domyślny zestaw bibliotek utworzonych przez AGP, jeśli w pliku build.gradle
nie zostaną jawnie określone żadne wartości docelowe.
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
Określ alternatywną metodę kompilacji (opcjonalnie)
Bardziej zaawansowanym przypadkiem użycia jest owinięcie istniejącego systemu kompilacji, który nie jest oparty na Ninja. W takim przypadku nadal musisz przedstawić wszystkie źródła wraz z ich flagami oraz biblioteki wyjściowe, aby Android Studio mogło wyświetlać odpowiednie funkcje usługi językowej, takie jak autouzupełnianie i definicja domyślna. Chcesz jednak, aby AGP podczas faktycznego kompilowania korzystał z podstawowego systemu kompilacji.
Aby to zrobić, możesz użyć danych wyjściowych Ninja Build z określonym rozszerzeniem .passthrough
.
Na potrzeby tego przykładu załóżmy, że chcesz opakować MSBuild. Skrypt konfiguracji wygeneruje build.ninja
jak zwykle, ale doda też obiekt przekazywania, który określa, jak AGP będzie wywoływać 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
Prześlij opinię
Ta funkcja jest eksperymentalna, dlatego prosimy o opinię. Opinie możesz przesyłać za pomocą tych kanałów:
Aby przesłać ogólną opinię, dodaj komentarz do tego błędu.
Aby zgłosić błąd, otwórz Android Studio i kliknij Pomoc > Prześlij opinię. Pamiętaj, aby odnieść się do „Niestandardowych systemów kompilacji C/C++”, aby ułatwić nam znalezienie błędu.
Jeśli nie masz zainstalowanego Android Studio, możesz zgłosić błąd, korzystając z tego szablonu.