android基于cmakelist构建so库及使用

关键点

构建及使用so文件,主要包括以下三点

  1. abifilter
  2. cmakelist
  3. build.gradle

目标

  1. 在一个工程中构建单独的so库
  2. 在另外一个工程中c++能够正常调用

构建so

此步骤主要是构建出单独的so文件,供其他工程使用

  1. 新建android native c++工程,自带了jni,cmakelist等,省的自己添加了;
  2. 修改build.gradle选项,主要是修改c++编译选项及abifilter;
  3. 添加源文件及头头文件(功能实现);
  4. 修改cmakelist.txt(控制编译及生成);

下面详细介绍下,步骤2及4;
首先需要修改build.gradle,主要是添加编译选项,及abiFilters,以及相关路径设置,参考文件注释

apply plugin: 'com.android.application'

android {
    compileSdkVersion 29
    buildToolsVersion "29.0.1"
    defaultConfig {
    // 省略...
        externalNativeBuild {
            cmake {
                cppFlags "-std=c++17"
                abiFilters "x86_64","x86" // 控制编译出哪些abi文件,使用者需要和提供者保持一致
            }
        }
    }
    buildTypes {
        release {
    		// 省略...
        }
    }
    externalNativeBuild {
        cmake {
            path "src/main/cpp/CMakeLists.txt" //cmakelist文件路径
            version "3.10.2"
        }
    }
}
    // 省略...

源文件及头文件创建省略,本次测试源端目录结构如下

CMakeLists android so 生成目标 安卓cmakelist_so

cmakelist设置

cmake_minimum_required(VERSION 3.4.1)
# 源工程相关构建脚本未修改
add_library( # Sets the name of the library.
        native-lib
        SHARED
        native-lib.cpp)

# 新增构建脚本,${CMAKE_SOURCE_DIR}是一个cmake变量,其路径是cmakelist.txt所在路径
include_directories(${CMAKE_SOURCE_DIR})
add_library( # Sets the name of the library.
        ShraredLibTest # 新增模块名称
        SHARED        # 模式,static/shared
        SharedLibTest.cpp)  #源文件路径
# 查找系统库log,并将其路径赋值给log-lib
find_library( # Sets the name of the path variable.
        log-lib
        log)
#项目自带的库
target_link_libraries( # Specifies the target library.
        native-lib
        ${log-lib})
# 我们要构建的库,注意依赖
target_link_libraries( # Specifies the target library.
        ShraredLibTest
        ${log-lib})

到此,构建so的相关工作已经完成,一切正常的话,make后会在类似如下路径LibTest\app\build\intermediates\transforms\mergeJniLibs\debug\0\lib\x86中生成两个库,一个libnative-lib.so(项目自带的,我们不用);另外一个是libShraredLibTest.so,我们目标so
注意路径中x86和abifilters有关,通常情况下设置了几个,会有几个类似目录,生成针对不同平台的so,此次使用模拟器,故构建了x86。

使用so

主要包括以下步骤

  1. 拷贝文件(so及头文件)
  2. 修改build.gradle
  3. 修改代码
  4. 修改cmakelist.txt

拷贝文件

拷贝文件需要注意路径,so文件的路径,在gradle中会用到,以便把该so编译的时候打包进apk,cmakelist也会用到;头文件的路径cmakelist也会用到

结构如下,工程构建方法同上,native c++的工程,相关jni,cmakelist文件已经自动生成,本次在natvie-lib.cpp中直接调用上面的so中的方法,无需增加新的jni接口

CMakeLists android so 生成目标 安卓cmakelist_android_02


修改build.gradle

见文件注释

apply plugin: 'com.android.application'

android {
//...
            cmake {
                cppFlags "-std=c++17"
                abiFilters "x86_64","x86" // 控制编译出哪些abi文件,使用者需要和提供者保持一致
            }
        }
    }
//...
//设置libs文件路径,如果放置的是其他路径,需要修改成对应的相对路径
    sourceSets {
        main {
            jniLibs.srcDirs = ['libs']
        }
    }
}

cmakelist修改
见注释

cmake_minimum_required(VERSION 3.4.1)
# 定义一个变量,表示根路径
set(ROOT_DIR ${CMAKE_SOURCE_DIR}/../../../../)
# 项目自带文件,native-lib.cpp中会调用我们的so
add_library( # Sets the name of the library.
        native-lib
        SHARED
        native-lib.cpp)
// 设置头文件路径,根据头文件放置位置修改
include_directories(${CMAKE_SOURCE_DIR})
// 引入so库,注意方式是IMPORTED
add_library( # Sets the name of the library.
        ShraredLibTest
        SHARED
        IMPORTED)
// 设置so库文件的路径
set_target_properties(ShraredLibTest
        PROPERTIES IMPORTED_LOCATION
        ${ROOT_DIR}/app/libs/${ANDROID_ABI}/libShraredLibTest.so
        )

find_library( # Sets the name of the path variable.
        log-lib
        log)
// 修改链接依赖
target_link_libraries( # Specifies the target library.
        native-lib
        ShraredLibTest
        ${log-lib})

基本上就是这么个步骤,可以参考修改

运行效果如下

CMakeLists android so 生成目标 安卓cmakelist_so_03

环境
NDK 20
Cmake 3.10
Android studio 3.4