当前位置: 首页 > article >正文

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 PROPERTIESIMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/src/main/jniLibs/${ANDROID_ABI}/libssl.so
    )# 添加自己的目标(如共享库)
    add_library(native-lib SHAREDsrc/main/cpp/native-lib.cpp
    )# 链接第三方库和系统库(如 log)
    target_link_libraries(native-libopenssllog  # 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 PROPERTIESIMPORTED_LOCATION ${CMAKE_SOURCE_DIR}/src/main/jniLibs/${ANDROID_ABI}/libpng.a
    )# 链接静态库
    target_link_libraries(native-libpnglog
    )
    

3. 使用FetchContent模块(CMake 3.11+)

如果三方库可以从远程位置(如Git仓库)获取,可以使用FetchContent模块在构建过程中自动下载和构建三方库。

示例:

假设三方库的Git地址为https://github.com/someuser/SomeLibrary.git

# CMakeLists.txt# 启用FetchContent模块
include(FetchContent)# 下载并构建三方库
FetchContent_Declare(SomeLibraryGIT_REPOSITORY https://github.com/someuser/SomeLibrary.gitGIT_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 PRIVATEthird_party/SomeLibrary/src/file1.cppthird_party/SomeLibrary/src/file2.cpp
)
target_include_directories(SomeLibrary PRIVATEthird_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-libopenssl  # 假设第三方库生成的库名为 openssllog
    )
    

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(gtestGIT_REPOSITORY https://github.com/google/googletest.gitCMAKE_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/includethirdparty/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 PROPERTIESIMPORTED_LOCATION ${LIB_DIR}/libpng.so
      )
      
  3. 依赖传递性

    • 如果第三方库依赖其他库(如 libcrypto.so),需逐层导入:
      add_library(crypto SHARED IMPORTED)
      set_target_properties(crypto PROPERTIESIMPORTED_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) | 需要 | 需自动管理源码下载和编译 | 自动化流程,便于版本控制 | 构建时间较长 |

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

相关文章:

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

在Android NDK CMake工程中引入其他C三方库时,有以下几种常见的依赖方式: 1. 源码依赖 如果三方库的源代码包含在你的项目目录中,并且它有自己的CMake配置,可以使用add_subdirectory将三方库的构建过程集成到你的项目中。 示例…...

【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…...

CSS3学习教程,从入门到精通,CSS3 弹性盒子(Flexbox)布局全面指南(20)

CSS3 弹性盒子(Flexbox)布局全面指南 一、Flexbox 概述 Flexbox(弹性盒子)是 CSS3 提供的一种一维布局模型,可以轻松实现各种复杂的页面布局。它特别适合处理不同屏幕尺寸下的元素排列和对齐问题。 主要优势: 简单实现垂直居中…...

Redis 性能数据解读与问题排查优化版

目录标题 Redis 性能数据解读与问题排查优化版一、Redis 性能数据解读二、常见问题排查与解决(一)CPU 使用率高(二)内存使用异常(三)集群状态异常(四)数据库状态问题 三、综合优化建…...

新能源动力电池测试设备深度解析:充放电设备与电池模拟器的差异及技术趋势

一、技术原理对比与核心技术创新 充放电设备 核心原理与硬件架构 充放电设备的核心功能是通过电力电子技术精确控制电池的充放电过程,其硬件架构包括高精度电源模块、双向DC/DC变换器、数据采集系统和温控单元。例如,在放电阶段,设备通过双向…...

LVS的三种工作模式简述

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

Ribbon负载均衡的深度解析与应用

在微服务架构中,服务之间的调用频繁且复杂,因此负载均衡显得尤为重要。Spring Cloud生态系统中,Ribbon作为一个客户端负载均衡器,扮演着关键的角色。它不仅能提高系统的响应速度,还能确保系统的稳定性和可用性。接下来…...

使用 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软件的推动…...

vue 使用v-model实现父子组件传值——子父组件同步更新

基于vue2和vue3两个版本的框架略显不同&#xff0c;所以我分开的来讲&#xff1a; 1、vue2 子组件&#xff08;my-input.vue&#xff09;&#xff1a; <template><input type"text" :value"name" input"inputChange" /> </tem…...

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

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

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

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

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

适配器设计模式 &#x1f6a9;什么是适配器设计模式&#xff1f;&#x1f6a9;适配器设计模式的特点&#x1f6a9;适配器设计模式的结构&#x1f6a9;适配器设计模式的优缺点&#x1f6a9;适配器设计模式的Java实现&#x1f6a9;代码总结&#x1f6a9;总结 &#x1f6a9;什么是…...

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长连接与短连接详解 一、核心概念对比 特性长连接&#xff08;Persistent Connection&#xff09;短连接&#xff08;Short-lived Connection&#xff09;连接生命周期一次建立后长期保持&#xff0c;多次数据交互复用同一连接每次数据交互均需新建连接&#xff0c;完成后…...

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

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

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

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

211数学专业大三想转码C++方向,目前在学算法,没系统学习计算机专业课,要先定方向吗?

今天给大家分享的是一位粉丝的提问&#xff0c;211数学专业大三想转码C方向&#xff0c;目前在学算法&#xff0c;没系统学习计算机专业课&#xff0c;要先定方向吗&#xff1f; 接下来把粉丝的具体提问和我的回复分享给大家&#xff0c;希望也能给一些类似情况的小伙伴一些启…...

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

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

黑苹果及OpenCore Legacy Patcher

黑苹果及OpenCore Legacy Patcher OpenCoreUnable to resolve dependencies, error code 71 OpenCore Unable to resolve dependencies, error code 71 黑苹果升级后打补丁不成功&#xff0c;比如提示以下错误&#xff0c;可参考官方文档进行修复。 Open TerminalType sudo …...

记一个阿里云CDN域名配置不当引起服务鉴权失效问题

背景&#xff1a;公司最近需要通过不同的域名提供给不同角色的用户使用&#xff0c;在阿里云上新增了多个域名&#xff0c;新域名与原域名指向的是一样的服务器地址。 问题现象&#xff1a;用户使用新域名登录后&#xff0c;返回的不是该用户的身份信息&#xff0c;不管是哪个…...

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

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

遗传算法优化支持向量机分类是一种将遗传算法与支持向量机相结合的方法

遗传算法优化支持向量机分类是一种将遗传算法与支持向量机相结合的方法&#xff0c;旨在提高支持向量机的分类性能。以下是其相关内容的详细介绍&#xff1a; 支持向量机&#xff08;SVM&#xff09; 原理&#xff1a;SVM是一种基于统计学习理论的机器学习方法&#xff0c;其…...

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

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

时序数据库 InfluxDB(一)

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

java开发环境本地全套

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

优化 K8s负载平衡之方法(Method for Optimizing K8s Load Balancing)

优化 K8s 负载平衡的 11 种方法 优化 Kubernetes 中的负载平衡对于保持应用程序的高可用性、可扩展性和性能至关重要。有效的负载平衡可确保流量在 Pod 之间高效分配&#xff0c;防止任何单个 Pod 成为瓶颈并确保无缝的用户体验。本指南探讨了优化 Kubernetes 负载平衡的 11 种…...