Android 开发之Studio NDK 构建工具 CMake介绍
白羽 2018-06-15 来源 :网络 阅读 1268 评论 0

摘要:本文将带你了解Android 开发之Studio NDK 构建工具 CMake介绍 ,希望本文对大家学Android有所帮助。




CMakeLists.txt文件说明

CMakeLists.txt就是编译so库的脚本文件,类似于原来的Android.mk,Application.mk。

设置CMake插件的版本


   

<code># Sets the minimum version of CMake required to build your native library.
# This ensures that a certain set of CMake features is available to
# your build.
 
cmake_minimum_required(VERSION 3.4.1)</code>
   
定义要编译的源代码和最终要生成的库文件名称及类型
   
<code># Specifies a library name, specifies whether the library is STATIC or
# SHARED, and provides relative paths to the source code. You can
# define multiple libraries by adding multiple add.library() commands,
# and CMake builds them for you. When you build your app, Gradle
# automatically packages shared libraries with your APK.
 
#语法,参考:https://cmake.org/cmake/help/latest/command/add_library.html
add_library(<name> [STATIC | SHARED | MODULE]
            [EXCLUDE_FROM_ALL]
            source1 [source2 ...])
# 语法#########################################
 
# 示例
add_library(
             #编译生成的库的名称,注意最终生成时会在前面加`lib`.
             # Specifies the name of the library.
             native-lib
 
             # Sets the library as a shared library.
             # 生成的库的类型,有SHARED,STATIC,MODULE
             SHARED
 
             # Provides a relative path to your source file(s).
             # 要编译的源代码文件
             src/main/cpp/native-lib.cpp )</name></code>
   
源码头文件">包含要编译的源码头文件
如果有源码文件有头文件,自然需要包含:
   
<code># 语法, 参考:https://cmake.org/cmake/help/latest/command/include_directories.html
include_directories([AFTER|BEFORE] [SYSTEM] dir1 [dir2 ...])
# 语法#########################################
 
 
# Specifies a path to native header files.
# 注意这里指定的是头文件的目录
include_directories(src/main/cpp/include/)</code>
   
使用NDK中的Api
有时候我们发现需要使用到NDK中定义的Api,因为NDK中的API都已经是编译好的,而且CMake会自动去NDK目录中查找这些我们需要使用的库,所以这里只需要提供库的名称就可以了,一下举例加载NDK中的log库,因为我们在NDK开发中,总是少不了要打印日志的。- 首先查找要使用的库,使用变量保存它的路径。
<code><code># 语法,参考:https://cmake.org/cmake/help/latest/command/find_library.html
# A short-hand signature is:
# name1 保存库路径的变量
find_library (<var> name1 [path1 path2 ...])
# The general signature is:
 
find_library (
          <var>
          name | NAMES name1 [name2 ...] [NAMES_PER_DIR]
          [HINTS path1 [path2 ... ENV var]]
          [PATHS path1 [path2 ... ENV var]]
          [PATH_SUFFIXES suffix1 [suffix2 ...]]
          [DOC "cache documentation string"]
          [NO_DEFAULT_PATH]
          [NO_CMAKE_ENVIRONMENT_PATH]
          [NO_CMAKE_PATH]
          [NO_SYSTEM_ENVIRONMENT_PATH]
          [NO_CMAKE_SYSTEM_PATH]
          [CMAKE_FIND_ROOT_PATH_BOTH |
           ONLY_CMAKE_FIND_ROOT_PATH |
           NO_CMAKE_FIND_ROOT_PATH]
         )
# 语法#########################################
 
# 示例  
# Searches for a specified prebuilt library and stores the path as a
# variable. Because system libraries are included in the search path by
# default, you only need to specify the name of the public NDK library
# you want to add. CMake verifies that the library exists before
# completing its build.
 
find_library( # Sets the name of the path variable.
              log-lib
 
              # Specifies the name of the NDK library that
              # you want CMake to locate.
              log )</var></var></code></code>
   
为了编译时可以使用,需要将上面一步找到的库链接到我们要编译的库中。
   
<code><code># 语法,参考: https://cmake.org/cmake/help/latest/command/target_link_libraries.html
target_link_libraries(<target> ... <item>... ...)
# 语法 end #######################
 
# Specifies libraries CMake should link to your target library. You
# can link multiple libraries, such as libraries you define in the
# build script, prebuilt third-party libraries, or system libraries.
# 注意这里可以同时链接多个库
target_link_libraries( # Specifies the target library.
                       native-lib
 
                       # Links the log library to the target library.
                       # 此处使用上面保存的变量
                       ${log-lib} )</item></target></code></code>
   
