AndroidStudio用Cmake方式编译NDK代码(cmake配置.a库)

相逢意气为君饮,系马高楼垂柳边。这篇文章主要讲述AndroidStudio用Cmake方式编译NDK代码(cmake配置.a库)相关的知识,希望能为你提供帮助。
1.cmake是什么?
CMake是一个跨平台的安装(编译)工具,可以用简单的语句来描述所有平台的安装(编译过程)。他能够输出各种各样的makefile或者project文件,能测试编译器所支持的C++特性,类似UNIX下的automake。
 
谷歌从androidStudio2.2以上就添加了Cmake方式来编译NDK代码,并从NDK例子看出,默认编译的方式就是cmake方式。
 
2.谷歌官方的用cmake方式编译NDK的教程
 
谷歌从AndroidStudio2.2以上就添加了Cmake方式来编译NDK代码,并从NDK例子看出,默认编译的方式就是cmake方式。
如果您希望向现有项目添加原生代码,请执行以下步骤:

  1. 创建新的原生源文件并将其添加到您的 Android Studio 项目中。
    • 如果您已经拥有原生代码或想要导入预构建的原生库,则可以跳过此步骤。
  2. 创建 CMake 构建脚本,将您的原生源代码构建到库中。如果导入和关联预构建库或平台库,您也需要此构建脚本。
    • 如果您的现有原生库已经拥有  CMakeLists.txt  构建脚本或者使用 ndk-build 并包含  Android.mk  构建脚本,则可以跳过此步骤。
  3. 提供一个指向您的 CMake 或 ndk-build 脚本文件的路径,将 Gradle 关联到您的原生库。Gradle 使用构建脚本将源代码导入您的 Android Studio 项目并将原生库(SO 文件)封装到 APK 中。
配置完项目后,您可以使用  JNI 框架从 java 代码中访问您的原生函数。要构建和运行应用,只需点击  Run 
AndroidStudio用Cmake方式编译NDK代码(cmake配置.a库)

文章图片

 
言归正传,那么要添加第三方的xx.a链接库呢?
通常我们把第三方提供的h文件夹,放在cpp的include里面。这是规范,不是必须。而xxx.a库放在src/main/jniLibs/armeabi目录下。
本文章以添加libjsoncpp.a连接库做例子
首先在cpp目录下建立一个include文件夹,把jsoncpp官方提供的头文件文件夹拷贝到include里面(我这个项目有3个链接库,jsoncpp, curl , openssl,另外2个仅做参考作用,与其无关)
AndroidStudio用Cmake方式编译NDK代码(cmake配置.a库)

文章图片

 
AndroidStudio用Cmake方式编译NDK代码(cmake配置.a库)

文章图片

 
第二步, 在app的src目录的main下,建立一个文件夹,jniLibs,然后在jniLibs里面再建立一个armeabi文件夹。
然后把libjsoncpp.a链接库拷贝进去。
AndroidStudio用Cmake方式编译NDK代码(cmake配置.a库)

文章图片

 
第三步, 动态库与头文件拷贝进去时候,是需要告诉编译器做关联的。在app目录的src文件夹下有个CMakeLists.txt文件,我们通过它编写配置信息。
将jsoncpp头文件所在目录告诉编译,在里面添加
  1. include_directories(  src/main/cpp/include/jsoncpp)  
如果有多个链接库,那么可以这样
例如有三个链接库,jsoncpp, currl , openssl.
 
  1. include_directories(  src/main/cpp/include/jsoncpp   
  2.                                           src/main/cpp/include/curl   
  3.                                           src/main/cpp/include/openssl   
  4.                                           )   
  然后告诉编译器,libjsoncppp.a在哪个目录下,并指定链接库的名称
接着添加
  1. #添加json库   
  2. add_library(jsoncpp  STATIC  IMPORTED)   
  3. set_target_properties(jsoncpp   
  4.     PROPERTIES  IMPORTED_LOCATION   
  5.     ${CMAKE_SOURCE_DIR}/src/main/jniLibs/${ANDROID_ABI}/libjsoncpp.a)  
然后修改target_link_libraries,加多一行jsoncpp
 
  1. target_link_libraries(native-lib   
  2.                                             jsoncpp   
  3.                                             ${log-lib})  
