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

news2025/3/31 12:18:19

在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) | 需要 | 需自动管理源码下载和编译 | 自动化流程,便于版本控制 | 构建时间较长 |

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2323387.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

【redis】持久化之RDB与AOF

在数字世界的脉搏中,数据是流淌的血液,而持久化则是保障系统生命力的核心机制。作为内存数据库的标杆,Redis凭借其高性能特性成为互联网架构的基石,但其「易失性」的天然属性也催生了关键命题:如何在服务重启或故障时保…

Brainstorm绘制功能连接图(matlab)

上篇笔记简单介绍了Brainstorm,本次使用Brainstorm绘制功能连接图。而对于连接矩阵,软件中有几种方法:相关、相干、双变量格兰杰因果关系、相位锁相值、包络相关、相位转移熵。 首先,对数据进行预处理,保存为.set&…

华为HG532路由器RCE漏洞 CVE-2017-17215 复现

华为HG532路由器RCE漏洞 CVE-2017-17215 CVE-Description Huawei HG532 with some customized versions has a remote code execution vulnerability. An authenticated attacker could send malicious packets to port 37215 to launch attacks. Successful exploit could l…

LVS的三种工作模式简述

一、引言 在过去的十几年中,Internet从几个研究机构相连为信息共享的网络发展成为拥有大量应用和服务的全球性网络,它正成为人们生活中不可缺少的 一部分。虽然Internet发展速度很快,但建设和维护大型网络服务依然是一项挑战性的任务&#xf…

使用 Layers 扩展你的 Nuxt4 应用

面对一个臃肿的页面或项目,你会如何简化重构、扩展它? 当单个 Vue 文件中界面/业务足够多时,通常我们会把它拆分成多个 components 或 composables 来引入,以此来减少此文件复杂度和增加可维护性。 当一个项目的界面/业务逻辑足…

Excel处理控件Aspose.Cells指南:如何在不使用 Microsoft Excel 的情况下解锁 Excel 工作表

Microsoft Excel 允许用户使用密码保护工作表,以防止未经授权的更改。但是,在某些情况下,您可能需要在不使用 Microsoft Excel 的情况下解锁 Excel 工作表。在本指南中,我们将探讨解锁 Excel 工作表的不同方法,例如使用…

进军场景智能体,云迹机器人又快了一步

(图片来源:Pixels) 2025年,AI和机器人行业都发生了巨大改变。 数科星球原创 作者丨苑晶 编辑丨大兔 2025年,酒店行业正掀起一股批量采购具备AI功能的软硬一体解决方案的热潮。 在DeepSeek、Manus等国产AI软件的推动…

PHP 应用SQL 注入符号拼接请求方法HTTP 头JSON编码类

#PHP-MYSQL- 数据请求类型 SQL 语句由于在黑盒中是无法预知写法的, SQL 注入能发成功是需要拼接原 SQL 语句, 大部分黑盒能做的就是分析后各种尝试去判断,所以有可能有注入但可能出现无法注入成 功的情况。究其原因大部分都是原 SQL …

【React】基础版React + Redux实现教程,自定义redux库,Redux Toolkit教程

本项目是一个在react中,使用 redux 管理状态的基础版实现教程,用简单的案例练习redux的使用,旨在帮助学习 redux 的状态管理机制,包括 store、action、reducer、dispatch 等核心概念。 项目地址:https://github.com/Yv…

23种设计模式-适配器(Adapter)设计模式

适配器设计模式 🚩什么是适配器设计模式?🚩适配器设计模式的特点🚩适配器设计模式的结构🚩适配器设计模式的优缺点🚩适配器设计模式的Java实现🚩代码总结🚩总结 🚩什么是…

debug 笔记:llama 3.2 部署bug 之cutlassF: no kernel found to launch!

1 问题描述 按照官方的写法 import torch from transformers import pipeline import os os.environ["HF_TOKEN"] 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 model_id "meta-llama/Llama-3.2-3B"pipe pipeline("text-generation", modelmode…

TCP的长连接和短连接,以及它们分别适用于什么场合

TCP长连接与短连接详解 一、核心概念对比 特性长连接(Persistent Connection)短连接(Short-lived Connection)连接生命周期一次建立后长期保持,多次数据交互复用同一连接每次数据交互均需新建连接,完成后…

【操作系统】(五)操作系统引导(Boot)

视频参考:王道计算机2.了解计算机的启动过程和主引导扇区,让你的计算机从这里起飞吧_哔哩哔哩_bilibili 操作系统引导(Boot)就是在开机的时候,如何让操作系统运行起来? 主存分成RAM小部分ROM,其中ROM里面存放的是BIOS&#xff08…

蓝桥与力扣刷题(蓝桥 山)

题目:这天小明正在学数数。 他突然发现有些止整数的形状像一挫 “山”, 比㓚 123565321、145541123565321、145541, 它 们左右对称 (回文) 且数位上的数字先单调不减, 后单调不增。 小朋数了衣久也没有数完, 他惒让你告诉他在区间 [2022,2022222022] 中有 多少个数…

场馆预约小程序的设计与实现

摘 要 时代在进步,人们对日常生活质量的要求不再受限于衣食住行。现代人不仅想要一个健康的身体,还想拥有一身宛如黄金比例的身材。但是人们平常除了上下班和上下学的时间,其余空余时间寥寥无几,所以我们需要用体育场馆预约来节省…

Pytorch学习笔记(十二)Learning PyTorch - NLP from Scratch

这篇博客瞄准的是 pytorch 官方教程中 Learning PyTorch 章节的 NLP from Scratch 部分。 官网链接:https://pytorch.org/tutorials/intermediate/nlp_from_scratch_index.html 完整网盘链接: https://pan.baidu.com/s/1L9PVZ-KRDGVER-AJnXOvlQ?pwdaa2m 提取码: …

Axure项目实战:智慧运输平台后台管理端-母版、登录(文本框高级交互)

亲爱的小伙伴,在您浏览之前,烦请关注一下,在此深表感谢! 课程主题:智慧运输平台后台管理端 主要内容:母版、登录页制作 应用场景:母版、登录、注册、密码找回 案例展示: 案例视频…

时序数据库 InfluxDB(一)

时序数据库 InfluxDB(一) 数据库种类有很多,比如传统的关系型数据库 RDBMS( 如 MySQL ),NoSQL 数据库( 如 MongoDB ),Key-Value 类型( 如 redis &#xff09…

java开发环境本地全套

文章目录 1、jdk下载安装1.1、下载地址:1.2、安装1.3、验证 2、maven下载安装2.1、下载地址2.2、安装2.3、验证 3、git下载。3.1、下载地址 4、ideal下载5、dbeaver下载 1、jdk下载安装 1.1、下载地址: https://www.oracle.com/java/technologies/down…

华为配置篇-ISIS基础实验

ISIS 一、简述二、常用命令总结三、实验 一、简述 一、基本定义与历史背景 IS-IS(Intermediate System to Intermediate System,中间系统到中间系统)是一种链路状态路由协议,最初由ISO设计用于OSI(开放系统互联&#…