前言

 之前有一篇的文章介绍了通过CMake来进行Android NDK开发的入门文章。写那篇文章的时候由于内容较多,   所以有的内容没有细说,就一笔带过了。这篇文章算是一个小小的补充。所以,建议看这篇文章的小伙伴,先阅读之前的博文。  

使用CMake来进行Android NDK 开发


内容

使用CMake来进行Android NDK 开发这篇博文说道,向现有的项目里添加原生代
码的步骤分为***三大步***:

  1. 创建新的原生源文件。
  2. 创建CMake构建脚本。
  3. 将Gradle关联到你的原生库。
    第一步比较简单就不说了,第二步对CMake构建脚本即CMakeLists.txt文件的构建
    说明,先看一张图:

这张图片是系统自动给我们生成的CMakeLists.txt内容,当时我们只说明了add_library命令的作用,
那现在我们看一下find_library 代表什么,根据Google文档,find_library表示定位NDK库,图片上关于这个命令的描述说明还挺好理解的,
查找一个特殊的预构建库并且把其存储路径设置为一个变量。那这个命令里面第一个值是路径变量的名称,
第二个就是你想要CMake去定位的库的具体名字。我们为什么要定位一个NDK库呢?是这样的,Android平台上有一些系统的预构建库,这些系统的库不需要再构建,打包到apk包中的。直接指定其的路径就可以使用了。那现在用了find_library就可以直接使用系统的预构建库了么?还不行,我们还差一个target_link_libraries命令,这个命令表示:关联目标库和其他库。

find_library(...)# Links your native library against one or more other native libraries.target_link_libraries( # Specifies the target library.                       native-lib                       # Links the log library to the target library.                       ${log-lib} )

如图这样设置后,native-lib库中就可以调用log库的函数了。
其实在我们创建支持C/C++的新项目时,系统就自动的创建了CMakeLists.txt文件,里面有默认的定位 Android 特定的日志支持库

添加其他的预构建库

刚刚说了是添加系统的预构建库,使用了find_library命令,那添加其他的非系统的预构建库,还是使用find_library 么?不是的了,是使用add_library。咦?之前我们指定要构建的库就是用这个命令啊,现在添加其他的预构建库也用这个命令哇~~确实使用这个命令,不过呢,还是有区别的。在使用add_libraray 添加其他的预构建库时需要,用***IMPORTED***这个作为标志。格式如下:

add_library( imported-lib             SHARED             IMPORTED )             

然后,我们需要使用 set_target_properties() 命令指定库的路径,如下所示。
某些库为特定的 CPU 架构提供了单独的软件包,并将其组织到单独的目录中。此方法既有助于库充分利用特定的 CPU 架构,又能让你仅使用所需的库版本。要向 CMake 构建脚本中添加库的多个 ABI 版本,而不必为库的每个版本编写多个命令,你可以使用 ANDROID_ABI 路径变量。此变量使用 NDK 支持的一组默认 ABI,或者你手动配置 Gradle 而让其使用的一组经过筛选的 ABI。例如:

