Ninja kullanarak özel C/C++ derleme sistemlerini entegre edin (deneysel)

CMake veya ndk-build kullanmıyorsanız ancak Android Gradle eklentisi (AGP) C/C++ derlemesinin ve Android Studio'nun tam entegrasyonunu istiyorsanız derleme bilgilerini Ninja derleme dosyası biçiminde yazan bir kabuk komut dosyası hazırlayarak özel bir C/C++ derleme sistemi oluşturabilirsiniz.

Android Studio ve AGP'ye özel C/C++ derleme sistemleri için deneysel destek eklendi. Bu özellik, Android Studio Dolphin | sürümünden itibaren kullanılabilir. 1.3.2021 Canary 4.

Genel Bakış

C/C++ projelerinde, özellikle de birden fazla platformu hedefleyen projelerde yaygın olarak kullanılan bir kalıp, bu platformların her biri için birtakım temel temsillerden projeler oluşturmaktır. Bu kalıbın belirgin bir örneği CMake'dir. CMake, CMakeLists.txt dosyasına kaydedilen tek bir temel gösterimden Android, iOS ve diğer platformlar için projeler oluşturabilir.

CMake, doğrudan AGP tarafından desteklense de doğrudan desteklenmeyen başka proje araçları da mevcuttur:

Bu tür proje oluşturucular, C/C++ yapısının arka uç temsili olarak Ninja'yı destekler veya arka uç temsili olarak Ninja oluşturacak şekilde uyarlanabilir.

Entegre bir C/C++ proje sistemi oluşturma aracına sahip bir AGP projesi doğru yapılandırıldığında, kullanıcıların şunları yapmasına olanak tanır:

  • Komut satırından ve Android Studio'dan oluşturun.

  • Android Studio'da tam dil hizmeti desteğine (ör. tanıma git) sahip kaynakları düzenleyin.

  • Yerel ve karma işlemlerde hata ayıklamak için Android Studio hata ayıklayıcılarını kullanın.

ziyaret edin.

Derlemenizi özel C/C++ derleme yapılandırma komut dosyası kullanacak şekilde değiştirme

Bu bölümde, AGP'den özel bir C/C++ derleme yapılandırma komut dosyası kullanmaya yönelik adımlar açıklanmaktadır.

1. Adım: Modül düzeyindeki build.gradle dosyasını bir yapılandırma komut dosyasına referans verecek şekilde değiştirin

AGP'de Ninja desteğini etkinleştirmek için modül düzeyindeki build.gradle dosyasında experimentalProperties öğesini yapılandırın:

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}"
       ]
     }
   }

Özellikler AGP tarafından şu şekilde yorumlanır:

  • ninja.abiFilters, derlenecek ABI'lerin listesidir. Geçerli değerler şunlardır: x86, x86-64, armeabi-v7a ve arm64-v8a.

  • ninja.path, C/C++ proje dosyasına giden bir yoldur. Bu dosyanın biçiminde istediğiniz herhangi bir şey olabilir. Bu dosyada yapılan değişiklikler, Android Studio'da Gradle senkronizasyonu istemini tetikler.

  • ninja.configure, C/C++ projesini yapılandırmak için gerekli olduğunda Gradle tarafından yürütülecek komut dosyası yoludur. İlk derlemede, Android Studio'daki Gradle senkronizasyonu sırasında veya yapılandırma komut dosyası girişlerinden biri değiştiğinde bir proje yapılandırılır.

  • ninja.arguments, ninja.configure tarafından tanımlanan komut dosyasına aktarılacak bağımsız değişkenler listesidir. Bu listedeki öğeler, değerleri AGP'deki mevcut yapılandırma bağlamına bağlı olan bir makro grubuna başvurabilir:

    • ${ndk.moduleMakeFile}, ninja.configure dosyasının tam yoludur. Dolayısıyla, bu değer C:\path\to\configure-ninja.bat olacaktır.

    • ${ndk.variantName}, oluşturulmakta olan mevcut AGP varyantının adıdır. Örneğin, hata ayıklama veya yayınlama.

    • ${ndk.abi}, oluşturulmakta olan mevcut AGP ABI'nın adıdır. Örneğin, x86 veya arm64-v8a.

    ziyaret edin.
    • ${ndk.buildRoot}, AGP tarafından oluşturulan ve komut dosyasının çıktısını yazdığı bir klasörün adıdır. Bu işlemin ayrıntıları 2. Adım: Yapılandırma komut dosyasını oluşturun bölümünde açıklanacaktır.

    • ${ndk.ndkVersion}, kullanılacak NDK sürümüdür. Bu, genellikle build.gradle dosyasında android.ndkVersion'a iletilen değer veya herhangi bir değer yoksa varsayılan değerdir.

    • ${ndk.minPlatform}, AGP tarafından istenen minimum hedef Android platformudur.

  • ninja.targets, oluşturulması gereken belirli Ninja hedeflerinin listesidir.

