在我们NDK开发中,可能会遇到需要通过cmake生成一个可执行程序,在app运行的过程中,调用该可执行程序用于做一些底层操作,尽管我们做的更多的可能是通过java直接调用JNI接口的方式来调用底层c/c++接口
开发环境
操作系统:macOS 10.14.3
ndk版本:android-ndk-r19
示例
这里以opengl es来作为参考示例,编写一个可以在android平台用于测试音频的可执行程序
build.gradle
首先我们需要在build.gradle文件中,与编译动态库或者静态库类似的做法,指定abiFilters与path参数,其中abiFilters指定编译的目标平台,path指定cmake文件路径,参考代码如下:
android {
compileSdkVersion 27
defaultConfig {
applicationId "com.eggsy.opensles"
minSdkVersion 16
targetSdkVersion 27
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
externalNativeBuild {
cmake {
cppFlags ""
abiFilters 'armeabi-v7a', 'arm64-v8a' , 'x86', 'x86_64'
}
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
externalNativeBuild {
cmake {
path "CMakeLists.txt"
}
}
}
可能会有人有疑问,为什么abiFilters中armeabi、mips、mips64等平台呢,因为当前ndk版本是r19,从NDK r17版本开始,已经去掉了armeabi、mips、mips64的ABI支持,所以我们不需要在abiFilters中使用以上配置。
CMakeLists.txt
上面我们定义了abiFilter,并指定了cmake文件的文件名,下面我们看下CMakeLists.txt是怎么写的
# 指定当前cmake支持的最低版本
cmake_minimum_required(VERSION 3.4.1)
# 指定输出的目录结构,这里我们指定到当前CMakeLists.txt同级目录的/src/main/assets/目录下,
# 根据abiFilter中指定的编译平台在细分子目录
set(EXECUTABLE_OUTPUT_PATH "${CMAKE_CURRENT_SOURCE_DIR}/src/main/assets/${ANDROID_ABI}")
# 指定编译的目标可执行程序名称与编译的文件,其中testopensl是输出的可执行程序名称,src/main/cpp/opensltest.cpp是
# 编译到可执行程序中的文件,可指定多个
add_executable(testopensl src/main/cpp/opensltest.cpp)
# 添加目标编译目录
#target_include_directories (testopensl PUBLIC ${CMAKE_CURRENT_SOURCE_DIR})
# 从ANDROID_NDK变量表示的目录下,找到SLES/OpenSLES.h路径,存储在SL_INCLUDE_DIR变量中备用
find_path(SL_INCLUDE_DIR SLES/OpenSLES.h
HINTS ${ANDROID_NDK})
# 从上面find_path中找到的S