如果有多个,那么可以多次添加。如
  1. #添加json库   
  2. add_library(jsoncpp  STATIC  IMPORTED)   
  3. set_target_properties(jsoncpp   
  4.     PROPERTIES  IMPORTED_LOCATION   
  5.     ${CMAKE_SOURCE_DIR}/src/main/jniLibs/${ANDROID_ABI}/libjsoncpp.a)   
  6.    
  7. #添加curl网络请求   
  8. add_library(curl  STATIC  IMPORTED)   
  9. set_target_properties(curl   
  10.     PROPERTIES  IMPORTED_LOCATION   
  11.     ${CMAKE_SOURCE_DIR}/src/main/jniLibs/${ANDROID_ABI}/libcurl.a)   
  12.    
  13. #添加加密工具(md5,  base64,  des,  aes  ,  asa)  part-1   
  14. add_library(crypto  STATIC  IMPORTED)   
  15. set_target_properties(crypto   
  16.     PROPERTIES  IMPORTED_LOCATION   
  17.     ${CMAKE_SOURCE_DIR}/src/main/jniLibs/${ANDROID_ABI}/libcrypto.a)   
  18.    
  19. #添加加密工具(md5,  base64,  des,  aes  ,  asa)  des加密  part-2   
  20. add_library(ssl  STATIC  IMPORTED)   
  21. set_target_properties(ssl   
  22.     PROPERTIES  IMPORTED_LOCATION   
  23.     ${CMAKE_SOURCE_DIR}/src/main/jniLibs/${ANDROID_ABI}/libssl.a)   

  1. target_link_libraries(native-lib   
  2.                                             jsoncpp   
  3.                                             curl   
  4.                                             crypto   
  5.                                             ssl   
  6.                                             ${log-lib})     

然后gradle编译就可以使用了。是不是很简单?

 
 
将 Gradle 关联到您的原生库
要将 Gradle 关联到您的原生库,您需要提供一个指向 CMake 或 ndk-build 脚本文件的路径。在您构建应用时,Gradle 会以依赖项的形式运行 CMake 或 ndk-build,并将共享的库封装到您的 APK 中。Gradle 还使用构建脚本来了解要将哪些文件添加到您的 Android Studio 项目中,以便您可以从  Project  窗口访问这些文件。如果您的原生源文件没有构建脚本,则需要先创建 CMake 构建脚本,然后再继续。
将 Gradle 关联到原生项目后,Android Studio 会更新  Project  窗格以在  cpp  组中显示您的源文件和原生库,在  External Build Files  组中显示您的外部构建脚本。
注:更改 Gradle 配置时,请确保通过点击工具栏中的  Sync Project  AndroidStudio用Cmake方式编译NDK代码(cmake配置.a库)  应用更改。此外,如果在将 CMake 或 ndk-build 脚本文件关联到 Gradle 后再对其进行更改,您应当从菜单栏中选择  Build > Refresh Linked C++ Projects,将 Android Studio 与您的更改同步。
使用 Android Studio UI您可以使用 Android Studio UI 将 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 也会包含此文件。
    AndroidStudio用Cmake方式编译NDK代码(cmake配置.a库)图 4.使用 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 ndkBuild {} cmake {// Passes optional arguments to CMake. arguments "-DANDROID_ARM_NEON=TRUE", "-DANDROID_TOOLCHAIN=clang"// Sets optional flags for the C compiler. cFlags "-D_EXAMPLE_C_FLAG1", "-D_EXAMPLE_C_FLAG2"// Sets a flag to enable format macro constants for the C++ compiler. cppFlags "-D__STDC_FORMAT_MACROS" } } }buildTypes {...}productFlavors { ... demo { ... externalNativeBuild { cmake { ... // Specifies which native libraries to build and package for this // product flavor. If you don‘t configure this property, Gradle // builds and packages all shared object libraries that you define // in your CMake or ndk-build project. targets "native-lib-demo" } } }paid { ... externalNativeBuild { cmake { ... targets "native-lib-paid" } } } }// Use this block to link Gradle to your CMake or ndk-build script. externalNativeBuild { cmake {...} // or ndkBuild {...} } }

要详细了解配置产品风味和构建变体,请参阅配置构建变体。如需了解您可以使用  arguments  属性为 CMake 配置的变量列表,请参阅使用 CMake 变量。
指定 ABI默认情况下,Gradle 会针对  NDK 支持的 ABI  将您的原生库构建到单独的  .so  文件中,并将其全部封装到您的 APK 中。如果您希望 Gradle 仅构建和封装原生库的特定 ABI 配置,您可以在模块级  build.gradle  文件中使用  ndk.abiFilters  标志指定这些配置,如下所示:
android { ... defaultConfig { ... externalNativeBuild { cmake {...} // or ndkBuild {...} }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 拆分,但没有像上面的代码示例一样指定  abiFilters  标志,Gradle 会构建原生库的所有受支持 ABI 版本,不过仅会封装您在 ABI 拆分配置中指定的版本。为了避免构建您不想要的原生库版本,请为  abiFilters  标志和 ABI 拆分配置提供相同的 ABI 列表。
【AndroidStudio用Cmake方式编译NDK代码(cmake配置.a库)】 
谷歌从AndroidStudio2.2以上就添加了Cmake方式来编译NDK代码,并从NDK例子看出,默认编译的方式就是cmake方式。


    推荐阅读