在Android NDK CMake工程中引入其他C++三方库时,有以下几种常见的依赖方式:
如果三方库的源代码包含在你的项目目录中,并且它有自己的CMake配置,可以使用add_subdirectory
将三方库的构建过程集成到你的项目中。
假设三方库的源代码位于third_party/SomeLibrary
目录下。
# CMakeLists.txt
# 添加三方库的构建
add_subdirectory(third_party/SomeLibrary)
# 添加可执行文件目标
add_library(native-lib SHARED native-lib.cpp)
# 将三方库链接到目标
target_link_libraries(native-lib PRIVATE SomeLibrary)
如果三方库已经预先编译成.so
或.a
文件,可以使用add_library
和target_link_libraries
来引入这些预编译库。
适用场景:第三方库已提供针对 Android 的预编译动态库(.so
)和头文件。
假设三方库的预编译.so
文件位于libs/${ANDROID_ABI}/libSomeLibrary.so
。
# CMakeLists.txt
# 添加预编译库
add_library(SomeLibrary SHARED IMPORTED)
set_target_properties(SomeLibrary PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/libs/${ANDROID_ABI}/libSomeLibrary.so)
# 添加可执行文件目标
add_library(native-lib SHARED native-lib.cpp)
# 将预编译库链接到目标
target_link_libraries(native-lib PRIVATE SomeLibrary)
.so
)步骤:
放置文件:
.so
文件按 ABI 分类放入 src/main/jniLibs/abi/
目录(如 armeabi-v7a/libmylib.so
)。src/main/cpp/include/
目录。配置 CMakeLists.txt
:
# 设置头文件路径
include_directories(src/main/cpp/include)
# 导入动态库(以 openssl 为例)
add_library(openssl SHARED IMPORTED)
set_target_properties(openssl PROPERTIES
IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/src/main/jniLibs/${ANDROID_ABI}/libssl.so
)
# 添加自己的目标(如共享库)
add_library(native-lib SHARED
src/main/cpp/native-lib.cpp
)
# 链接第三方库和系统库(如 log)
target_link_libraries(native-lib
openssl
log # Android 系统日志库
)
.a
)步骤:
放置文件:
.a
文件放入 src/main/jniLibs/abi/
目录。src/main/cpp/include/
。配置 CMakeLists.txt
:
# 导入静态库(如 libpng)
add_library(png STATIC IMPORTED)
set_target_properties(png PROPERTIES
IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/src/main/jniLibs/${ANDROID_ABI}/libpng.a
)
# 链接静态库
target_link_libraries(native-lib
png
log
)
FetchContent
模块(CMake 3.11+)如果三方库可以从远程位置(如Git仓库)获取,可以使用FetchContent
模块在构建过程中自动下载和构建三方库。
假设三方库的Git地址为https://github.com/someuser/SomeLibrary.git
。
# CMakeLists.txt
# 启用FetchContent模块
include(FetchContent)
# 下载并构建三方库
FetchContent_Declare(
SomeLibrary
GIT_REPOSITORY https://github.com/someuser/SomeLibrary.git
GIT_TAG main
)
FetchContent_MakeAvailable(SomeLibrary)
# 添加可执行文件目标
add_library(native-lib SHARED native-lib.cpp)
# 将三方库链接到目标
target_link_libraries(native-lib PRIVATE SomeLibrary)
如果三方库的源代码是一个简单的库,没有复杂的构建系统,可以直接将源文件添加到你的CMake工程中。
假设三方库的源文件位于third_party/SomeLibrary/src
目录下,头文件位于third_party/SomeLibrary/include
目录下。
# CMakeLists.txt
# 添加三方库的源文件
add_library(SomeLibrary STATIC)
target_sources(SomeLibrary PRIVATE
third_party/SomeLibrary/src/file1.cpp
third_party/SomeLibrary/src/file2.cpp
)
target_include_directories(SomeLibrary PRIVATE
third_party/SomeLibrary/include
)
# 添加可执行文件目标
add_library(native-lib SHARED native-lib.cpp)
# 将三方库链接到目标
target_link_libraries(native-lib PRIVATE SomeLibrary)
步骤:
将源码放入项目目录:
thirdparty/
目录下(如 thirdparty/openssl
)。配置 CMakeLists.txt
:
# 将第三方库的源码目录加入子目录编译
add_subdirectory(${CMAKE_SOURCE_DIR}/thirdparty/openssl)
# 添加自己的目标
add_library(native-lib SHARED src/main/cpp/native-lib.cpp)
# 链接编译后的库
target_link_libraries(native-lib
openssl # 假设第三方库生成的库名为 openssl
log
)
include_directories
指定头文件路径如果需要引入三方库的头文件,可以使用include_directories
指定头文件路径。
假设三方库的头文件位于third_party/SomeLibrary/include
目录下。
# CMakeLists.txt
# 指定头文件路径
include_directories(third_party/SomeLibrary/include)
# 添加可执行文件目标
add_library(native-lib SHARED native-lib.cpp)
# 如果是预编译库,还需要指定库文件路径并链接
# add_library(SomeLibrary SHARED IMPORTED)
# set_target_properties(SomeLibrary PROPERTIES IMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/libs/${ANDROID_ABI}/libSomeLibrary.so)
# target_link_libraries(native-lib PRIVATE SomeLibrary)
find_package
)步骤:
确保库已安装:
配置 CMakeLists.txt
:
# 查找已安装的 OpenCV 库
find_package(OpenCV REQUIRED)
# 添加目标并链接
add_library(native-lib SHARED src/main/cpp/native-lib.cpp)
target_include_directories(native-lib PRIVATE ${OpenCV_INCLUDE_DIRS})
target_link_libraries(native-lib ${OpenCV_LIBS} log)
ExternalProject_Add
)步骤:
CMakeLists.txt
:# 下载并编译第三方库(如 gtest)
include(ExternalProject)
ExternalProject_Add(
gtest
GIT_REPOSITORY https://github.com/google/googletest.git
CMAKE_ARGS -DCMAKE_INSTALL_PREFIX=${CMAKE_BINARY_DIR}/gtest
)
# 添加目标并链接
add_library(gtest-lib INTERFACE)
target_include_directories(gtest-lib INTERFACE
${CMAKE_BINARY_DIR}/gtest/include
)
target_link_libraries(gtest-lib INTERFACE
${CMAKE_BINARY_DIR}/gtest/lib/libgtest.a
)
# 使用 gtest
add_executable(my_test test.cpp)
target_link_libraries(my_test gtest-lib)
头文件路径:
include_directories( # 传统方式
src/main/cpp/include
thirdparty/include
)
# 推荐使用 target_include_directories
target_include_directories(native-lib PRIVATE
${CMAKE_SOURCE_DIR}/src/main/cpp/include
)
动态库路径的动态化:
${ANDROID_ABI}
变量自动适配不同 ABI:set(LIB_DIR ${CMAKE_SOURCE_DIR}/src/main/jniLibs/${ANDROID_ABI})
set_target_properties(png PROPERTIES
IMPORTED_LOCATION ${LIB_DIR}/libpng.so
)
依赖传递性:
libcrypto.so
),需逐层导入:add_library(crypto SHARED IMPORTED)
set_target_properties(crypto PROPERTIES
IMPORTED_LOCATION ${LIB_DIR}/libcrypto.so
)
target_link_libraries(openssl PRIVATE crypto) # openssl 依赖 crypto
.so
或.a
文件。FetchContent
:适用于从远程位置获取并自动构建三方库。include_directories
:适用于需要引入三方库的头文件。.so
) | 不需要 | 第三方提供预编译动态库 | 快速集成,无需编译 | 需确保 ABI 兼容性 |.a
) | 不需要 | 第三方提供静态库 | 静态链接,无依赖传递问题 | 文件体积较大 |add_subdirectory
) | 需要 | 需自定义编译或库未提供预编译文件 | 灵活配置,支持修改源码 | 需处理交叉编译及依赖 |find_package
) | 不需要 | 系统已安装且提供 CMake 配置文件 | 自动化配置,简洁 | 依赖系统环境 |ExternalProject
) | 需要 | 需自动管理源码下载和编译 | 自动化流程,便于版本控制 | 构建时间较长 |通过以上方法,可以根据第三方库的提供形式和项目需求,灵活选择最合适的依赖方式。