Android NDK r5开始支持预编译共享库,共享库分为静态.a与动态.so,相对与将源码提供给使用者这种方式更为便捷,而第三方使用者直接将so库放到项目对应目录下并加载使用即可。
本章节主要讲解下自己如何搭建并编译动态库的方式(内部依赖第三方动态共享库),说白了就是现在要用ndk自己编译so库,内部方法依赖其他库(预编译库),如果预编译库没有在mk文件中声明独立模块的话将编译不通过,因为内部方法找不到,也不知从哪儿找。
针对这一需求,我做了较详细的讲解,根据步骤操作就可以实现。
一:前提
Android Studio中NDK配置成功
NDK环境变量配置成功
JNI相关目录搭建成功 (可参照 Android Studio——JNI 初体验(二))
确保预编译共享库存在(需要保证共享库ABI的兼容性)
二:操作步骤
LOCAL_PATH:= $(call my-dir) //当前jni目录,位与第一行
include $(CLEAR_VARS) //清除全局变量,防止下次使用出错
LOCAL_MODULE := a //第三方动态库名称
LOCAL_SRC_FILES := $(TARGET_ARCH_ABI)/liba.so //$(TARGET_ARCH_ABI)根据abi类型查找对应的so库
include $(PREBUILT_SHARED_LIBRARY) //预构建动态库
include $(CLEAR_VARS)
LOCAL_MODULE := b
LOCAL_SRC_FILES := $(TARGET_ARCH_ABI)/libb.so
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := plugin
LOCAL_SRC_FILES := main.c otp_gen.c sotp_crypto.c //编译so库的源文件,多个文件加空格分割
LOCAL_SHARED_LIBRARIES := liba libcrypto //动态库间也用空格分割
LOCAL_LDLIBS := -llog -lz -lm
include $(BUILD_SHARED_LIBRARY) // 动态库
因为预编译库只支持上述的两种类型,所以自己编译时就将ABI类型改为armeabi与x86
APP_MODULES:需要编译的模块名称,可以是多个,用空格分割,模块名称由Android.mk文件中的LOCAL_MODULE指出,现在特指所有的LOCAL,与默认效果一样。
三:错误集结
操作过程中遇到的问题做了下总结,如果有其他错误可以相互讨论
1:LOCAL_SRC_FILES points to a missing file 对应ABI目录下没有找到so库,根据提示信息确认每个支持的ABI目录下预编译库
1:Error:ABIs [armeabi] are not supported for platform. Supported ABIs are [arm64-v8a, armeabi-v7a, x86, x86_64].
错误原因:build.gradle配置了ndk不支持的cpu架构类型
ndk{
abiFilters 'x86',"armeabi"
}
改为支持的cpu架构重新编译即可:
ndk{
abiFilters 'x86',"armeabi-v7a"
}
2:使用ndk-build命令报:Android NDK: Could not find application project directory !
Android NDK: Please define the NDK_PROJECT_PATH variable to point to it.
ndk-build --directory=E:\BaiduNetdiskDownload\s\SOTPV2Test_chengdu\app\src\main\jni即可编译
注意标注的红色部分
3:Android NDK: The armeabi ABI is no longer supported. Use armeabi-v7a. 不再支持armeabi ABI。使用ARMEBAI V7A
Android NDK: NDK Application 'local' targets unknown ABI(s): armeabi NDK应用程序“本地”目标未知ABI:Armeabi
Android NDK: Please fix the APP_ABI definition in xx/jni/Application.mk 更改Application.mk 文件中的abi类型
原来Application.mk:
APP_ABI := x86 armeabi
APP_MODULES := local
根据翻译情况得知,需要更改.mk文件中的abi类型
更改Application.mk:
APP_ABI := x86 armeabi-v7a
APP_MODULES := local
5:xx/obj/local/arm64-v8a/libxx.so: error adding symbols: File in wrong format 添加符号时出错:文件格式错误
clang++.exe: error: linker command failed with exit code 1 (use -v to see invocation) clang++.exe:错误:链接器命令失败,退出代码为1(使用-v查看调用)
原Application.mk:
APP_ABI := x86 armeabi-v7a arm64-v8a
导致失败的原因为libxx.so不支持arm64-v8a类型的
6:Unable to recognise the format of the input file xx/main/libs/armeabi-v7a/libxx.so 无法识别输入文件的格式
make: *** xx/main/libs/armeabi-v7a/libxx.so] Error 1
make: *** Deleting file `xx/main/libs/armeabi-v7a/libxx.so' 正在删除文件
make: Leaving directory `xx/main/jni'
因为jni/armeabi-v7a/libxx.so库是从jni/x86/中考出来的,cpu abi类型不对,所以自动将编译好的armeabi-v7a/libxx.so错误文件删除掉,根据abi类型编译各自的库,不能混着用
四:ndk版本对比
根据版本不同编译不同类型的so文件,platforms 与prebuilt下可以查看支持的ABI类型,这只是个人理解,误喷但可以纠正,期待~~