2. Adım: Yapılandırma komut dosyasını oluşturun

Yapılandırma komut dosyasının (önceki örnekte configure-ninja.bat) minimum sorumluluğu, Ninja ile oluşturulduğunda projenin tüm yerel çıkışlarını derleyip bağlayacak bir build.ninja dosyası oluşturmaktır. Bunlar genellikle .o (Nesne), .a (Arşiv) ve .so (Paylaşılan Nesne) dosyalarıdır.

Yapılandırma komut dosyası, ihtiyaçlarınıza bağlı olarak build.ninja dosyasını iki farklı yere yazabilir.

  • AGP'nin konum seçmesinde bir sakınca yoksa yapılandırma komut dosyası, ${ndk.buildRoot} makrosunda ayarlanan konuma build.ninja yazar.

  • Yapılandırma komut dosyasının build.ninja dosyasının konumunu seçmesi gerekiyorsa, ${ndk.buildRoot} makrosunda ayarlanan konuma build.ninja.txt adlı bir dosya da yazar. Bu dosya, yapılandırma komut dosyasının yazdığı build.ninja dosyasının tam yolunu içerir.

build.ninja dosyasının yapısı

Genel olarak, Android C/C++ derlemesini doğru şekilde temsil eden çoğu yapı işe yarayacaktır. AGP ve Android Studio için gereken temel öğeler şunlardır:

  • C/C++ kaynak dosyalarının listesi ve Clang'in derlemek için ihtiyaç duyduğu işaretler.

  • Çıkış kitaplıklarının listesi. Bunlar genellikle .so (paylaşılan nesne) dosyalarıdır, ancak aynı zamanda .a (arşiv) veya yürütülebilir (uzantısız) olabilirler.

build.ninja dosyası oluşturmayla ilgili örneklere ihtiyacınız varsa build.ninja oluşturucu kullanıldığında CMake çıkışına bakabilirsiniz.

Minimal bir build.ninja şablonu örneğini aşağıda bulabilirsiniz.

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

En iyi uygulamalar

Gerekliliklere (kaynak dosyaların ve çıkış kitaplıklarının listesi) ek olarak, aşağıda önerilen bazı en iyi uygulamalar yer almaktadır.

Adlandırılmış çıkışları phony kurallarıyla bildirme

Mümkün olduğunda, build.ninja yapısının, derleme çıkışlarına kullanıcıların okuyabileceği adlar vermek için phony kurallarını kullanması önerilir. Dolayısıyla, örneğin, c:/path/to/lib.so adlı bir çıkışınız varsa aşağıdaki gibi okunabilir bir ad verebilirsiniz.

build curl: phony /path/to/lib.so

Bunu yapmanın avantajı, bu adı daha sonra build.gradle dosyasında bir derleme hedefi olarak belirtebilmenizdir. Örneğin,

android {
  defaultConfig {
    externalNativeBuild {
      ...
      experimentalProperties["ninja.targets"] = [ "curl" ]

Bir "tümü" belirtin hedef

Bir all hedefi belirlediğinizde bu, build.gradle dosyasında açıkça hiçbir hedef belirtilmediğinde AGP tarafından oluşturulan varsayılan kitaplık grubu olur.

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

Alternatif bir derleme yöntemi belirtin (isteğe bağlı)

Daha gelişmiş bir kullanım alanı da Ninja'da yerleşik olmayan mevcut bir derleme sistemini kullanmaktır. Bu durumda, Android Studio'nun otomatik tamamlama ve tanıma git gibi uygun dil hizmeti özelliklerini sunabilmesi için yine de tüm kaynakları çıkış kitaplıklarıyla birlikte işaretleriyle temsil etmeniz gerekir. Ancak, gerçek derleme sırasında AGP'nin temel derleme sistemini dikkate almasını istersiniz.

Bunu yapmak için belirli bir .passthrough uzantısına sahip Ninja derleme çıkışını kullanabilirsiniz.

Daha somut bir örnek olarak, bir MSBuild'i sarmalamak istediğinizi varsayalım. Yapılandırma komut dosyanız her zamanki gibi build.ninja oluşturur, ancak aynı zamanda AGP'nin MSBuild'i nasıl çağıracağını tanımlayan bir geçiş hedefi de ekler.

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

Geri bildirim gönder

Bu özellik deneysel olduğundan, geri bildirimleriniz bizim için çok değerlidir. Aşağıdaki kanalları kullanarak geri bildirimde bulunabilirsiniz:

  • Genel geri bildirim için bu hataya yorum ekleyin.

  • Hata bildirmek için Android Studio'yu açın ve Yardım > Geri Bildirim Gönderin. "Custom C/C++ Build Systems" (Özel C/C++ Derleme Sistemleri) öğesini referans gösterdiğinizden emin olun. nasıl yardımcı olabileceğinden bahsettik.

  • Android Studio yüklü değilse bildirmek için bu şablonu kullanarak hata bildiriminde bulunun.