Link Gradle to your native library

To include your native library project as a Gradle build dependency, you need to provide Gradle with the path to your CMake or ndk-build script file. When you build your app, Gradle runs CMake or ndk-build, and packages shared libraries with your APK. Gradle also uses the build script to know which files to pull into your Android Studio project, so you can access them from the Project window. If you don’t have a build script for your native sources, you need to create a CMake build script before you proceed.

Each module in your Android project can link to only one CMake or ndk-build script file. So, for example, if you want to build and package outputs from multiple CMake projects, you need to use one CMakeLists.txt file as your top-level CMake build script (which you then link Gradle to) and add other CMake projects as dependencies of that build script. Similarly, if you're using ndk-build, you can include other Makefiles in your top-level Android.mk script file.

Once you link Gradle to a native project, Android Studio updates the Project pane to show your source files and native libraries in the cpp group, and your external build scripts in the External Build Files group.

Note: When making changes to the Gradle configuration, make sure to apply your changes by clicking Sync ProjectLink Gradle - 图1 in the toolbar. Additionally, when making changes to your CMake or ndk-build script file after you have already linked it to Gradle, you should sync Android Studio with your changes by selecting Build > Refresh Linked C++ Projects from the menu bar.

Use the Android Studio UI

You can link Gradle to an external CMake or ndk-build project using the Android Studio UI:

  • Open the Project pane from the left side of the IDE and select the Android view.
  • Right-click on the module you would like to link to your native library, such as the app module, and select Link C++ Project with Gradle from the menu. You should see a dialog similar to the one shown in figure 4.
  • From the drop-down menu, select either CMake or ndk-build.

    • If you select CMake, use the field next to Project Path to specify the CMakeLists.txt script file for your external CMake project.
    • If you select ndk-build, use the field next to Project Path to specify the Android.mk script file for your external ndk-build project. Android Studio also includes the Application.mk file if it is located in the same directory as your Android.mk file. Link Gradle - 图2
      Figure 4. Linking an external C++ project using the Android Studio dialog.
  • Click OK.

Manually configure Gradle

To manually configure Gradle to link to your native library, you need to add the externalNativeBuild block to your module-level build.gradle file and configure it with either the cmake or ndkBuild block:

  1. android {
  2. ...
  3. defaultConfig {...}
  4. buildTypes {...}
  5.  
  6. // Encapsulates your external native build configurations.
  7. externalNativeBuild {
  8.  
  9. // Encapsulates your CMake build configurations.
  10. cmake {
  11.  
  12. // Provides a relative path to your CMake build script.
  13. path "CMakeLists.txt"
  14. }
  15. }
  16. }

Note: If you want to link Gradle to an existing ndk-build project, use the ndkBuild block instead of the cmake block, and provide a relative path to your Android.mk file. Gradle also includes the Application.mk file if it is located in the same directory as your Android.mk file.

Specify optional configurations

You can specify optional arguments and flags for CMake or ndk-build by configuring another externalNativeBuild block within the defaultConfig block of your module-level build.gradle file. Similar to other properties in the defaultConfig block, you can override these properties for each product flavor in your build configuration.

