使用CMake构建工具进行NDK开发

Android推荐使用的NDK构建工具,从AS 2.2版本之后开始支持(包含2.2版本)

相关环境

  • 操作系统mac
  • Android Studio 4.0

环境搭建

在SDK Tools中安装NDK开发环境(Tools > SDK Manager > Appearance & Behavior > System Settings > Android SDK > SDK Tools)

image

选择NDK,CMake进行安装。

快捷工具配置

生成头文件快捷工具配制-javah-jni

Tools > External Tools选项,点击【+】按钮添加生成jni头文件以及ndk-build命令的快捷工具:

image
image
  • Name:javah-jni
    工具名称
  • Program:$JDKPath$/bin/javah
    javah所在的路径,$JDKPath$代表在环境变量中配置的JDK路径。
  • Parameters:-jni -encoding UTF-8 -d $ProjectFileDir$/app/src/main/cpp/include $FileClass$
    命令参数:

    -jni代表生成JNI样式的标头文件,文件名为当前包名+类名($FileClass$)
    
    -encoding代表编码格式为UTF-8
    
    -d代表指定头文件的输出路径为jni目录($ProjectFileDir$/app/src/main/cpp/include )
    
  • Working directory:$SourcepathEntry$

工作目录:$SourcepathEntry$为当前module的路径
javah用法: 
  javah [options] 
其中, [options] 包括:
  -o                 输出文件 (只能使用 -d 或 -o 之一)
  -d                  输出目录
  -v  -verbose             启用详细输出
  -h  --help  -?           输出此消息
  -version                 输出版本信息
  -jni                     生成 JNI 样式的标头文件 (默认值)
  -force                   始终写入输出文件
  -classpath         从中加载类的路径
  -cp                从中加载类的路径
  -bootclasspath     从中加载引导类的路径
 是使用其全限定名称指定的
(例如, java.lang.Object)。

NDK开发

这里以普通项目来进行编写(当然我们也可以采用Android Studio 自带创建C++项目来实现)。

创建 JniTest.java文件

package com.iblogstreet.myapplication;

/**
 * @author junwang
 * @date 2020/12/17 3:20 PM
 */
public class JniTest {
    public native String java2C();
    static {
        System.loadLibrary("native-lib");
    }
}

首先加载native-lib库,其中定义java2C方法。

生成头文件

选中JniTest文件,右键,选择External Tools > javah-jni,生成头文件com_iblogstreet_myapplication_JniTest.h

/* DO NOT EDIT THIS FILE - it is machine generated */
#include 
/* Header for class com_iblogstreet_myapplication_JniTest */

#ifndef _Included_com_iblogstreet_myapplication_JniTest
#define _Included_com_iblogstreet_myapplication_JniTest
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_iblogstreet_myapplication_JniTest
 * Method:    java2C
 * Signature: ()Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_com_iblogstreet_myapplication_JniTest_java2C
  (JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif

通过javah 命令生成头文件

"/Applications/Android Studio 2.app/Contents/jre/jdk/Contents/Home/bin/javah" -jni -encoding UTF-8 -d /Users/junwang/androidporject/MyApplication4/app/src/main/cpp/include 
 com.iblogstreet.myapplication.JniTest
新建cpp类

在cpp目录中新建cpp类native-lib.cpp

#include 
#include 
#include "include/com_iblogstreet_myapplication_JniTest.h"

extern "C" JNIEXPORT jstring JNICALL
Java_com_iblogstreet_myapplication_JniTest_java2C(
        JNIEnv* env,
        jobject /* this */) {
    std::string hello = "Hello from C++";
    return env->NewStringUTF(hello.c_str());
}

接着在cpp目录下新建CMakeLists.txt配置文件。

新建CMakeLists.txt
# For more information about using CMake with Android Studio, read the
# documentation: https://d.android.com/studio/projects/add-native-code.html

# Sets the minimum version of CMake required to build the native library.

cmake_minimum_required(VERSION 3.4.1)

# Creates and names a library, sets it as either STATIC
# or SHARED, and provides the relative paths to its source code.
# You can define multiple libraries, and CMake builds them for you.
# Gradle automatically packages shared libraries with your APK.

add_library( # Sets the name of the library.
             native-lib

             # Sets the library as a shared library.
             SHARED

             # Provides a relative path to your source file(s).
             native-lib.cpp )

# Searches for a specified prebuilt library and stores the path as a
# variable. Because CMake includes system libraries 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 )

# Specifies libraries CMake should link to your target library. You
# can link multiple libraries, such as libraries you define in this
# build script, prebuilt third-party libraries, or system libraries.

target_link_libraries( # Specifies the target library.
                       native-lib

                       # Links the target library to the log library
                       # included in the NDK.
                       ${log-lib} )
gradle关联CMakeLists.txt
android {
   ...

    defaultConfig {
       ...
        externalNativeBuild {
            cmake {
                cppFlags "-std=c++11"
            }
        }
    }

   ...
    externalNativeBuild {
        cmake {
            path "src/main/cpp/CMakeLists.txt"
            version "3.10.2"
        }
    }
}
生成so文件

重新编译,在app > build > intermediates > cmake > debug > obj目录下会生成不同CPU架构对应的so文件。

image

CMakeLists.txt 相关命令解析

cmake_minimum_required

指定需要CMAKE的最小版本

cmake_minimum_required(VERSION 3.4.1)
add_library

添加 源文件或库,可以出现多次。

add_library( # Sets the name of the library.
             native-lib

             # Sets the library as a shared library.
             SHARED

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

指定 原生代码 或 so库 的头文件路径。

# Specifies a path to native header files.
include_directories(src/main/cpp/include/)
find_library and target_link_libraries

添加 NDK API,向 CMake 构建脚本添加 find_library() 命令以找到 NDK 库并将其路径存储为一个变量。

可以使用此变量在构建脚本的其他部分引用 NDK 库。以下示例会找到 Android 专有的日志支持库,并将其路径存储在 log-lib 中。

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 )

为了让原生库能够调用 log 库中的函数,需要使用 CMake 构建脚本中的 target_link_libraries() 命令来关联这些库

# 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} )

相关参考

android 官方
Android NDK开发(一) 使用CMake构建工具进行NDK开发
Android NDK开发(二) 使用ndk-build构建工具进行NDK开发
CMAKE手册-中文版
CMake Tutorial

你可能感兴趣的:(使用CMake构建工具进行NDK开发)