NDK中也有一些库是以源代码的方式存在的,这个时候如果我们要使用它,就需要把它编译到一个本地静态库中,再链接到我们要生成的库中。
   
<code><code># 这样就会在\app\.externalNativeBuild\cmake\debug\${ANDROID_ABI}\ 目录下生成libapp-glue.a/静态库
add_library( app-glue
             # 以静态的方式添加
             STATIC
             # 该源码用于管理`NativeActivity`生命周期事件和触摸事件
             ${ANDROID_NDK}/sources/android/native_app_glue/android_native_app_glue.c )
 
# You need to link static libraries against your shared native library.
# 链接到库中
target_link_libraries( native-lib app-glue ${log-lib} )</code></code>
   
添加第三方的库
使用add_library添加第三库
   
<code><code><code># 语法,因为已经编译好了,所以使用`IMPORTED`关键字
add_library(<name> <shared|static|module|unknown> IMPORTED [GLOBAL])
 
# 示例
add_library( imported-lib
             SHARED
             IMPORTED )</shared|static|module|unknown></name></code></code></code>
   
当第三方库有针对不同架构编译了不同的库版本时,有时候我们只需要引入我们想要的版本的库,当我们想要引入多个版本的库时,可以使用ANDROID_ABI变量,它表示默认的ABI架构和NDK支持的架构,如果我们在build.gradle中设置了过滤值,则表示过滤后的架构集合。
   
<code><code><code><code><code>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是在项目的app目录下的
                       imported-lib/src/${ANDROID_ABI}/libimported-lib.so )</code></code></code></code></code>
   
同时为了在编译时的使用,我们需要导入所依赖的库的头文件
?
1
   
<code><code><code><code><code>include_directories( imported-lib/include/ )</code></code></code></code></code>
   
添加链接,以便在编译的时候使用,注意如果要添加的第三方库在编译我们要产出的库时不需要直接用到(比如一个库是imported-lib所依赖的),则不需要执行以下步骤。
?
1
   
<code><code><code><code><code><code>target_link_libraries( native-lib imported-lib app-glue ${log-lib} )</code></code></code></code></code></code>
   
在build.gradle中配置编译库的脚本
   
<code><code><code><code><code><code><code>android {
    ......
 
    defaultConfig {
        ......
        //在默认配置中配置 cmake 的一些参数
        externalNativeBuild {
            cmake {
                arguments "-DANDROID_TOOLCHAIN=clang"
                cFlags  ""
                cppFlags ""
            }
        }
 
        //ndk 配置
        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'
        }
    }
 
    //配置库编译的脚本
    externalNativeBuild {
        cmake {
            path "CMakeLists.txt"
        }
    }
 
 
    //定义不同的产品类型(多渠道打包),通过复写externalNativeBuild,使用target字段实现打包不同的so库。
    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"
        }
      }
    }
  }
 
}</code></code></code></code></code></code></code>
   
cFlags和cppFlags,c/c++编译标记。
错误收集
cmake要求的NDK版本与当前指定不一致
   
<code><code><code><code><code><code><code><code><code><code>External Native Build Issues
Build command failed.
Error while executing 'C:\Users\Administrator\AppData\Local\Android\Sdk\cmake\3.6.3155560\bin\cmake.exe' with arguments {-HE:\Source\GitHub\JniTestDemo\app -BE:\Source\GitHub\JniTestDemo\app\.externalNativeBuild\cmake\release\armeabi-v7a -GAndroid Gradle - Ninja -DANDROID_ABI=armeabi-v7a -DANDROID_NDK=C:\Users\Administrator\AppData\Local\Android\Sdk\ndk-bundle -DCMAKE_LIBRARY_OUTPUT_DIRECTORY=E:\Source\GitHub\JniTestDemo\app\.externalNativeBuild\cmake\release\obj\armeabi-v7a -DCMAKE_BUILD_TYPE=Release -DCMAKE_MAKE_PROGRAM=C:\Users\Administrator\AppData\Local\Android\Sdk\cmake\3.6.3155560\bin\ninja.exe -DCMAKE_TOOLCHAIN_FILE=C:\Users\Administrator\AppData\Local\Android\Sdk\ndk-bundle\build\cmake\android.toolchain.cmake -DANDROID_NATIVE_API_LEVEL=15 -DCMAKE_CXX_FLAGS=-std=c++11 -D__cplusplus=201103L -fvisibility=hidden}
-- Configuring incomplete, errors occurred!
See also "E:/Source/GitHub/JniTestDemo/app/.externalNativeBuild/cmake/release/armeabi-v7a/CMakeFiles/CMakeOutput.log".
CMake Error at C:/Users/Administrator/AppData/Local/Android/sdk/cmake/3.6.3155560/android.toolchain.cmake:356 (message):
  Invalid Android NDK revision (should be 12): 13.1.3345770.
