ネイティブ ライブラリ プロジェクトを Gradle ビルド依存関係として組み込むには、CMake または ndk-build のスクリプト ファイルへのパスを Gradle に指定する必要があります。アプリをビルドすると、Gradle は CMake または ndk-build を実行し、アプリと共有ライブラリをパッケージ化します。さらに、ビルド スクリプトも使って、Android Studio プロジェクトに含めるファイルも判別するため、[Project] ウィンドウからそれらのファイルにアクセスできます。ネイティブ ソースのビルド スクリプトがない場合は、次の手順に進む前に CMake ビルド スクリプトを作成する必要があります。
  Android プロジェクト内の各モジュールがリンクできるのは、それぞれ 1 つのスクリプト ファイル(CMake または ndk-build)に限られます。そのため、たとえば複数の CMake プロジェクトからビルドして出力をパッケージ化する場合、1 つの CMakeLists.txt ファイルを最上位の CMake ビルド スクリプトとして使用し(Gradle をそれにリンクし)、そのビルド スクリプトの依存関係として、その他の CMake プロジェクトを追加する必要があります。ndk-build を使用する場合も同様に、最上位の Android.mk スクリプト ファイルにその他の makefile を含めることができます。
    
Gradle をネイティブ プロジェクトにリンクすると、Android Studio では [Project] ペインが更新され [cpp] グループにソースファイルとネイティブ ライブラリが表示され、[External Build Files] グループに外部ビルド スクリプトが表示されます。
  注: Gradle の設定を変更したときは、必ずツールバーのプロジェクトの同期アイコン  をクリックして変更を適用してください。また、Gradle にリンクした後に CMake または ndk-build のスクリプト ファイルを変更したときは、メニューバーから [Build] > [Refresh Linked C++ Projects] を選択して、Android Studio と変更内容を同期する必要があります。
 をクリックして変更を適用してください。また、Gradle にリンクした後に CMake または ndk-build のスクリプト ファイルを変更したときは、メニューバーから [Build] > [Refresh Linked C++ Projects] を選択して、Android Studio と変更内容を同期する必要があります。
Android Studio UI を使用する
Android Studio UI を使用して Gradle を外部の CMake または ndk-build のビルド プロジェクトにリンクすることが可能です。
- IDE の左側の [Project] ペインを開き、[Android] ビューを選択します。
- app モジュールなど、ネイティブ ライブラリにリンクするモジュールを右クリックし、メニューから [Link C++ Project with Gradle] を選択します。図 4 に示すようなダイアログが表示されます。
- プルダウン メニューから [CMake] または [ndk-build] を選択します。
    - [CMake] を選択した場合は、[Project Path] の横にあるフィールドで、外部 CMake プロジェクト用の CMakeLists.txtスクリプト ファイルを指定します。
- [ndk-build] を選択した場合は、[Project Path] の横にあるフィールドで、外部 ndk-build プロジェクト用の Android.mkスクリプト ファイルを指定します。Android Studio は、Android.mkファイルと同じディレクトリに配置されているApplication.mkファイルがあれば、それも対象に含めます。
   図 4. Android Studio ダイアログを使って外部の C++ プロジェクトをリンクする 
- [CMake] を選択した場合は、[Project Path] の横にあるフィールドで、外部 CMake プロジェクト用の 
- [OK] をクリックします。
Gradle を手動で設定する
  Gradle をネイティブ ライブラリにリンクするように手動で設定するには、externalNativeBuild ブロックをモジュール レベルの build.gradle ファイルに追加し、cmake ブロックまたは ndkBuild ブロックを使って設定する必要があります。
Groovy
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") } } }
  注: Gradle を既存の ndk-build プロジェクトにリンクする場合は、cmake ブロックではなく ndkBuild ブロックを使用して、Android.mk ファイルへの相対パスを指定します。Gradle は、Android.mk ファイルと同じディレクトリに配置されている Application.mk ファイルがあれば、それも対象に含めます。
