如果希望将so库生成到特定目录,并让项目直接使用该目录下的so,应该如何配置呢?
比较简单:需要在CMakeList.txt中配置库的输出路径信息,即:
CMAKE_LIBRARY_OUTPUT_DIRECTORY
# cmake最低版本要求 cmake_minimum_required(VERSION 3.4.1) # 配置库生成路径 # CMAKE_CURRENT_SOURCE_DIR是指 cmake库的源路径,通常是build/.../cmake/ # /../jniLibs/是指与CMakeList.txt所在目录的同级目录:jniLibs (如果没有会新建) # ANDROID_ABI 生成库文件时,采用gradle配置的ABI策略(即:生成哪些平台对应的库文件) set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/../jniLibs/${ANDROID_ABI}) # 添加库 add_library( # 库名 native-lib # 类型: # SHARED 是指动态库,对应的是.so文件 # STATIC 是指静态库,对应的是.a文件 # 其他类型:略 SHARED # native类路径 native-lib.cpp) # 查找依赖库 find_library( # 依赖库别名 log-lib # 希望加到本地的NDK库名称,log指NDK的日志库 log) # 链接库,建立关系( 此处就是指把log-lib 链接给native-lib使用 ) target_link_libraries( # 目标库名称(native-lib就是咱们要生成的so库) native-lib # 要链接的库(上面查找的log库) ${log-lib})还需要在gradle中配置 jniLibs.srcDirs 属性(即:指定了lib库目录):
sourceSets { main { jniLibs.srcDirs = ['jniLibs']//指定lib库目录 } }接着,重新build就会在cpp相同目录级别位置生成jniLibs目录,so库也在其中了:
注意事项: 1、配置了CMAKE_CURRENT_SOURCE_DIR,并非表示编译时直接将so生成在该目录中,实际编译时,so文件仍然是 先生成在build/.../cmake/中,然后再拷贝到目标目录中的 2、如果只配置了CMAKE_CURRENT_SOURCE_DIR,并未在gradle中配置 jniLibs.srcDirs,也会有问题,如下: More than one file was found with OS independent path 'lib/arm64-v8a/libnative-lib.so' 此问题是指:在编译生成apk时,发现了多个so目录,android studio不知道使用哪一个了,所以需要咱们 告诉android studio当前工程使用的是jniLibs目录,而非build/.../cmake/目录 3.2.5、如何生成指定CPU平台对应的库文件呢?我们可以在cmake中设置abiFilters,也可在ndk中设置abiFilters,效果是一样的:
defaultConfig { applicationId "com.qxc.testnativec" minSdkVersion 21 targetSdkVersion 29 versionCode 1 versionName "1.0" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" externalNativeBuild { cmake { cppFlags "" abiFilters "arm64-v8a" } } } defaultConfig { applicationId "com.qxc.testnativec" minSdkVersion 21 targetSdkVersion 29 versionCode 1 versionName "1.0" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" externalNativeBuild { cmake { cppFlags "" } } ndk { abiFilters "arm64-v8a" } }按照新的配置,我们重新运行工程,如下图:
再反编译看下工程,果然只有arm64-v8a的so库了,不过库文件在apk中仍然是放在lib目录,而非jniLibs(其实也很好理解,jniLibs只是我们本地的目录,便于我们管理库文件,真正生成apk时,仍然会按照lib目录放置库文件),如下图:
至此,CMake的主要技术点都讲完了,接下来咱们看下NDK-Build吧~
3.3、ndk-build的应用在ndk-build编译之前,咱们又应该先做哪些准备工作?
1、ndk-build环境变量是否正确配置? -- 如果未配置,是无法在cmd、Mac终端、Terminal中使用ndk-build命令的(会报错:找不到命令) 2、NDK环境是否配置正确? -- 如果未配置正确是无法进行C/C++开发的,更不用说ndk-build编译了 3、C/C++功能是否实现? -- 此次演示主要使用系统默认创建的native-lib.cpp文件,关于具体如何实现:后续文章再详细讲解 -- 注意:为了与CMake区分,咱们新建一个“jni”目录存放C/C++文件、配置文件吧 4、Android.mk是否创建并正确配置? -- 该文件是ndk-build工具编译的基础,未配置或配置项错误,均会影响编译结果 5、gradle是否正确配置?(可选项,如果通过cmd、Mac终端、Terminal执行ndk-build,可忽略) -- gradle配置也是ndk-build工具编译的基础,未配置或配置项错误,均会影响编译结果 6、Application.mk是否创建并正确配置?(可选项,一般配ABI、版本,这些项均可在gradle中配置) -- 该文件也是ndk-build工具编译的基础,未配置或配置项错误,均会影响编译结果