美文网首页
使用CMake构建工具进行NDK开发

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

作者: gooddaytoyou | 来源:发表于2020-12-18 11:31 被阅读0次

    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] <classes>
    其中, [options] 包括:
      -o <file>                输出文件 (只能使用 -d 或 -o 之一)
      -d <dir>                 输出目录
      -v  -verbose             启用详细输出
      -h  --help  -?           输出此消息
      -version                 输出版本信息
      -jni                     生成 JNI 样式的标头文件 (默认值)
      -force                   始终写入输出文件
      -classpath <path>        从中加载类的路径
      -cp <path>               从中加载类的路径
      -bootclasspath <path>    从中加载引导类的路径
    <classes> 是使用其全限定名称指定的
    (例如, 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 <jni.h>
    /* 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 <jni.h>
    #include <string>
    #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开发

          本文链接:https://www.haomeiwen.com/subject/wlyxnktx.html