オプション構成を指定する
  CMake または ndk-build のオプションの引数やフラグを指定するには、モジュール レベルの build.gradle ファイルの defaultConfig ブロック内に別の externalNativeBuild ブロックを設定します。defaultConfig ブロック内のその他のプロパティと同様に、ビルド設定のプロダクト フレーバーごとに、これらのプロパティをオーバーライドできます。
  たとえば、CMake または ndk-build のプロジェクトで複数のネイティブ ライブラリや実行可能ファイルを定義する場合、targets プロパティを使用して、特定のプロダクト フレーバーのアーティファクトのサブセットのみをビルドしてパッケージ化することが可能です。設定できるプロパティの一部を、次のサンプルコードに示します。
Groovy
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 {...} } }
  プロダクト フレーバーとビルド バリアントの設定方法については、ビルド バリアントを設定するをご覧ください。arguments プロパティを使用して CMake で設定できる変数のリストについては、CMake 変数を使用する場合の説明をご覧ください。
ビルド済みのネイティブ ライブラリを組み込む
外部ネイティブ ビルドで使用されていないビルド済みネイティブ ライブラリを Gradle でパッケージ化する場合、それをモジュールの src/main/jniLibs/ABI ディレクトリに追加します。
バージョン 4.0 より前の Android Gradle プラグインでは、CMake の IMPORTED ターゲットをアプリに組み込むには、それを jniLibs ディレクトリに含める必要がありました。以前のバージョンのプラグインから移行する場合には、次のようなエラーが発生する可能性があります。
* 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 プラグイン 4.0 を使用している場合、CMake の IMPORTED ターゲットが使用するライブラリを jniLibs ディレクトリから移動することでこのエラーを回避できます。
ABI を指定する
  Gradle はデフォルトでは、NDK がサポートするアプリケーション バイナリ インターフェース(ABI)の個々の .so ファイルにネイティブ ライブラリをビルドし、それをすべてアプリにパッケージ化します。Gradle を使ってネイティブ ライブラリの特定の API 設定のみビルドしてパッケージ化したい場合は、下記に示すように、モジュール レベルの build.gradle ファイル内で ndk.abiFilters フラグを使って指定できます。
Groovy
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 {...}
}
  ほとんどの場合、必要なのは上記のように ndk ブロックに abiFilters を指定することだけです。この設定によって Gradle はネイティブ ライブラリの目的のバージョンを対象に、ビルドとパッケージ化の両方を行うからです。ただし、アプリにパッケージ化する対象とは別個に、Gradle がビルドする対象を制御する場合は、defaultConfig.externalNativeBuild.cmake ブロック(または defaultConfig.externalNativeBuild.ndkBuild ブロック)内で別の abiFilters フラグを設定します。Gradle はその ABI 構成をビルドしますが、パッケージ化するのは defaultConfig.ndk ブロック内で指定したものだけに限られます。
ダウンロード時に配信されるのは、ユーザーのデバイスの ABI に一致するネイティブ ライブラリだけであるため、アプリのサイズをさらに小さくするために、Android App Bundle を使用して公開することをおすすめします。
 APK を使用して旧式アプリ(2021 年 8 月より前に作成)を公開する場合は、ABI に基づくマルチ APK を設定することをおすすめします。ネイティブ ライブラリのすべてのバージョンを組み込んだ単一の大きな APK を作成するのではなく、サポート対象の ABI ごとに Gradle で個別の APK を作成し、各 ABI に必要なファイルだけをパッケージ化するようにします。上記のサンプルコードに示すように、abiFilters フラグを指定せずに、ABI ごとに複数の APK を設定する場合、ネイティブ ライブラリについて、サポート対象のすべての ABI バージョンが Gradle でビルドされますが、パッケージ化されるのは、マルチ APK 設定で指定するものだけです。不要なバージョンのネイティブ ライブラリをビルド対象から除外するには、abiFilters フラグと ABI ごとのマルチ APK 設定の両方に、ABI の同じリストを指定します。
    
