谷歌从AndroidStudio2.2以上就添加了Cmake方式来编译So库,
这种方式比起原来命令行式的ndk-build方便了不少,
也不需要Android.mk,Application.mk和JNI文件夹了。
在下方的谷歌Android官方链接可以看到一个中文NDK的教程。
https://developer.android.com/studio/projects/add-native-code.html
而这个链接是谷歌Android官方英文Cmake指南
https://developer.android.com/ndk/guides/cmake.html
这俩都要认真上网
才能看。
Using Android Studio 2.2 and higher, you can use the NDK
and CMake
to compile C and C++ code into a native library. Android Studio then packages your library into your APK using Gradle, the IDE's integrated build system.
先说一下具体环境,使用的是,Windows10 + AndroidStudio3.0
新建一个NDK工程
首先创建一个新项目,选中Include C++ support,因为是NDK项目嘛(见图1)
然后一路点Next,可以选Empty Activity,Layout文件也不需要,
因为是为了编So库嘛,不是为了做apk。(见图2,图3)
最后则要选定C++标准,(比如C++11),异常,RTTI,(见图4)
就完成了,非常简单。
CMake构建
工程完成后,先关注下新建好的工程的目录结构,
(见图5)
最主要看两个文件,app目录内的build.gradle和CMakeList.txt
build.gradle是gradle构建的配置定义文件,这里就不展开讲了,只关注和CMake相关的。
externalNativeBuild {
cmake {
cppFlags "-std=c++11 -frtti -fexceptions"
}
}
externalNativeBuild {
cmake {
path "CMakeLists.txt"
}
}
cppFlags是刚才选择的C++11,rtti和异常
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)
# 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.
set(libs "${CMAKE_SOURCE_DIR}/libs")
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).
src/main/cpp/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.
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.
target_link_libraries( # Specifies the target library.
native-lib
# Links the target library to the log library
# included in the NDK.
${log-lib} )
cmake_minimum_required(VERSION 3.4.1)
用来设置在编译本地库时我们需要的最小的cmake版本,AndroidStudio自动生成,我们几乎不需要自己管。
以下是几个常用命令:
set
,CMake设置变量,变量在下面就可以使用
add_library
用来设置编译生成的本地库的名字为native-lib,SHARED表示编译生成的是动态链接库(这个概念前面已经提到过了),src/main/cpp/native-lib.cpp表示参与编译的文件的路径,这里面可以写多个文件的路径。
find_library
是用来添加一些我们在编译我们的本地库的时候需要依赖的一些库,由于cmake已经知道系统库的路径,所以我们这里只是指定使用log库,然后给log库起别名为log-lib便于我们后面引用,此处的log库是我们后面调试时需要用来打log日志的库,是NDK为我们提供的。
target_link_libraries
是为了关联我们自己的库和一些第三方库或者系统库,这里把我们把自己的库native-lib库和log库关联起来。
set_target_properties
命令的意思是设置目标的一些属性来改变它们构建的方式。
常见用法:
1)设置输出路径
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/src/main/libs/${ANDROID_ABI})
修改So的生成路径至main/libs,与main/cpp同级。
2)引用第三方库,通过set_target_properties,
设置IMPORTED_LOCATION
,就是被引入So库所在路径。
add_library(usb-1.0.9
SHARED
IMPORTED
)
set_target_properties(usb-1.0.9
PROPERTIES IMPORTED_LOCATION
"${libs}/${ANDROID_ABI}/libusb-1.0.9.so")
3)为子目录编译So库文件,
有的时候,我们并不想把所有代码文件打包成单一个So,那么可以为子目录写一个CMakeList.txt,
在这个子CMakeList.txt内,add_library,target_link_libraries,
然后在主CMakeList.txt里加一句add_subdirectory(src/main/cpp/子目录路径),
这样就会为子目录也生成一个So库文件,
我们在主CMakeList.txt里可以像引用第三方库一样引用这个子目录了。
更多:
对多个So编译,这两篇文章写的很好的。
分别是子目录
和多Module
编译多个So库文件。我就不赘述了。
子目录方式:http://blog.csdn.net/b2259909/article/details/58591898
多Module方式:https://www.jianshu.com/p/4e3c0c20c244
4)编译Debug版和Release版
target_link_libraries
可以附带debug,optimized的参数
用法如下:
target_link_libraries( # Specifies the target library.
native-lib
debug/optimized
# Links the target library to the log library
# included in the NDK.
${log-lib} )
target_link_libraries(< target> [item1 [item2 […]]] [[debug|optimized|general] < item>] …)
这个更多的具体的用法,可以看后面附的CMake命令链接。
5)CMake引入CpuFeatures库
在CMakeList.txt里加这两句,然后就可以在target_link_libraries调用cpufeatures了
include(AndroidNdkModules)
android_ndk_import_module_cpufeatures()
target_link_libraries( # Specifies the target library.
native-lib
cpufeatures
# Links the target library to the log library
# included in the NDK.
${log-lib} )
更进一步学习CMake
https://www.zybuluo.com/khan-lau/note/254724
这篇文章很好,翻译了https://cmake.org/cmake-tutorial/,和CMake的80个命令
CMake的全部命令,官网链接:
https://cmake.org/cmake/help/latest/manual/cmake-commands.7.html
CMake的帮助文档,官网链接:
https://cmake.org/cmake/help/latest/index.html
最后,编译So库
点击Make Project,各个ABI的So,就生成在相应的目录内了。