For example, if your CMake or ndk-build project defines multiple native libraries and executables, you can use the targets property to build and package only a subset of those artifacts for a given product flavor. The following code sample describes some of the properties you can configure:

  1. android {
  2. ...
  3. defaultConfig {
  4. ...
  5. // This block is different from the one you use to link Gradle
  6. // to your CMake or ndk-build script.
  7. externalNativeBuild {
  8.  
  9. // For ndk-build, instead use the ndkBuild block.
  10. cmake {
  11.  
  12. // Passes optional arguments to CMake.
  13. arguments "-DANDROID_ARM_NEON=TRUE", "-DANDROID_TOOLCHAIN=clang"
  14.  
  15. // Sets a flag to enable format macro constants for the C compiler.
  16. cFlags "-D__STDC_FORMAT_MACROS"
  17.  
  18. // Sets optional flags for the C++ compiler.
  19. cppFlags "-fexceptions", "-frtti"
  20. }
  21. }
  22. }
  23.  
  24. buildTypes {...}
  25.  
  26. productFlavors {
  27. ...
  28. demo {
  29. ...
  30. externalNativeBuild {
  31. cmake {
  32. ...
  33. // Specifies which native libraries or executables to build and package
  34. // for this product flavor. The following tells Gradle to build only the
  35. // "native-lib-demo" and "my-executible-demo" outputs from the linked
  36. // CMake project. If you don't configure this property, Gradle builds all
  37. // executables and shared object libraries that you define in your CMake
  38. // (or ndk-build) project. However, by default, Gradle packages only the
  39. // shared libraries in your APK.
  40. targets "native-lib-demo",
  41. // You need to specify this executable and its sources in your CMakeLists.txt
  42. // using the add_executable() command. However, building executables from your
  43. // native sources is optional, and building native libraries to package into
  44. // your APK satisfies most project requirements.
  45. "my-executible-demo"
  46. }
  47. }
  48. }
  49.  
  50. paid {
  51. ...
  52. externalNativeBuild {
  53. cmake {
  54. ...
  55. targets "native-lib-paid",
  56. "my-executible-paid"
  57. }
  58. }
  59. }
  60. }
  61.  
  62. // Use this block to link Gradle to your CMake or ndk-build script.
  63. externalNativeBuild {
  64. cmake {...}
  65. // or ndkBuild {...}
  66. }
  67. }

To learn more about configuring product flavors and build variants, go to Configure Build Variants. For a list of variables you can configure for CMake with the arguments property, see Using CMake Variables.

Include prebuilt native libraries

If you want Gradle to package prebuilt native librarieswith your APK,modify the default source set configurationto include the directory of your prebuilt .so files, as shown below. Keep inmind, you don't need to do this to include artifacts of CMake build scripts thatyou link to Gradle.

  1. android {
  2. ...
  3. sourceSets {
  4. main {
  5. jniLibs.srcDirs 'imported-lib/src/', 'more-imported-libs/src/'
  6. }
  7. }
  8. }

Specify ABIs

By default, Gradle builds your native library into separate .so files for the Application Binary Interfaces (ABIs) the NDK supports and packages them all into your APK. If you want Gradle to build and package only certain ABI configurations of your native libraries, you can specify them with the ndk.abiFilters flag in your module-level build.gradle file, as shown below:

  1. android {
  2. ...
  3. defaultConfig {
  4. ...
  5. externalNativeBuild {
  6. cmake {...}
  7. // or ndkBuild {...}
  8. }
  9.  
  10. // Similar to other properties in the defaultConfig block,
  11. // you can configure the ndk block for each product flavor
  12. // in your build configuration.
  13. ndk {
  14. // Specifies the ABI configurations of your native
  15. // libraries Gradle should build and package with your APK.
  16. abiFilters 'x86', 'x86_64', 'armeabi', 'armeabi-v7a',
  17. 'arm64-v8a'
  18. }
  19. }
  20. buildTypes {...}
  21. externalNativeBuild {...}
  22. }

In most cases, you only need to specify abiFilters in the ndk block, as shown above, because it tells Gradle to both build and package those versions of your native libraries. However, if you want to control what Gradle should build, independently of what you want it to package into your APK, configure another abiFilters flag in the defaultConfig.externalNativeBuild.cmake block (or defaultConfig.externalNativeBuild.ndkBuild block). Gradle builds those ABI configurations but only packages the ones you specify in the defaultConfig.ndk block.

To further reduce the size of your APK, consider configuring multiple APKs based on ABI—instead of creating one large APK with the all versions of your native libraries, Gradle creates a separate APK for each ABI you want to support and only packages the files each ABI needs. If you configure multiple APKs per ABI without specifying the abiFilters flag as shown in the code sample above, Gradle builds all supported ABI versions of your native libraries, but only packages those you specify in your multiple APK configuration. To avoid building versions of your native libraries that you don't want, provide the same list of ABIs for both the abiFilters flag and your per-ABI multiple APK configuration.