1. 新建的NDK项目
当我们新建了一个NDK项目,打开CMakeLists.txt
,会有如下内容,下面对这些命令做了注解
#指定CMake最小支持版本
cmake_minimum_required(VERSION 3.18.1)
#项目名称
project("myndktest")
# 添加一个库,根据native-lib,cpp源文件编译一个native-lib的动态库
add_library(
myndktest #设置库的名称
SHARED #将库设置为动态链接库(即.so文件)
native-lib.cpp) # 源文件的相对路径
# 查找系统库,这里查找的是系统日志库,并赋值给变量lig-lib
# 实际路径:D:\Android\SDK\ndk-bundle\platforms\android-21\arch-arm\usr\lib\liblog.so
find_library(
log-lib #设置名称
log) # 指定在NDK库中的路径
# 设置依赖的库 (第一个参数必须为目标模块,顺序不能换)
target_link_libraries( # Specifies the target library.
myndktest
${
log-lib})
2. 常用的一些命令
2.1 cmake_minimum_required
指定Cmake最低支持的版本
2.2 aux_source_directory(. DIR_SRCS)
查找当前目录所有源文件,并将源文件名称列表保存到DIR_SRCS
变量,但是不能查找子目录
2.3 add_library
作用一:添加一个库
add_library(<name> [STATIC|SHARED|MODULE] [EXCLUDE_FROM_ALL] source1 source2 ... sourceN)
name
:设置库的名称
STATIC|SHARED|MODULE
:指定库的类型。STATIC
:静态库,SHARED
:动态库(.so文件),MODULE
:在使用dyld的系统有效,若不支持dyld,等同于STATIC
EXCLUDE_FROM_ALL
:表示该库不会被默认构建
source1 source2 ... sourceN
: 用来指定库的源文件
作用二:导入预编译库
添加一个已存在的预编译库,名为<name>
一般配合set_target_properties使用
add_library(<name> <STATIC|SHARED|MODULE|UNKNOWN> IMPORTED)
比如
add_library(test SHARED IMPORTED)
set_target_properties(
test #指定目标库名
PROPERTIES IMPORTED_LOCATION #指明要设定的参数
库路径/${
ANDROID_ABI}/xxxxx.so #导入库的路径
)
2.4 常用命令之set
用来设置CMake的变量
# 设置可执行文件的输出路径 (EXECUTABLE_OUTPUT_PATH是全局变量)
set(EXECUTABLE_OUTPUT_PATH [output_path])
# 设置库文件的输出路径 (LIBRARY_OUTPUT_PATH是全局变量)
set(LIBRARY_OUTPUT_PATH [output_path])
# 设置C++编译参数 (CMAKE_CXX_FLAGS是全局变量)
set(CMAKE_CXX_FLAGS "-Wall std=c++11")
# 设置源文件集合 (SOURCE_FILES是本地变量即自定义变量)
set(SOURCE_FILES main.cpp test.cpp ...)
2.5 include_directories
设置头文件目录,相当于g++
选项中的-l
参数
#可以使用相对或绝对路径,也可以用自定义的变量值
include_directories(./include ${
MY_INCLUDE})
2.6 add_executable
添加可执行文件
add_executable(<name> ${
SRC_LIST})
2.7 target_link_libraries
将若干库链接到目标库文件
target_link_libraries(<name> lib1 lib2 lib3)
2.8 add_definitions
add_definitions(-DFOO -DDEBUG ...)
为当前路径以及子目录的源文件加入由-D
引入的define flag
,通常用来添加编译参数
2.9 add_subDirectory
如果当前目录下还有子目录时可以用add_subDirectory
,子目录中也需要包含有CMakeLists.txt
2.10 file命令
进行文件操作
2.11 set_directory_properties
set_directory_properties(PROPERTIES prop1 value1 prop2 value2)
设置某个路径的一种属性
prop1
、prop2
代表属性,取值为
INCLUDE_DIRECTORIES
LINK_DIRECTORIES
INCLUDE_REGULAR_EXPRESSION
ADDITIONAL_MAKE_CLEAN_FILES
2.12 set_property
在给定的作用域内设置一个命名的属性
3. 常用处理
3.1 多个源文件处理
如果源文件很多,把所有文件一个个加入很麻烦,可以使用aux_source_directory
命令或file
命令,查找指定目录下的所有源文件,然后将结果存进指定变量名。
# 查找当前目录所有源文件,并将名称保存到 DIR_SRCS 变量,不能查找子目录
aux_source_directory(. DIR_SRCS)
# 也可以使用
file(GLOB DIR_SRCS *.c *.cpp)
add_library(
myndktest
SHARED
${
DIR_SRCS})
3.2 多目录多源文件处理
主目录中的CMakeLists.txt
中添加add_subdirectory(child)
命令,指明本项目包含一个子项目child
。
并在target_link_libraries
指明本项目需要链接一个名为child
的库。
aux_source_directory(. DIR_SRCS)
# 添加 child 子目录下的cmakelist
add_subdirectory(child)
add_library(
native-lib
SHARED
${
DIR_SRCS}
)
target_link_libraries(native-lib child)
子目录child
中创建CMakeLists.txt
,这里child
编译为动态库
aux_source_directory(. DIR_LIB_SRCS)
add_library(
child
SHARED
${
DIR_LIB_SRCS}
)
3.3 添加预编译库(Android6.0版本以后)
在Android6.0
及以上版本,使用这种方式添加预编译动态库
# set命令定义一个变量
# CMAKE_C_FLAGS : c的参数,会传递给编译器
# 如果是c++文件,需要用CMAKE_CXX_FLAGS
# -L : 库的查找路径
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -L[SO所在目录]")
3.4 添加头文件目录
为了确保CMake
可以字啊编译时定位头文件,使用include_directories
,相当于g++
选项中的-l
参数。
这样就可以使用#include <xx.h>
,否则需要使用#include "path/xx.h"
# 设置头文件目录
include_directories(<文件目录>)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -L[SO所在目录]")
aux_source_directory(. DIR_SRCS)
add_library(
native-lib
SHARED
${
DIR_SRCS}
)
target_link_libraries(native-lib imported-lib)
3.5 Build.gradle配置
android {
//...
defaultConfig {
//...
externalNativeBuild {
cmake {
//使用的编译器 clang/gcc
//cmake默认就是 gnustl_static arguments "-DANDROID_TOOLCHAIN=clang","-DANDROID_STL=gnustl_static"
//指定cflags和cppflags,效果和cmakelist使用一样
cFlags ""
cppFlags ""
//指定需要编译的CPU架构
abiFilters "armeabi-v7a","arm64-v8a"
}
}
}
externalNativeBuild {
cmake {
//指定CMakeLists.txt文件相较于当前Build.gradle的路径
path file('src/main/cpp/CMakeLists.txt')
//设置CMake版本
version '3.18.1'
}
}
//...
}