android studio ndk编译的两种方式(ndk-build和cmake)配置

安卓默认用armeabi-v7a

1.ndk-build

动态加载JNI
1.java 层代码:

    static {
    
    
        System.loadLibrary("MyLibrary"); // libxxx.so库的  libMyLibrary.so
    }

2.jni C++
(1)在main目录下新建一个jni目录,里面的.cpp最终要生成.so 库,加载进apk里面

在这里插入代码片

(2) 创建Android.mk Application.mk文件 编译脚本

Android.mk

    #每个Android.mk文件必须以LOCAL_PATH开头,在整个开发中,它通常别用做定位资源文件,例如,功能宏my-dir提供给编译系统当前的路径。
    LOCAL_PATH := $(call my-dir)
    
    #CLEAR_VARS指编译系统提供一个特殊的GUN MakeFile来为你清除所有的LOCAL_XXX变量,LOCAL_PATH不会被清除。使用这个变量是因为在编译系统时,所有的控制文件都会在一个GUN Make上下文进行执行,而在此上下文中所有的LOCAL_XXX都是全局的。
    include $(CLEAR_VARS)
    
    #LOCAL_MODULE变量是为了确定模块名,并且必须要定义。这个名字必须是唯一的同时不能含有空格。会自动的为文件添加适当的前缀或后缀,模块名为“foo”它将会生成一个名为“libfoo.so”文件。
    LOCAL_MODULE := myjni
    
    #包含一系列被编译进模块的C 或C++资源文件
    LOCAL_SRC_FILES := JNI_C++.cpp
    
    #指明一个GUN Makefile脚本,并且收集从最近“include$(CLEAR_VARS)”下的所有LOCALL_XXX变量的信息,最后告诉编译系统如何正确的进行编译。将会生成一个静态库hello-jni.a文件或者动态库libhello-jni.so。
    include $(BUILD_SHARED_LIBRARY)

总结:
LOCAL_PATH即为调用命令的所在目录,你在哪个目录下使用cmd命令,这里就会返回它的路径地址
LOCAL_MODULE你生成的文件名称是什么,输出之后会自动在名称的前后加上lib和.so
LOCAL_SRC_FILES要对哪个文件进行编译

Application.mk
可没有,主要指定so调用库名以及编译的so对应CPU平台
若没有,则可在build.gradle中设置,此时使用系统进行编译,而非使用ndk-build

    APP_MODULES := MyJni
    APP_ABI := all all代表全平台

3.编译方式选择:
在app module目录下的build.gradle中设置库文件名(生成的so文件名)。找到gradle文件的defaultConfig这项,在里面添加如下内容:

//第一种是将c++ 文件生成.so 库
defaultConfig {
    
     
    ...... 
    //1.指定生成模块名,架构
    ndk{
    
     
        moduleName "JniLibName"  //生成的so名字
        ldLibs "log", "z", "m"  //添加依赖库文件,如果有log打印等 
        abiFilters "armeabi", "armeabi-v7a", "x86" //输出指定cpu体系结构下的so库。 
    } 
}
//2.指定编译Android.mk目录
externalNativeBuild {
    
      
          ndkBuild {
    
     path file("src/main/java/jni/Android.mk") 
    } 
}
//3.指定jni代码目录
sourceSets {
    
          
    main {
    
    
        jni.srcDirs('src/main/java/jni')
    }
}
此种生成的so文件在app/build/intermediates/ndkBuild/debug下



//第二种是 指定将已经有的.so 编译进apk里面
    sourceSets {
    
    
        main {
    
    
            jniLibs.srcDirs('.\\libs')        
            这种是指定.so 文件编译进apk里面,如果在main目录下已经有个JniLibs目录则不用指定,编译时自动会编译进去
        }
    }

2.Cmake方式(常用)

main/java 同级目录 jni jniLibs 这两个目录手动创建后,则在build.gradle中不用指定jni 代码目录和so库路径。
在这里插入图片描述

Cmake方式创建步骤:
1.在buidl.gradle里面设置cmake编译模式,设置编译架构,源码so库路径
2.同级目录创建CMakeLists.txt(需要在buidl.gradle里面指定)
3.jni目录里面创建在创建CMakeLists.txt,生成so库

(1)build.gradle

android {
    
    
    defaultConfig {
    
    
....
        externalNativeBuild {
    
    
            cmake {
    
    
                cppFlags ""
            }
        }
        ndk {
    
     //设置打包时只编译so库armeabi-v7a
           moduleName "MyLibrary"
           abiFilters  'armeabi-v7a', 'arm64-v8a' ,'x86', 'x86_64'  
        }
    }
  externalNativeBuild {
    
     //设置cmake编译脚本
        cmake {
    
    
            path "CMakeLists.txt"
        }
    }
    sourceSets {
    
     //注意如果自己在src/java创建了 jni jniLibs则不用指定,根据需要自己设定
        main {
    
    
            manifest.srcFile 'src/main/AndroidManifest.xml'
            java.srcDirs = ['src/main/java', 'src/main/aidl']
            resources.srcDirs = ['src/main/java', 'src/main/aidl']
            aidl.srcDirs = ['src/main/aidl']
            res.srcDirs = ['src/main/res']
            assets.srcDirs = ['src/main/assets']
            jni.srcDirs = ['src/main/jni', 'src/main/native']
            jniLibs.srcDirs 'src/main/jniLibs'
        }
    }

}

(2) 跟build同级目录创建CMakeLists.txt

cmake_minimum_required(VERSION 3.4.1)
#添加子目录, 调用子目录中的CMakeLists.txt
set(JNI_PATH ${
    
    CMAKE_CURRENT_SOURCE_DIR}/src/main/jni)
add_subdirectory(${
    
    JNI_PATH})

(3)在src/main jni 里面创建CMakeLists.txt生成so库

cmake_minimum_required(VERSION 3.4.1)
。。。。

猜你喜欢

转载自blog.csdn.net/weixin_41477306/article/details/107800170