add_library(...)set_target_properties( # Specifies the target library.                       imported-lib                       # Specifies the parameter you want to define.                       PROPERTIES IMPORTED_LOCATION                       # Provides the path to the library you want to import.                       imported-lib/src/${ANDROID_ABI}/libimported-lib.so )

为了确保 CMake 可以在编译时定位您的标头文件,您需要使用 include_directories() 命令,并包含标头文件的路径:

include_directories( imported-lib/include/ )
常用的一些构建命令就介绍到这,有其他的需求,大家可以看官方CMake命令文档cmake命令文档

将Gradle关联到原生仓库的第二种方式

第二步说完,我们现在看第三步,之前的博文中介绍了,gradle关联原生仓库的第一种方式。是通过as的快捷键来实现的,右键点击你想要关联到原生库的模块(例如 app 模块),
并从菜单中选择 Link C++ Project with Gradle。
BuildSystem选择CMake,projectpath就是CMakeLists.txt文件的路径。点击ok完成。 如下图:

这样呢,就会在应用模块下的build.gradle文件中,android闭包下出现:

externalNativeBuild {        cmake {            path 'CMakeLists.txt'        }    }

这样的语块。
那我们的第二种方式就是手动的来修改build.gradle文件夹,来实现关联的目的。时光倒退到向现有的项目里添加原生代码的步骤 三大步 中的第二步。我们在第二步完成之后,不通过as 的快捷键,我们直接在build.gradle的文件写入

externalNativeBuild {        cmake {            path 'CMakeLists.txt'        }    }

也是可以的。。。当然,可以是可以,我们这里肯定不止这个。我们刚刚有到上面出现代码是在android闭包内的。事实上呢,在build.gradle文件的defaultConfig块中也可以设置externalNativeBuild {}块,为 CMake 指定可选参数和标志。先上代码:

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

这个代码是我从官网山得到sample,我们看到defaultConfig闭包内是存在了externalNativeBuild {},并且配置了一些属性。arguments “-DANDROID_ARM_NEON=TRUE”, “-DANDROID_TOOLCHAIN=clang”

"-DANDROID_ARM_NEON=TRUE"表示:是否让CMake构建原生库时支持“NEON”,默认的是不支持。  DANDROID_TOOLCHAIN=clang" 这个参数不知道大家还不记得这个图  

   这是当时创建支持原生代码的新项目时,我们见到界面,C++ Standard这个复选框,我们选择     Toolchain Default选项。这与DANDROID_TOOLCHAIN=clang意思一样,支持CMake构建原生库的意思。

cFlags “-D_EXAMPLE_C_FLAG1”, “-D_EXAMPLE_C_FLAG2”
cppFlags “-D__STDC_FORMAT_MACROS”
这两个配置,虽说能根据英文翻译出个大概,但是有点不确定含义,没用过。从网上也没搜到满意的回答。如果知道的大佬,可以说明一下,(__) 嘻嘻……


接着看上面的代码,我们发现externalNativeBuild {}块,不仅仅出现在defaultConfig闭包内,也出现在了,productFlavor块中。这是什么情况!!??仔细想想,其实,也好理解,productFlavor闭包中其他的渠道之前都是可以重写defaultConfig内的属性的。所以他自然也可以了区分各个渠道,重写externalNativeBuild {}内的内容哇。这样,每个渠道的包就有他自己的属性配置。多和谐~~
上面的代码中我们发现了,targets属性,这个是面对这种情况的。如果你的 CMake 或 ndk-build 项目定义多个原生库,你可以使用 targets 属性仅为给定渠道构建和打包这些库中的一部分。

好了,补充内容补充的差不多了,在国庆放假前一天静下心来补充这个,真是难熬/(ㄒoㄒ)/~~。。
最后再补充一个,之前博文在最后展示打包进入apk的so文件的时候,给出了下面的一张图:

我们看到了x86,armeabi、armeabi-v7a,mips只有这四个ABI。你们跑的时候可能出现了:

7个ABI,看一些size,apk大小的45.9%。多么可怕,这是不允许的。而且也不需要适配这么多的ABI。所以我们需要指定ABI。如何做呢?在build.gradle文件的defaultConfig闭包下加入如下语句即可:

ndk {           abiFilters 'x86', 'x86_64', 'armeabi', 'armeabi-v7a',                       }

上诉语句就表明会打出对应与’x86’, ‘x86_64’, ‘armeabi’, ‘armeabi-v7a’,这四个ABI的库。

好了,补充篇到此结束,安心过节啦~

最后列出与此篇博文对应的上篇博文地址:
使用CMake来进行Android NDK 开发
PalmRead


扫码加入我的个人微信公众号:Android开发圈 ,一起学习Android知识!!

更多相关文章

  1. Android(安卓)Rom分区 与 SD卡读写
  2. Android(安卓)画图 擦除开发
  3. android在framework层增加自己的service仿照GPS
  4. Android(安卓)Monkey测试入门-2-ADB安装和卸载命令
  5. 构建Android平台Google Map应用!
  6. Android(安卓)WiFi 调试之爬坑
  7. 图解Android应用程序构建原理
  8. Android多版本构建
  9. android代码执行adb shell终端命令(linux命令)并返回执行结果

随机推荐

  1. Android倒计时
  2. Android 访问权限许可大全
  3. Android UI开发第二十六篇——Fragment间
  4. Android 源码阅读之SMS
  5. Android积木之LayoutParams使用
  6. Android打开WIFI或者移动网络的代码实现
  7. Android 中文字符转UTF-8编码
  8. Android InputMethodManager 导致的内存
  9. android 读取网络 xml 数据
  10. android - mvp实现商品详情页面【仿】京