Gradle'ı yerel kitaplığınıza bağlama

Yerel kitaplık projenizi Gradle derleme bağımlılığı olarak eklemek için Gradle'a CMake veya ndk-build komut dosyası dosyanızın yolunu sağlamanız gerekir. Uygulamanızı derlediğinizde Gradle, CMake veya ndk-build'i çalıştırır ve uygulamanızla paylaşılan kitaplıkları paketler. Gradle, Android Studio projenize hangi dosyaların çekileceğini bilmek için derleme komut dosyasını da kullanır. Böylece, Proje penceresinden dosyalara erişebilirsiniz. Yerel kaynaklarınız için bir derleme komut dosyanız yoksa devam etmeden önce bir CMake derleme komut dosyası oluşturmanız gerekir.

Android projenizdeki her modül yalnızca bir CMake veya ndk-build komut dosyası dosyasına bağlanabilir. Örneğin, birden fazla CMake projesinden çıkış oluşturup paketlemek istiyorsanız üst düzey CMake derleme komut dosyanız olarak bir CMakeLists.txt dosyası kullanmanız (daha sonra Gradle'ı bu dosyaya bağlarsınız) ve başka CMake projelerini bu derleme komut dosyasının bağımlılıkları olarak eklemeniz gerekir. Benzer şekilde, ndk-build kullanıyorsanız üst düzey Android.mk komut dosyanıza diğer Makefiles dosyalarını ekleyebilirsiniz.

Gradle'ı yerel bir projeye bağladıktan sonra Android Studio, Proje bölmesini güncelleyerek kaynak dosyalarınızı ve yerel kitaplıklarınızı cpp grubunda, harici derleme komut dosyalarınızı ise Harici Derleme Dosyaları grubunda gösterir.

Not: Gradle yapılandırmasında değişiklik yaparken araç çubuğunda Projeyi Senkronize Et simgesini tıklayarak değişikliklerinizi uyguladığınızdan emin olun. Ayrıca, Gradle'a bağladıktan sonra CMake veya ndk-build komut dosyası dosyanızda değişiklik yaparken menü çubuğundan Derleme > Bağlı C++ Projelerini Yenile'yi seçerek Android Studio'yu yaptığınız değişikliklerle senkronize etmeniz gerekir.

Android Studio kullanıcı arayüzünü kullanarak Gradle'ı harici bir CMake veya ndk-build projesine bağlayabilirsiniz:

  1. IDE'nin sol tarafından Proje bölmesini açın ve Android görünümünü seçin.
  2. Yerel kitaplığınıza bağlamak istediğiniz uygulama modülü gibi modülü sağ tıklayın ve menüden C++ projesini Gradle ile bağla'yı seçin. Şekil 4'te gösterilene benzer bir iletişim kutusu görürsünüz.
  3. Açılır menüden CMake veya ndk-build seçeneğini belirleyin.
    1. CMake'ı seçerseniz harici CMake projeniz için CMakeLists.txt komut dosyası dosyasını belirtmek üzere Proje Yolu'nun yanındaki alanı kullanın.
    2. ndk-build'i seçerseniz harici ndk-build projenizin Android.mk komut dosyasını belirtmek için Proje Yolu'nun yanındaki alanı kullanın. Android Studio, Android.mk dosyanızla aynı dizinde bulunuyorsa Application.mk dosyasını da içerir.

    4. Şekil. Android Studio iletişim kutusunu kullanarak harici bir C++ projesini bağlama.

  4. Tamam'ı tıklayın.

Gradle'ı manuel olarak yapılandırın

Gradle'ı yerel kitaplığınıza bağlantı oluşturacak şekilde manuel olarak yapılandırmak için externalNativeBuild bloğunu modül düzeyindeki build.gradle dosyanıza eklemeniz ve cmake ya da ndkBuild blokuyla yapılandırmanız gerekir:

Modern

android {
  ...
  defaultConfig {...}
  buildTypes {...}

  // Encapsulates your external native build configurations.
  externalNativeBuild {

    // Encapsulates your CMake build configurations.
    cmake {

      // Provides a relative path to your CMake build script.
      path "CMakeLists.txt"
    }
  }
}

Kotlin

android {
  ...
  defaultConfig {...}
  buildTypes {...}

  // Encapsulates your external native build configurations.
  externalNativeBuild {

    // Encapsulates your CMake build configurations.
    cmake {

      // Provides a relative path to your CMake build script.
      path = file("CMakeLists.txt")
    }
  }
}

Not: Gradle'ı mevcut bir ndk-build projesine bağlamak istiyorsanız cmake bloku yerine ndkBuild blokunu kullanın ve Android.mk dosyanız için göreli bir yol sağlayın. Gradle, Android.mk dosyanızla aynı dizinde bulunuyorsa Application.mk dosyasını da içerir.

İsteğe bağlı yapılandırmaları belirtin

Modül düzeyindeki build.gradle dosyanızın defaultConfig bloğunda başka bir externalNativeBuild bloğu yapılandırarak CMake veya ndk-build için isteğe bağlı bağımsız değişkenler ve işaretler belirtebilirsiniz. defaultConfig bloğundaki diğer özelliklere benzer şekilde, derleme yapılandırmanızdaki her ürün çeşidi için bu özellikleri geçersiz kılabilirsiniz.

Örneğin, CMake veya ndk-build projeniz birden fazla yerel kitaplık ve yürütülebilir dosya tanımlıyorsa belirli bir ürün çeşidi için bu yapıların yalnızca bir alt kümesini oluşturup paketlemek amacıyla targets özelliğini kullanabilirsiniz. Aşağıdaki kod örneğinde, yapılandırabileceğiniz bazı özellikler açıklanmaktadır:

Modern

android {
  ...
  defaultConfig {
    ...
    // This block is different from the one you use to link Gradle
    // to your CMake or ndk-build script.
    externalNativeBuild {

      // For ndk-build, instead use the ndkBuild block.
      cmake {

        // Passes optional arguments to CMake.
        arguments "-DANDROID_ARM_NEON=TRUE", "-DANDROID_TOOLCHAIN=clang"

        // Sets a flag to enable format macro constants for the C compiler.
        cFlags "-D__STDC_FORMAT_MACROS"

        // Sets optional flags for the C++ compiler.
        cppFlags "-fexceptions", "-frtti"
      }
    }
  }

  buildTypes {...}

  productFlavors {
    ...
    demo {
      ...
      externalNativeBuild {
        cmake {
          ...
          // Specifies which native libraries or executables to build and package
          // for this product flavor. The following tells Gradle to build only the
          // "native-lib-demo" and "my-executible-demo" outputs from the linked
          // CMake project. If you don't configure this property, Gradle builds all
          // executables and shared object libraries that you define in your CMake
          // (or ndk-build) project. However, by default, Gradle packages only the
          // shared libraries in your app.
          targets "native-lib-demo",
                  // You need to specify this executable and its sources in your CMakeLists.txt
                  // using the add_executable() command. However, building executables from your
                  // native sources is optional, and building native libraries to package into
                  // your app satisfies most project requirements.
                  "my-executible-demo"
        }
      }
    }

    paid {
      ...
      externalNativeBuild {
        cmake {
          ...
          targets "native-lib-paid",
                  "my-executible-paid"
        }
      }
    }
  }

  // Use this block to link Gradle to your CMake or ndk-build script.
  externalNativeBuild {
    cmake {...}
    // or ndkBuild {...}
  }
}

Kotlin

android {
  ...
  defaultConfig {
    ...
    // This block is different from the one you use to link Gradle
    // to your CMake or ndk-build script.
    externalNativeBuild {

      // For ndk-build, instead use the ndkBuild block.
      cmake {

        // Passes optional arguments to CMake.
        arguments += listOf("-DANDROID_ARM_NEON=TRUE", "-DANDROID_TOOLCHAIN=clang")

        // Sets a flag to enable format macro constants for the C compiler.
        cFlags += listOf("-D__STDC_FORMAT_MACROS")

        // Sets optional flags for the C++ compiler.
        cppFlags += listOf("-fexceptions", "-frtti")
      }
    }
  }

  buildTypes {...}

  productFlavors {
    ...
    create("demo") {
      ...
      externalNativeBuild {
        cmake {
          ...
          // Specifies which native libraries or executables to build and package
          // for this product flavor. The following tells Gradle to build only the
          // "native-lib-demo" and "my-executible-demo" outputs from the linked
          // CMake project. If you don't configure this property, Gradle builds all
          // executables and shared object libraries that you define in your CMake
          // (or ndk-build) project. However, by default, Gradle packages only the
          // shared libraries in your app.
          targets += listOf("native-lib-demo",
                  // You need to specify this executable and its sources in your CMakeLists.txt
                  // using the add_executable() command. However, building executables from your
                  // native sources is optional, and building native libraries to package into
                  // your app satisfies most project requirements.
                  "my-executible-demo")
        }
      }
    }

    create("paid") {
      ...
      externalNativeBuild {
        cmake {
          ...
          targets += listOf("native-lib-paid",
                  "my-executible-paid")
        }
      }
    }
  }

  // Use this block to link Gradle to your CMake or ndk-build script.
  externalNativeBuild {
    cmake {...}
    // or ndkBuild {...}
  }
}

Ürün çeşitlerini yapılandırma ve varyant oluşturma hakkında daha fazla bilgi edinmek için Derleme Varyantlarını Yapılandırma bölümüne gidin. arguments mülküyle CMake için yapılandırabileceğiniz değişkenlerin listesi için CMake Değişkenlerini Kullanma konusuna bakın.

Önceden oluşturulmuş yerel kitaplıkları dahil et

Gradle'ın herhangi bir harici yerel derlemede kullanılmayan önceden oluşturulmuş yerel kitaplıkları paketlemesini istiyorsanız bunları modülünüzün src/main/jniLibs/ABI dizinine ekleyin.

Uygulamanıza dahil edebilmeleri için jniLibs dizininizdeki CMake IMPORTED hedeflerini de içeren Android Gradle Eklentisi'nin 4.0 öncesi sürümleri gerekir. Eklentinin önceki bir sürümünden geçiş yapıyorsanız aşağıdakine benzer bir hatayla karşılaşabilirsiniz:

* What went wrong:
Execution failed for task ':app:mergeDebugNativeLibs'.
> A failure occurred while executing com.android.build.gradle.internal.tasks.Workers$ActionFacade
   > More than one file was found with OS independent path 'lib/x86/libprebuilt.so'

Android Gradle Plugin 4.0 kullanıyorsanız bu hatayı önlemek için IMPORTED CMake tarafından kullanılan tüm kitaplıkları jniLibs dizininizin dışına taşıyın.

ABI'leri belirtin

Varsayılan olarak Gradle, yerel kitaplığınızı NDK'nın desteklediği Uygulama İkili Arabirimleri (ABI'ler) için ayrı .so dosyaları halinde oluşturur ve bunların tümünü uygulamanızda paketler. Gradle'ın yerel kitaplıklarınızın yalnızca belirli ABI yapılandırmalarını derleyip paketlemesini istiyorsanız bunları, aşağıda gösterildiği gibi modül düzeyindeki build.gradle dosyanızda ndk.abiFilters işaretiyle belirtebilirsiniz:

