NDK 通过工具链文件支持 CMake。工具链文件是用于自定义交叉编译工具链行为的 CMake 文件。从 NDK r19 开始,NDK 默认安装的工具链可供使用。与任意构建系统进行交互时不再需要使用 make_standalone_toolchain.py 脚本。
一、基本使用
cmake_minimum_required(VERSION 3.4.1) 设置cmake最低版本
# 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.
add_library( # Sets the name of the library. 设置生成so文件名
my-jni
# Sets the library as a shared library. 设置库的类型,一种是静态的STATIC .a文件,一种是动态SHARED so文件
SHARED
# Provides a relative path to your source file(s). 要编译的C/C++文件,可以编译多个文件
src/main/cpp/JniTest.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.
my-jni
# Links the target library to the log library
# included in the NDK.
c++_shared
${log-lib})
# C的编译选项是 CMAKE_C_FLAGS
# 指定编译参数,可选
# set(CMAKE_CXX_FLAGS "-Wno-error=format-security -Wno-error=pointer-sign")
# 设置生成的so动态库最后输出的路径
# set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/../jniLibs/${ANDROID_ABI})
# 设置头文件搜索路径(和此txt同个路径的头文件无需设置),可选
# include_directories(${CMAKE_CURRENT_SOURCE_DIR}/common)
# 指定用到的系统库或者NDK库或者第三方库的搜索路径,可选。
# link_directories(/usr/local/lib)
二、如何生成多个so文件
方法一:
直接在app/下的CMakeLists.text 的末尾添加要生成的so 文件名,资源路径,添加内容如下
add_library(test-lib SHARED src/main/cpp/test.cpp)
target_link_libraries(test-lib ${log-lib} )
方法二 创建一个新的CMakeLists.txt文件
文件内容如下 和上面的内容是一样的,然后在app下的CMakeLists.txt 末尾添加
# 添加子目录,将会调用子目录中的CMakeLists.txt,括号内的内容是我们创建的CMakeLists.txt的路径
add_subdirectory(src/main/cpp/one)
add_subdirectory(two)
三、指令汇总
1. 设置project name
set(PROJECT_NAME sunny)
project (${PROJECT_NAME})
2. .so输出路径:CMAKE_LIBRARY_OUTPUT_DIRECTORY
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/../jniLibs/${ANDROID_ABI})
3. .a 静态库输出路径:CMAKE_ARCHIVE_OUTPUT_DIRECTORY
4. 获取当前CMake路径:CMAKE_CURRENT_SOURCE_DIR
5. 设置头文件目录:include_directories
# 设置头文件搜索路径(和此txt同个路径的头文件无需设置),可选
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/common)
6. target_link_libraries
# 将若干库链接到目标库文件
# 将lib1/lib2/lib3链接到<name>库里面
# 链接顺序应该符合gcc链接顺序规则,被链接的库放在依赖它的库的后面
# 如果lib1依赖于lib2,lib2依赖于lib3,则必须严格按照lib1 lib2 lib3顺序排列,否则会报错
target_link_libraries(<name> lib1 lib2 lib3)
#如果出现相互依赖的静态库,CMake会运行出现依赖循环
add_library(A STATIC a.c)
add_library(B STATIC b.c)
target_link_libraries(A B)
target_link_libraries(B A)
add_executable(main main.c)
target_link_libraries(main A)
7. 获取当前编译的abi:ANDROID_ABI
8. 编译选项:
CMAKE_C_FLAGS
CMAKE_CXX_FLAGS
CMAKE_CXX_FLAGS_DEBUG/CMAKE_CXX_FLAGS_RELEASE
set(CMAKE_CXX_FLAGS "-Wno-error=format-security -Wno-error=pointer-sign")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -L${CMAKE_SOURCE_DIR}/../jniLibs/${CMAKE_ANDROID_ARCH_ABI}")
9. 子目录编译:add_subdirectory
# 添加子目录,将会调用子目录中的CMakeLists.txt
add_subdirectory(one)
# sub_dir 指定包含CMakeLists.txt和源码文件的子目录位置
# [binary_dir]是输出路径,一般可以不指定
# 如果当前目录下还有子目录时可以使用add_subdirectory,子目录中也需要包含有CMakeLists.txt
add_subdirectory(sub_dir [binary_dir])
10. 设置.c文件集合的变量
#查找当前cmakelists.txt所在目录的所有.c .cpp源文件,并将源文件名称列表保存到DIR_SRCS变量,不能查找子目录
aux_source_directory(. SRC_LIST)
#增加其他目录的源文件到集合变量中
list(APPEND SRC_LIST
../common/1.c
../common/2.c
../common/3.c
../common/4.c
../common/5.c
../common/WriteLog.c
)
#生成so库,直接使用变量代表那些.c文件集合
add_library(${PROJECT_NAME} SHARED ${SRC_LIST})
11. 指定当前目录下的所有.cpp文件(包括子目录)
file(GLOB_RECURSE cpp_src "${SRC_DIR}/*.cpp")
add_library(${PROJECT_NAME} SHARED ${cpp_src})
12. file

GLOB选项将会为所有匹配查询表达式的文件生成一个文件list,并将该list存储进变量variable里。
GLOB_RECURSE选项将会生成一个类似于通常的GLOB选项的list,只是它会寻访所有那些匹配目录的子路径并同时匹配查询表达式的文件。
13. add_library 导入预编译库
#一般配合set_target_properties使用
add_library(test
SHARED
IMPORTED)
set_target_properties(
test #指定目标库名
PROPERTIES IMPORTED_LOCATION #指明要设置的参数
${CMAKE_ANDROID_ARCH_ABI}/libtest.so #导入库的路径
)
14. 执行自定义命令
# copy头文件到 静态库相同文件夹下
add_custom_command(TARGET myjni
PRE_BUILD
COMMAND echo "executing a copy command"
COMMAND cp ${CMAKE_CURRENT_SOURCE_DIR}/myjni.h ${PROJECT_SOURCE_DIR}/../../../build/outputs/staticLib/myjni/${ANDROID_ABI}
COMMENT "PRE_BUILD, so This command will be executed before building target myjni"
)
本文详细介绍了如何使用CMake与AndroidNDK进行集成,包括基本CMake配置、添加库、生成多so文件的方法,以及CMakeLists.txt的使用技巧和常见指令,帮助开发者更高效地管理跨平台编译过程。

被折叠的 条评论
为什么被折叠?



