Jeśli nie korzystasz z CMake ani ndk-build, ale chcesz w pełni zintegrować wtyczkę C/C++ Androida (AGP) z Androidem Studio, możesz utworzyć własny system kompilacji C/C++, tworząc skrypt powłoki, który będzie zapisywał informacje o kompilacji w formacie pliku kompilacji Ninja.
W Android Studio i AGP dodaliśmy eksperymentalną obsługę niestandardowych systemów kompilacji w języku C/C++. Ta funkcja jest dostępna w Android Studio Dolphin | 2021.3.1 Canary 4.
Przegląd
Wspólnym wzorcem projektów C/C++, zwłaszcza tych kierowanych na wiele platform, jest generowanie projektów dla każdej z tych platform na podstawie pewnej podstawowej reprezentacji.
Znaczącym przykładem tego wzorca jest CMake. CMake może generować projekty na Androida, iOS i inne platformy na podstawie jednej reprezentacji zapisanej w pliku CMakeLists.txt
.
Chociaż CMake jest obsługiwane bezpośrednio przez AGP, dostępne są też inne generatory projektów, które nie są obsługiwane bezpośrednio:
Prywatne, niestandardowe generatory projektów
Tego typu generatory projektów obsługują ninja jako backendową reprezentację kompilacji C/C++ lub można je dostosować tak, aby wygenerować ninję jako reprezentację backendu.
Prawidłowo skonfigurowany projekt AGP ze zintegrowanym generatorem systemu projektów w C/C++ umożliwia użytkownikom:
Twórz z poziomu wiersza poleceń i Androida Studio.
Edytuj źródła z pełną obsługą języka (np. przejściem definicji) w Android Studio.
Używaj debugerów Android Studio do debugowania procesów natywnych i mieszanych.
Jak zmodyfikować kompilację, aby użyć niestandardowego skryptu konfiguracji kompilacji w C/C++
W tej sekcji omawiamy, jak korzystać z niestandardowego skryptu konfiguracji kompilacji w 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 systemie 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}"
]
}
}
Właściwości są interpretowane przez AGP w następujący sposób:
ninja.abiFilters
to lista interfejsów ABI do skompilowania. Prawidłowe wartości tox86
,x86-64
,armeabi-v7a
iarm64-v8a
.ninja.path
to ścieżka do pliku projektu w C/C++. Ten plik może mieć dowolny format. Zmiany w tym pliku spowodują wyświetlenie komunikatu o synchronizacji Gradle w Android Studio.ninja.configure
to ścieżka do pliku skryptu, który będzie wykonywany przez Gradle, gdy konieczne będzie skonfigurowanie projektu C/C++. Projekt jest konfigurowany przy pierwszej kompilacji, podczas synchronizacji Gradle w Android Studio lub po zmianie danych wejściowych skryptu.ninja.arguments
to lista argumentów, które zostaną przekazane do skryptu zdefiniowanego przez ninja.configure. Elementy na tej liście mogą odwoływać się do zestawu makr, których wartości zależą od kontekstu bieżącej konfiguracji w interfejsie AGP:${ndk.moduleMakeFile}
to pełna ścieżka do plikuninja.configure
. W naszym przykładzie będzie toC:\path\to\configure-ninja.bat
.${ndk.variantName}
to nazwa obecnie tworzonego wariantu AGP. Na przykład debug lub wersja.${ndk.abi}
to nazwa obecnie tworzonego interfejsu AGP ABI. na przykładx86
lubarm64-v8a
.
${ndk.buildRoot}
to nazwa folderu wygenerowanego przez AGP, w którym skrypt zapisuje dane wyjściowe. Szczegółowe informacje na ten temat znajdziesz w kroku 2. Utwórz skrypt konfiguracji.${ndk.ndkVersion}
to wersja pakietu NDK, która ma być używana. Zwykle jest to wartość przekazywana do android.ndkVersion w plikubuild.gradle
lub wartość domyślna, jeśli nie podano żadnej wartości.${ndk.minPlatform}
to minimalna docelowa platforma Androida wymagana przez AGP.
ninja.targets
to lista konkretnych celów ninja, które należy utworzyć.
Krok 2. Utwórz skrypt konfiguracji
Minimalnym obowiązkiem skryptu konfiguracji (configure-ninja.bat
we wcześniejszym przykładzie) jest wygenerowanie pliku build.ninja
, który po skompilowaniu kodu Ninja skompiluje i połączy wszystkie natywne dane wyjściowe projektu. Zwykle są to pliki .o
(obiekt), .a
(archiwum) i .so
(obiekty udostępnione).
W zależności od potrzeb skrypt konfiguracji może zapisać plik build.ninja
w 2 różnych miejscach.
Jeśli AGP może wybrać lokalizację, skrypt konfiguracji zapisuje
build.ninja
w lokalizacji ustawionej w makrze${ndk.buildRoot}
.Jeśli skrypt konfiguracji musi wybrać lokalizację pliku
build.ninja
, zapisze też plik o nazwiebuild.ninja.txt
w lokalizacji ustawionej w makrze${ndk.buildRoot}
. Ten plik zawiera pełną ścieżkę do plikubuild.ninja
napisanego przez skrypt konfiguracji.
Struktura pliku build.ninja
Ogólnie będzie działać większość struktury, która dokładnie odzwierciedla kompilację na Androida C/C++. Kluczowe elementy wymagane przez AGP i Android Studio:
Lista plików źródłowych C/C++ wraz z flagami potrzebnymi do ich skompilowania.
Lista bibliotek wyjściowych. Zwykle są to pliki
.so
(obiekty udostępnione), ale mogą to być też pliki.a
(archiwum) lub wykonywalne (bez rozszerzeń).
Jeśli potrzebujesz przykładów tego, jak wygenerować plik build.ninja
, możesz zobaczyć 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 spełnienia wymagań (lista plików źródłowych i bibliotek wyjściowych) oto kilka zalecanych sprawdzonych metod.
Deklaruj nazwane dane wyjściowe za pomocą phony
reguł
W miarę możliwości zalecamy używanie w strukturze build.ninja
reguł phony
, aby nadawać wynikom kompilacji zrozumiałe dla człowieka nazwy. Jeśli na przykład masz dane wyjściowe o nazwie c:/path/to/lib.so
, możesz nadać mu nazwę zrozumiałą dla człowieka w ten sposób.
build curl: phony /path/to/lib.so
Zaletą jest to, że możesz ją później określić jako cel kompilacji w pliku build.gradle
. Na przykład
android {
defaultConfig {
externalNativeBuild {
...
experimentalProperties["ninja.targets"] = [ "curl" ]
Określ cel „wszystko”
Gdy określisz środowisko docelowe all
, będzie to domyślny zestaw bibliotek utworzonych przez AGP, o ile w pliku build.gradle
nie określono wyraźnie żadnych celów.
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)
W bardziej zaawansowanym przypadku użycia warto dodać do istniejącego systemu kompilacji, który nie jest oparty na ninja. W takim przypadku nadal musisz przedstawiać wszystkie źródła za pomocą ich flag wraz z bibliotekami wyjściowymi, aby Android Studio mógł prezentować odpowiednie funkcje usług językowych, takie jak autouzupełnianie i definicja. Chcesz jednak, aby w czasie jej trwania AGP korzystało z bazowego systemu kompilacji.
Aby to zrobić, możesz użyć danych wyjściowych kompilacji Ninja z konkretnym rozszerzeniem .passthrough
.
Załóżmy, że chcesz zapakować obiekt MSBuild. Skrypt konfiguracji wygenerowałby zdarzenie build.ninja
w zwykły sposób, ale dodałby też miejsce docelowe przekazywania, które określa sposób wywoływania przez 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
Prześlij opinię
Jest to funkcja eksperymentalna, więc będziemy wdzięczni za Twoją opinię. Opinię możesz przesłać w tych kanałach:
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 uwzględnić „Niestandardowe systemy kompilacji C/C++”, aby ułatwić kierowanie błędu.
Aby zgłosić błąd, jeśli nie masz zainstalowanego Android Studio, zgłoś błąd, korzystając z tego szablonu.