编译使用jni有两种构建方式,:
编写CMakeList.txt,以及跟Android.mk的对比
1.设置需要设置构建jni所需的CMake的最低版本
cmake_minimum_required(VERSION 3.4.1)
2.设置生成的so动态库最后输出的路径,如果项目的so库不需要给别人使用,也可以不设置,不设置的话会生成在build里面,如果给别人使用,寻找的话还是比较麻烦,所以指定一下路径更方便。
#设置生成的so动态库最后输出的路径,set后面两个参数,
#前面一个是命令,后面是路径。
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/../jniLibs/${ANDROID_ABI})
3.设置头文件搜索路径,如果跟CMakeLists.txt同路径则不需要设置,同路径下文件夹不行。
#设置头文件搜索路径(和此txt同个路径的头文件无需设置),可选
include_directories(Cipher
Core
Core/Common
Core/DB
Core/DG)
对应于Android.mk 下的 LOCAL_C_INCLUDES
4.设置生成so库的名称,并为源文件提供一个相对路径
file(GLOB jni "*.cpp")//设置统配符
file(GLOB Cipher "Cipher/*.cpp")//设置统配符
add_library( # Sets the name of the library. 设置库的名称,也就是生成的so名称,在java代码中加载so库需要与此一致
demo
# Sets the library as a shared library. 将library设置为一个共享库
SHARED
# Provides a relative path to your source file(s).为源文件提供一个相对路径,可以使用通配符,也可以一个一个文件的引入
demo.cpp
${jni}//引用上面设置到通配符
${Cipher}
)
对应于Android.mk
LOCAL_MODULE 设置so库的名称
LOCAL_SRC_FILES 设置源文件
FILE_LIST 设置文件列表,也就是通配符
5.使用本地系统库,在CMake默认的搜索路径就已经包含了系统库,所以直接指定名称就行,CMake会验证库是否存在。
find_library( # Sets the name of the path variable.
设置路径变量的名称,后面会引用到
log-lib //log日志,默认都需要添加
# Specifies the name of the NDK library that 指定NDK库的名称
# you want CMake to locate.
log
)
find_library( # Sets the name of the path variable. 设置路径变量的名称
jnigraphics-lib
# Specifies the name of the NDK library that 指定NDK库的名称
# you want CMake to locate.
jnigraphics
)
对应于Android.mk 下的 LOCAL_LDLIBS
6.加载第三库,比如自己定义的库,或者用的第三方库,.a库等等
//比如添加一个第三方库libpng,这两个需要配合使用
add_library(libpng STATIC IMPORTED)
set_target_properties( libpng
PROPERTIES IMPORTED_LOCATION
......../libpng.a )
使用的时候,只需要修改将两个libpng名称改成你需要的,可以随意取,该名称是后面用来链接使用的,再修改一下对应文件路径就ok。
对应于Android.mk 下的 LOCAL_LDLIBS
7.链接所有的库,比如上面我们添加的第三方库,添加的本地log库
target_link_libraries( # Specifies the target library.指定目标library中。
//通过add_library添加的直接写设置的名字,
//一种是SHARED,一般来说就是我们需要生成的so文件
//二中是STATIC IMPORTED 添加的第三方静态库
demo
libpng
# Links the target library to the log library 将目标library链接到日志库
# included in the NDK.
//链接本地NDK里面的库
${log-lib}
${jnigraphics-lib}
)
8.如何通过CMakeList.txt生成多个so库?针对不同的so库,编写不同的CMakeList.txt,然后在主CMakeList.txt中加载
# 再主CMakeList.txt中加载其他的子CMakeList.txt文件
# 指定子CMakeList.txt文件路径(指定到CMakeList.txt所在文件夹即可)
ADD_SUBDIRECTORY(FrameWork/ThirdParty/a)
ADD_SUBDIRECTORY(b)
9.如果不进行配置,那么默认会生成四种架构的so库文件,如何生成指定的so库文件
完整的CMakeList.txt文件脚本
# For more information about using CMake with Android Studio, read the
# documentation: https://d.android.com/studio/projects/add-native-code.html
# Sets the minimum version of CMake required to build the native library.
cmake_minimum_required(VERSION 3.4.1)
# 设置生成的so动态库最后输出的路径
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/../jniLibs/${ANDROID_ABI})
#设置头文件搜索路径(和此txt同个路径的头文件无需设置),可选
include_directories(Cipher
Core
Core/Common
Core/DB
Core/DG
)
file(GLOB jni "*.cpp")
file(GLOB Cipher "Cipher/*.cpp")
# Creates and names a library, sets it as either STATIC
# or SHARED, and provides the relative paths to its source code.
# You can define multiple libraries, and CMake builds them for you.
# Gradle automatically packages shared libraries with your APK. Gradle
add_library( # Sets the name of the library. 设置库的名称。
demo
# Sets the library as a shared library. 将library设置为一个共享库
SHARED
# Provides a relative path to your source file(s).为源文件提供一个相对路径
demo.cpp
${jni}
${Cipher}
)
# Searches for a specified prebuilt library and stores the path as a
# variable. Because CMake includes system libraries in the search path by
# default, you only need to specify the name of the public NDK library
# you want to add. CMake verifies that the library exists before
# completing its build.
find_library( # Sets the name of the path variable. 设置路径变量的名称
log-lib
# Specifies the name of the NDK library that 指定NDK库的名称
# you want CMake to locate.
log
)
find_library( # Sets the name of the path variable. 设置路径变量的名称
jnigraphics-lib
# Specifies the name of the NDK library that 指定NDK库的名称
# you want CMake to locate.
jnigraphics
)
# Specifies libraries CMake should link to your target library. You
# can link multiple libraries, such as libraries you define in this
# build script, prebuilt third-party libraries, or system libraries.
add_library(libpng STATIC IMPORTED)
set_target_properties( libpng
PROPERTIES IMPORTED_LOCATION
..../libpng.a )
target_link_libraries( # Specifies the target library.
demo
libpng
# Links the target library to the log library
# included in the NDK.
${log-lib}
${jnigraphics-lib}
)
//加载子CMakeList.txt文件
ADD_SUBDIRECTORY(FrameWork/ThirdParty/a)
ADD_SUBDIRECTORY(b)
externalNativeBuild {
cmake {
cppFlags ""
abiFilters "armeabi-v7a"//需要什么构架的so,就在这边添加即可
}
}
所遇到的问题
1.从eclipse转化过来的工程,使用CMakeList.txt,部分头文件的导入路径会发生改变,需要进行修改。可能跟CMakeList.txt里面的头文件配置有关系。
2.More than one file was found with OS independent path ‘lib/arm64-v8a/xxx.so’ 如果运行的时候遇到这个问题。在gradle里面配置一下。原因不详,按理说通过CMakeList.txt设置生成目录到jniLibs后,so存放在jniLibs里面,而在gradle里面配置只有so库存放在lib下才需要,但是看这个错误好像是lib下冲突,但我lib下并没有存放so文件,编译可以通过,运行就会报错,然后我看了一下bulid下面也有一份so库文件,难道运行后,会自动将bulid下的so文件复制到lib里面吗?如果有知道的原因,麻烦告诉一声,感激不尽!
sourceSets{
main{
jniLibs.srcDirs = ['libs']
}
}
更多参考https://blog.csdn.net/u012528526/article/details/80647537
# For more information about using CMake with Android Studio, read the
# documentation: https://d.android.com/studio/projects/add-native-code.html
# Sets the minimum version of CMake required to build the native library.
# 设置构建本机库所需的CMake的最小版本。
cmake_minimum_required(VERSION 3.4.1)
# Creates and names a library, sets it as either STATIC
# or SHARED, and provides the relative paths to its source code.
# You can define multiple libraries, and CMake builds them for you.
# Gradle automatically packages shared libraries with your APK.
# 创建并命名库,将其设置为静态或共享,并提供到其源代码的相对路径。
#您可以定义多个库,CMake为您构建它们。
# Gradle自动将共享库打包到APK中。
add_library( # Sets the name of the library.
native-lib
# Sets the library as a shared library.
SHARED
# Provides a relative path to your source file(s).
native-lib.cpp )
# Searches for a specified prebuilt library and stores the path as a
# variable. Because CMake includes system libraries in the search path by
# default, you only need to specify the name of the public NDK library
# you want to add. CMake verifies that the library exists before
# completing its build.
# 搜索指定的预构建库并将路径存储为变量。
# 因为CMake在搜索路径by中包含了系统库默认情况下,
# 您只需要指定公共NDK库的名称 CMake验证库之前是否存在完成构建。
find_library( # Sets the name of the path variable.
log-lib
# Specifies the name of the NDK library that
# you want CMake to locate.
log )
# Specifies libraries CMake should link to your target library. You
# can link multiple libraries, such as libraries you define in this
# build script, prebuilt third-party libraries, or system libraries.
#指定库CMake应该链接到目标库。你可以链接多个库,
#比如您在本文中定义的库构建脚本、预构建的第三方库或系统库
target_link_libraries( # Specifies the target library.
native-lib
# Links the target library to the log library
# included in the NDK.
${log-lib} )