Modern

android {
  ...
  defaultConfig {
    ...
    externalNativeBuild {
      cmake {...}
      // or ndkBuild {...}
    }

    // Similar to other properties in the defaultConfig block,
    // you can configure the ndk block for each product flavor
    // in your build configuration.
    ndk {
      // Specifies the ABI configurations of your native
      // libraries Gradle should build and package with your app.
      abiFilters 'x86', 'x86_64', 'armeabi', 'armeabi-v7a',
                   'arm64-v8a'
    }
  }
  buildTypes {...}
  externalNativeBuild {...}
}

Kotlin

android {
  ...
  defaultConfig {
    ...
    externalNativeBuild {
      cmake {...}
      // or ndkBuild {...}
    }

    // Similar to other properties in the defaultConfig block,
    // you can configure the ndk block for each product flavor
    // in your build configuration.
    ndk {
      // Specifies the ABI configurations of your native
      // libraries Gradle should build and package with your app.
      abiFilters += listOf("x86", "x86_64", "armeabi", "armeabi-v7a",
                   "arm64-v8a")
    }
  }
  buildTypes {...}
  externalNativeBuild {...}
}

Çoğu durumda, yukarıda gösterildiği gibi ndk bloğunda abiFilters öğesini belirtmeniz yeterlidir. Bunun nedeni, Gradle'a yerel kitaplıklarınızın bu sürümlerini hem derlemesini hem de paketlemesini söylediğindendir. Bununla birlikte, Gradle'ın uygulamanıza ne paketlenmesini istediğinizden bağımsız olarak, ne oluşturması gerektiğini kontrol etmek istiyorsanız defaultConfig.externalNativeBuild.cmake bloğunda (veya defaultConfig.externalNativeBuild.ndkBuild bloğunda) başka bir abiFilters işareti yapılandırın. Gradle, bu ABI yapılandırmalarını oluşturur ancak yalnızca defaultConfig.ndk bloğunda belirttiğiniz yapılandırmaları paketler.

