NDK CMake工程中引入其他C++三方库

在Android NDK CMake工程中引入其他C++三方库时,有以下几种常见的依赖方式:

1. 源码依赖

如果三方库的源代码包含在你的项目目录中,并且它有自己的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)

2. 预编译库依赖

如果三方库已经预先编译成.so.a文件,可以使用add_librarytarget_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)
方式 1:预编译动态库(.so

步骤

  1. 放置文件

    • .so 文件按 ABI 分类放入 src/main/jniLibs/abi/ 目录(如 armeabi-v7a/libmylib.so)。
    • 将头文件放入 src/main/cpp/include/ 目录。
  2. 配置 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 系统日志库
    )
    

方式 2:预编译静态库(.a

步骤

  1. 放置文件

    • .a 文件放入 src/main/jniLibs/abi/ 目录。
    • 头文件放入 src/main/cpp/include/
  2. 配置 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
    )
    

3. 使用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)

4. 手动指定源文件

如果三方库的源代码是一个简单的库,没有复杂的构建系统,可以直接将源文件添加到你的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)

步骤

  1. 将源码放入项目目录

    • 将第三方库的源码放在 thirdparty/ 目录下(如 thirdparty/openssl)。
  2. 配置 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
    )
    

5. 使用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)

方式 4:系统库查找(find_package

步骤

  1. 确保库已安装

    • 第三方库需在系统中安装(如通过 NDK 或包管理器安装)。
  2. 配置 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)
    

方式 5:自动下载编译(ExternalProject_Add

步骤

  1. 配置 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)
    

关键配置说明

  1. 头文件路径

    include_directories(  # 传统方式
        src/main/cpp/include
        thirdparty/include
    )
    
    # 推荐使用 target_include_directories
    target_include_directories(native-lib PRIVATE
        ${CMAKE_SOURCE_DIR}/src/main/cpp/include
    )
    
  2. 动态库路径的动态化

    • 使用 ${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
      )
      
  3. 依赖传递性

    • 如果第三方库依赖其他库(如 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
      

总结:依赖方式对比

  • 源码依赖:适用于三方库的源代码已经包含在项目目录中,并且有CMake配置。
  • 预编译库依赖:适用于三方库已经预先编译成.so.a文件。
  • FetchContent:适用于从远程位置获取并自动构建三方库。
  • 手动指定源文件:适用于简单的三方库,直接将源文件添加到工程中。
  • include_directories:适用于需要引入三方库的头文件。
    | 方式 | 是否需要源码 | 适用场景 | 优点 | 缺点 |
    |------------------------|--------------|-----------------------------------|-------------------------------|-------------------------------|
    | 预编译动态库(.so) | 不需要 | 第三方提供预编译动态库 | 快速集成,无需编译 | 需确保 ABI 兼容性 |
    | 预编译静态库(.a) | 不需要 | 第三方提供静态库 | 静态链接,无依赖传递问题 | 文件体积较大 |
    | 源码编译(add_subdirectory) | 需要 | 需自定义编译或库未提供预编译文件 | 灵活配置,支持修改源码 | 需处理交叉编译及依赖 |
    | 系统库(find_package) | 不需要 | 系统已安装且提供 CMake 配置文件 | 自动化配置,简洁 | 依赖系统环境 |
    | 自动下载(ExternalProject) | 需要 | 需自动管理源码下载和编译 | 自动化流程,便于版本控制 | 构建时间较长 |

通过以上方法,可以根据第三方库的提供形式和项目需求,灵活选择最合适的依赖方式。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值