什么是NDK、JNI
- JNI
Java Native Interface,即 Java 本地接口,可以理解为在 Java 中调用 C/C++ 代码、在 C/C++ 中调用 Java 代码,JNI 是 Java 的,和 Android 无关 - NDK
Native Development Kit,Android NDK 是一个工具集,可让您使用 C 和 C++ 等语言以原生代码实现应用的各个部分,NDK 可以理解为 Android 中实现 JNI 的一种手段,通过 NDK,还可以打包 C/C++ 动态库,并自动打包进 APK/AAR 中
CMakeLists.txt 是什么?
- Android Studio 新建项目的时候可以选择各种各样的模板,选择 Native C++ 模板就可以创建一个简单的 NDK 项目
在 app/src/main/cpp 下可以看到有 CMakeLists.txt 和 native-lib.cpp。 - 当只有一个源文件时,直接使用gcc命令就可以直接编译,如果有很多源文件、团队成员多个时,直接使用gcc命令编译就非常繁琐;这个时候make指令应运而生,可以多人编辑同一个编译规则文件后,make工具依照这个编译规则文件进行编译,源文件、目标文件、目标类型等等都在该文件中体现,这个文件就是makefile文件;但是慢慢地大家发现大项目时编写makefile文件依然是一个繁琐容易出错的事情,这个时候cmake工具就出现了,它可以依据简单的配置文件自动生成makefile、project等文件,这个配置文件就是 CMakeLists.txt !很显然,相对于编写makefile文件,编写cmakelists文件要简单的多。
- CMakeLists.txt + cmake -> makefile;makefile + make -> 编译出目标结果
CMakeLists.txt 详解
常用变量
PROJECT_NAME: 用函数project(demo)指定的项目名称,这里变量的值为demo
PROJECT_SOURCE_DIR: 工程的根目录
PROJECT_BINARY_DIR: 执行cmake命令的目录,如果mkdir build ,cd build, cmake ../,的话,该变量的值为build目录
CMAKE_CURRENT_SOURCE_DIR:当前处理的CMakeLists.txt文件所在目录
CMAKE_CURRENT_BINARY_DIR: cmake当前正在处理的二进制目录
CMAKE_CURRENT_LIST_DIR: CMakeLists.txt的完整路径
CMAKE_CURRENT_LIST_LINE: 当前所在行
CMAKE_C_FLAGS: 设置C编译选项
CMAKE_CXX_FLAGS:设置C++编译选项
CMAKE_INSTALL_PREFIX: 指定install指令安装文件的根目录
EXECUTABLE_OUTPUT_PATH: 生成目标可执行文件的输出位置
LIBRARY_OUTPUT_PATH: 库文件输出位置指定cmake最小版本:(必须设置)
cmake_minimum_required(VERSION 3.10.2)
- 设置项目名称:(必须设置)
project("projectname")
- 设置编译类型:(必须设置)
add_executable(projectname native-lib.cpp) //生成可执行文件
add_library(projectname STATIC native-lib.cpp) //生成静态库(默认)
add_library(projectname SHARED native-lib.cpp) //生成动态库
- 制定编译包含的源文件(必须设置)
1.明确指定源文件
add_library(projectname SHARED native-lib.cpp)
2.搜索指定目录下所有源文件(不会递归遍历子目录)
//搜索一个目录下所有的源代码文件,并将列表存储再一个变量中
aux_source_directory(. SRC_LIST)
add_library(projectname SHARED ${SRC_LIST})
3.自定义搜索源文件规则(推荐使用 aux_source_directory,不推荐使用 file)
//搜索一个目录下所有的源代码文件,并将列表存储再一个变量中
file(GLOB SRC_LIST "*.cpp")
file(GLOB SRC_LIST "*.c")
file(GLOB SRC_LIST "src/*.cpp")
aux_source_directory(src SRC_PROTOCOL_LIST)
add_library(projectname SHARED ${SRC_LIST})
- 查找指定的库文件
// find_library(VAR name path)查找到指定的预编译库,并将它的路径存储在变量中。
// 默认的搜索路径为cmake 包含的系统库,因此如果是NDK的公共库只需要指定库的name即可。
# 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)
- 设置包含的目录(编译环境、头文件等)
include_directories(
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}
${CMAKE_CURRENT_SOURCE_DIR}/include
)
- 设置链接库的搜索目录
link_directories(
${CMAKE_CURRENT_SOURCE_DIR}/libs
)
- 设置target需要连接的库(
${log-lib}
也可以使用绝对路径、指定链接多个库在${log-lib}
后换行追加即可)
# 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.
projectname
# Links the target library to the log library
# included in the NDK.
${log-lib})
- set 常用指令
set(SRC_LIST main.cpp test1.cpp) //设置源代码变量
set(SRC_LIST test2.cpp) //追加
set(EXECUTABLE_OUTPUT_PATH [path]) //设置可执行文件的输出路径
set(LIBRARY_OUTPUT_PATH [output_path]) //设置库文件的输出路径
set(CMAKE_CXX_FLAGS "-Wall std=c++11") //设置C++编译参数
- 打印信息
message(${PROJECT_SOURCE_DIR})
message("build with debug mode")
message(WARNING "this is warnning message")
条件控制
1.if...elseif...else...endif
2.while...endwhile
3.foreach...endforeach多目录、多源文件、多CMakeLists.txt
主CMakeLists.txt
...
#添加child目录
add_subdirectory(child)
...
target_link_libraries( # Specifies the target library.
projectname
child
# Links the target library to the log library
# included in the NDK.
${log-lib})
子CMakeLists.txt
#child目录下的CMakeLists.txt
...
aux_source_directory(. DIR_SRCS)
...
add_library(
child
SHARED
${DIR_SRCS}
)