İndirme işlemiyle birlikte yalnızca kullanıcı cihazının ABI'siyle eşleşen yerel kitaplıklar yayınlanacağından uygulamanızın boyutunu daha da küçültmek için Android App Bundle kullanarak yayınlamanız önerilir.

APK'lar (Ağustos 2021'den önce oluşturulmuş) kullanan eski uygulamalarda, yerel kitaplıklarınızın tüm sürümlerini içeren büyük bir APK oluşturmak yerine ABI'ye göre birden fazla APK yapılandırmayı düşünün. Gradle, desteklemek istediğiniz her ABI için ayrı bir APK oluşturur ve yalnızca her ABI'nin ihtiyaç duyduğu dosyaları paketler. Yukarıdaki kod örneğinde gösterildiği gibi abiFilters işaretini belirtmeden ABI başına birden fazla APK yapılandırırsanız Gradle, yerel kitaplıklarınızın desteklenen tüm ABI sürümlerini oluşturur ancak yalnızca birden fazla APK yapılandırmanızda belirttiğiniz ABI sürümlerini paketler. Yerel kitaplıklarınızın istemediğiniz sürümlerini oluşturmamak amacıyla hem abiFilters işareti hem de ABI başına birden fazla APK yapılandırmanız için aynı ABI listesini sağlayın.