CMake

Customize C++ Support的两个选择

  • Exceptions Support:启用C++异常处理的支持。
  • Runtime Type Information Support(RTTI):运行时类型识别。能够给通过基类的指针或者引用来检索其所指对象的实际类型。
android {
    externalNativeBuild {
            cmake {
                cppFlags "-frtti -fexceptions"
            }
        }
}

创建C模块

创建C代码源文件

创建CMmake脚本文件

如果您的原生源文件还没有CMake构建脚本,则您需要自行创建一个并包含适当的CMake命令。CMake构建脚本是一个纯文本文件,您必须将其命名为CMakeLists.txt。

在CMakeLists文件中添加CMake命令,具体为:

cmake_minimum_required

设置最小需要的CMake的版本。低于最小版本的就会报错。

cmake_minimum_required(VERSION major.minor[.patch[.tweak]][FATAL_ERROR])

// 实例
cmake_minimum_required(VERSION 3.4.1)
add_library

添加名称为<name>的目标库,目标库是由source1 [source2 ...]生成的。

add_library(<name> [STATIC | SHARED | MODULE]
            [EXCLUDE_FROM_ALL]
            source1 [source2 ...])

// 实例
add_library( # Sets the name of the library.
             guard-lib

             # Sets the library as a shared library.
             SHARED

             # Provides a relative path to your source file(s).
              guard-lib.c
              my.cpp
             )
include_directories

它是和add_library配合使用的,告知编译器,编译时使用的源文件的文件路径。这样的作用是确保了CMake可以在编译时定位到.h文件。(当然,如果不加这个字段,可以直接在add_library里明确地指定)

include_directories([AFTER|BEFORE] [SYSTEM] dir1 [dir2 ...])
添加原生库

Android NDK本身已经提供了一套原生的API和库,开发者可以直接去使用。

预构建的NDK库是已经存在于Android平台上的,因此无需再构建或者打包到APK中【因此,添加原生库的依赖不会加到APK包的大小】。

同时,NDK预构建库已经是CMake搜索路径的一部分,因此在使用的时候都不需要指定原生库的位置,只需要库的名称即可,并关联到自己库上。

find_library

该命令实现添加到您的CMake构建脚本中以定位NDK库,并将其路径存储为一个变量。您可以使用此变量在构建脚本的其他部分引用NDK库。

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_PACKAGE_ROOT_PATH]
          [NO_CMAKE_PATH]
          [NO_CMAKE_ENVIRONMENT_PATH]
          [NO_SYSTEM_ENVIRONMENT_PATH]
          [NO_CMAKE_SYSTEM_PATH]
          [CMAKE_FIND_ROOT_PATH_BOTH |
           ONLY_CMAKE_FIND_ROOT_PATH |
           NO_CMAKE_FIND_ROOT_PATH]
         )

// 实例
find_library( # Defines the name of the path variable that stores the
              # location of the NDK library.
              log-lib

              # Specifies the name of the NDK library that
              # CMake needs to locate.
              log )
target_link_libraries

它的作用是为了确保自己的原生库可以调用到预构建的原生库,如果不产生关联,则无法调用。

其中,<target>必须是通过add_library()或者add_executable()创建的库。

<item>一般就是预构建的原生库。

target_link_libraries(<target> ... <item>... ...)

// 实例
target_link_libraries( # Specifies the target library.
                       native-lib

                       # Links the log library to the target library.
                       ${log-lib} )
直接源码的构建android预设的原生库

NDK 还以源代码的形式包含一些库,您在构建和关联到您的原生库时需要使用这些代码。您可以使用 CMake 构建脚本中的 add_library() 命令,将源代码编译到原生库中。要提供本地 NDK 库的路径,您可以使用 ANDROID_NDK 路径变量,Android Studio 会自动为您定义此变量。

例如:

add_library( app-glue
             STATIC
             ${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} )
使用其他的(非android预设)的原生库

添加预构建库与为 CMake 指定要构建的另一个原生库类似。不过,由于库已经预先构建,您需要使用 IMPORTED 标志告知 CMake 您只希望将库导入到项目中:

add_library( imported-lib
             SHARED
             IMPORTED )

set_target_properties()来指定引用库的一些相关的数据。

set_target_properties(target1 target2 ...
                      PROPERTIES prop1 value1
                      prop2 value2 ...)

// 实例
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 构建脚本的target_link_libraries()命令中:

target_link_libraries( native-lib imported-lib app-glue ${log-lib} )

将Gradle关联到自己的原生库

将Gradle关联到自己的原生库,主要是依赖CMake脚本。

可以通过以下几种方式进行关联:

使用 Android Studio UI

手动配置

建立关联

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

指定特定的配置:

可以在模块级 build.gradle 文件的 defaultConfig {} 块中配置另一个 externalNativeBuild {} 块,为 CMake 或 ndk-build 指定可选参数和标志。与 defaultConfig {} 块中的其他属性类似,您也可以在构建配置中为每个产品风味flavor重写这些属性。

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

指定 ABI

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

补充

CMake参数配置: https://developer.android.com/ndk/guides/cmake.html#variables

results matching ""

    No results matching ""