30、Android將 Gradle 關聯到您的原生庫

如需添加您的原生庫項目作爲 Gradle 構建依賴項,您需要向 Gradle 提供 CMake 或 ndk-build 腳本文件的路徑。當您構建應用時,Gradle 會運行 CMake 或 ndk-build,並將共享的庫打包到您的 APK 中。Gradle 還會使用構建腳本來了解要將哪些文件添加到您的 Android Studio 項目中,以便您可以從 Project 窗口訪問這些文件。如果您沒有原生源代碼文件的構建腳本,則需要先創建 CMake 構建腳本,然後再繼續。

Android 項目中的每個模塊只能關聯到一個 CMake 或 ndk-build 腳本文件。例如,如果您想要構建並打包來自多個 CMake 項目的輸出,就需要使用一個 CMakeLists.txt 文件作爲頂級 CMake 構建腳本(然後將 Gradle 關聯到該腳本),並添加其他 CMake 項目作爲該構建腳本的依賴項。同樣,如果您使用的是 ndk-build,則可以在頂級 Android.mk 腳本文件中包含其他 Makefile

將 Gradle 關聯到原生項目後,Android Studio 會更新 Project 窗格,以在 cpp 組中顯示源代碼文件和原生庫,並在 External Build Files 組中顯示外部構建腳本。

注意:更改 Gradle 配置後,請務必點擊工具欄中的 Sync Project 圖標 ,以便讓所做的更改生效。此外,如果要在將 CMake 或 ndk-build 腳本文件關聯到 Gradle 之後再對文件進行更改,您應當從菜單欄中選擇 Build > Refresh Linked C++ Projects,將 Android Studio 與您的更改進行同步。

您可以使用 Android Studio 界面將 Gradle 關聯到外部 CMake 或 ndk-build 項目:

  1. 從 IDE 左側打開 Project 窗格,然後選擇 Android 視圖。
  2. 右鍵點擊您想要關聯到原生庫的模塊(例如 app 模塊),然後從菜單中選擇 Link C++ Project with Gradle。您會看到一個類似於圖 4 所示的對話框。
  3. 從下拉菜單中,選擇 CMake 或 ndk-build
    1. 如果您選擇 CMake,請使用 Project Path 旁的字段爲您的外部 CMake 項目指定 CMakeLists.txt 腳本文件。
    2. 如果您選擇 ndk-build,請使用 Project Path 旁的字段爲您的外部 ndk-build 項目指定 Android.mk 腳本文件。如果 Application.mk 文件與您的 Android.mk 文件位於同一目錄下,Android Studio 也會包含此文件。
    圖 1. 使用 Android Studio 對話框關聯外部 C++ 項目

     

  4. 點擊 OK

手動配置 Gradle

要手動配置 Gradle 以關聯到您的原生庫,您需要將 externalNativeBuild 塊添加到模塊級 build.gradle 文件中,並使用 cmake 或 ndkBuild 塊對其進行配置:

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

注意:如果您要將 Gradle 關聯到現有的 ndk-build 項目,請使用 ndkBuild 塊(而不是 cmake 塊),並提供指向 Android.mk 文件的相對路徑。如果 Application.mk 文件與您的 Android.mk 文件位於同一目錄下,Gradle 也會包含此文件。

指定可選配置

您可以在模塊級 build.gradle 文件的 defaultConfig 塊中配置另一個 externalNativeBuild 塊,爲 CMake 或 ndk-build 指定可選參數和標記。與 defaultConfig 塊中的其他屬性類似,您也可以在構建配置中爲每種產品特性重寫這些屬性。

例如,如果您的 CMake 或 ndk-build 項目定義多個原生庫和可執行文件,您可以使用 targets 屬性爲指定產品特性構建和打包其中的部分工件。以下代碼示例說明了您可以配置的部分屬性:

    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 APK.
              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 APK 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 {...}
      }
    }

如需詳細瞭解如何配置產品變種和構建變體,請參閱配置構建變體。如需瞭解您可以使用 arguments 屬性爲 CMake 配置的變量列表,請參閱使用 CMake 變量

添加預構建的原生庫

如果您希望 Gradle 將預構建的原生庫打包到您的 APK 中,請修改默認的源代碼集配置,以添加預構建 .so 文件所在的目錄,如下所示。請注意,若要添加關聯到 Gradle 的 CMake 構建腳本的工件,則無需執行此操作。

    android {
        ...
        sourceSets {
            main {
                jniLibs.srcDirs 'imported-lib/src/', 'more-imported-libs/src/'
            }
        }
    }

指定 ABI

默認情況下,Gradle 會針對 NDK 支持的應用二進制接口 (ABI) 將您的原生庫構建到單獨的 .so 文件中,並將這些文件全部打包到您的 APK 中。如果您希望 Gradle 僅構建和打包原生庫的部分 ABI 配置,則可以在模塊級 build.gradle 文件中使用 ndk.abiFilters 標記指定這些配置,如下所示:

    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 APK.
          abiFilters 'x86', 'x86_64', 'armeabi', 'armeabi-v7a',
                       'arm64-v8a'
        }
      }
      buildTypes {...}
      externalNativeBuild {...}
    }

在大多數情況下,您只需要在 ndk 塊中指定 abiFilters(如上所示),因爲它會指示 Gradle 構建和打包原生庫的這些版本。但是,如果您想控制 Gradle 應當構建的配置,而不依賴於您希望其打包到 APK 中的配置,請在 defaultConfig.externalNativeBuild.cmake 塊(或 defaultConfig.externalNativeBuild.ndkBuild 塊)中配置另一個 abiFilters 標記。Gradle 會構建這些 ABI 配置,但只會打包您在 defaultConfig.ndk 塊中指定的配置。

爲了進一步降低 APK 的大小,請考慮基於 ABI 配置多個 APK,而不是創建一個包含原生庫所有版本的大型 APK。Gradle 會爲您想要支持的每個 ABI 創建單獨的 APK,並且僅打包每個 ABI 需要的文件。如果您爲每個 ABI 配置多個 APK,而不像上面的代碼示例中所示的那樣指定 abiFilters 標記,則 Gradle 會爲您的原生庫構建所有受支持的 ABI 版本,但是僅打包您在多 APK 配置中指定的版本。爲避免構建不想要的原生庫版本,請爲 abiFilters 標記和“一個 ABI 多個 APK”配置提供相同的 ABI 列表。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章