Call Stack (most recent call first):
  .externalNativeBuild/cmake/release/armeabi-v7a/CMakeFiles/3.6.0-rc2/CMakeSystem.cmake:6 (include)
  CMakeLists.txt
CMake Error: CMAKE_C_COMPILER not set, after EnableLanguage
CMake Error: CMAKE_CXX_COMPILER not set, after EnableLanguage
Error:executing external native build for cmake E:\Source\GitHub\JniTestDemo\app\CMakeLists.txt
Build command failed.
Error while executing 'C:\Users\Administrator\AppData\Local\Android\Sdk\cmake\3.6.3155560\bin\cmake.exe' with arguments {-HE:\Source\GitHub\JniTestDemo\app -BE:\Source\GitHub\JniTestDemo\app\.externalNativeBuild\cmake\debug\armeabi-v7a -GAndroid Gradle - Ninja -DANDROID_ABI=armeabi-v7a -DANDROID_NDK=C:\Users\Administrator\AppData\Local\Android\Sdk\ndk-bundle -DCMAKE_LIBRARY_OUTPUT_DIRECTORY=E:\Source\GitHub\JniTestDemo\app\.externalNativeBuild\cmake\debug\obj\armeabi-v7a -DCMAKE_BUILD_TYPE=Debug -DCMAKE_MAKE_PROGRAM=C:\Users\Administrator\AppData\Local\Android\Sdk\cmake\3.6.3155560\bin\ninja.exe -DCMAKE_TOOLCHAIN_FILE=C:\Users\Administrator\AppData\Local\Android\Sdk\ndk-bundle\build\cmake\android.toolchain.cmake -DANDROID_NATIVE_API_LEVEL=15 -DCMAKE_CXX_FLAGS=-std=c++11 -D__cplusplus=201103L -fvisibility=hidden}
-- Configuring incomplete, errors occurred!
See also "E:/Source/GitHub/JniTestDemo/app/.externalNativeBuild/cmake/debug/armeabi-v7a/CMakeFiles/CMakeOutput.log".
CMake Error at C:/Users/Administrator/AppData/Local/Android/sdk/cmake/3.6.3155560/android.toolchain.cmake:356 (message):
  Invalid Android NDK revision (should be 12): 13.1.3345770.
Call Stack (most recent call first):
  .externalNativeBuild/cmake/debug/armeabi-v7a/CMakeFiles/3.6.0-rc2/CMakeSystem.cmake:6 (include)
  CMakeLists.txt
CMake Error: CMAKE_C_COMPILER not set, after EnableLanguage
CMake Error: CMAKE_CXX_COMPILER not set, after EnableLanguage
Error:executing external native build for cmake E:\Source\GitHub\JniTestDemo\app\CMakeLists.txt</code></code></code></code></code></code></code></code></code></code>
   
出现该问题的修复方案:
<code><code><code><code><code><code><code><code><code><code>1,将NDK的版本修改为需要的版本,这里修改为12
2,修改SDK目录/cmake/cmakeversion/android.toolchain.cmake文件,将NDK版本修改为所使用的版本:
cmake_minimum_required(VERSION 3.6.0)
 
set(ANDROID_NDK_REVISION 13)</code></code></code></code></code></code></code

   

 


本文由职坐标整理并发布,希望对同学们有所帮助。了解更多详情请关注职坐标移动开发之Android频道


本文由 @白羽 发布于职坐标。未经许可,禁止转载。
喜欢 | 0 不喜欢 | 0
看完这篇文章有何感觉?已经有0人表态,0%的人喜欢 快给朋友分享吧~
评论(0)
后参与评论

您输入的评论内容中包含违禁敏感词

我知道了

助您圆梦职场 匹配合适岗位
验证码手机号,获得海同独家IT培训资料
选择就业方向:
人工智能物联网
大数据开发/分析
人工智能Python
Java全栈开发
WEB前端+H5

请输入正确的手机号码

请输入正确的验证码

获取验证码

您今天的短信下发次数太多了,明天再试试吧!

提交

我们会在第一时间安排职业规划师联系您!

您也可以联系我们的职业规划师咨询:

小职老师的微信号:z_zhizuobiao
小职老师的微信号:z_zhizuobiao

版权所有 职坐标-一站式IT培训就业服务领导者 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
 沪公网安备 31011502005948号    

©2015 www.zhizuobiao.com All Rights Reserved

208小时内训课程