CMake 脚本命令(Scripting Commands)之find_package

使用find_package引入外部依赖包

本章节通过示例演示Cmake中find_package的用法。

:所有教程均在linux系统下测试通过,如果是windows和mac系统,可能会出现错误,需要自行调试修改

通过Cmake内置模块引入依赖包

为了方便我们在项目中引入外部依赖包,cmake官方为我们预定义了许多寻找依赖包的Module,他们存储在path_to_your_cmake/share/cmake-<version>/Modules目录下。每个以Find.cmake命名的文件都可以帮我们找到一个包。我们也可以在官方文档中查看到哪些库官方已经为我们定义好了,我们可以直接使用find_package函数进行引用官方文档:Find Modules。

我们以curl库为例,假设我们项目需要引入这个库,从网站中请求网页到本地,我们看到官方已经定义好了FindCURL.cmake。所以我们在CMakeLists.txt中可以直接用find_pakcage进行引用。

find_package(CURL)
add_executable(curltest curltest.cc)
if(CURL_FOUND)target_include_directories(clib PRIVATE ${CURL_INCLUDE_DIR})target_link_libraries(curltest ${CURL_LIBRARY})
else()message(FATAL_ERROR ”CURL library not found”)
endif()

对于系统预定义的 Find<LibaryName>.cmake 模块,使用方法一般如上例所示。

每一个模块都会定义以下几个变量

  • <LibaryName>_FOUND
  • <LibaryName>_INCLUDE_DIR or <LibaryName>_INCLUDES
  • <LibaryName>_LIBRARY or <LibaryName>_LIBRARIES

你可以通过<LibaryName>_FOUND 来判断模块是否被找到,如果没有找到,按照工程的需要关闭 某些特性、给出提醒或者中止编译,上面的例子就是报出致命错误并终止构建。 如果<LibaryName>_FOUND 为真,则将<LibaryName>_INCLUDE_DIR 加入 INCLUDE_DIRECTORIES。

通过find_package引入非官方的库(该方式只对支持cmake编译安装的库有效)

假设此时我们需要引入glog库来进行日志的记录,我们在Module目录下并没有找到 FindGlog.cmake。所以我们需要自行安装glog库,再进行引用。

安装

# clone该项目
git clone https://github.com/google/glog.git 
# 切换到需要的版本 
cd glog
git checkout v0.40  # 根据官网的指南进行安装
cmake -H. -Bbuild -G "Unix Makefiles"
cmake --build build
cmake --build build --target install

此时我们便可以通过与引入curl库一样的方式引入glog库了

find_package(glog)
add_executable(glogtest glogtest.cc)
if(GLOG_FOUND)# 由于glog在连接时将头文件直接链接到了库里面,所以这里不用显示调用target_include_directoriestarget_link_libraries(glogtest glog::glog)
else()message(FATAL_ERROR ”glog library not found”)
endif()

Module模式与Config模式

通过上文我们了解了通过Cmake引入依赖库的基本用法。知其然也要知其所以然,find_package对我们来说是一个黑盒子,那么它是具体通过什么方式来查找到我们依赖的库文件的路径的呢。到这里我们就不得不聊到find_package的两种模式,一种是Module模式,也就是我们引入curl库的方式。另一种叫做Config模式,也就是引入glog库的模式。下面我们来详细介绍着两种方式的运行机制。

在Module模式中,cmake需要找到一个叫做Find<LibraryName>.cmake的文件。这个文件负责找到库所在的路径,为我们的项目引入头文件路径和库文件路径。cmake搜索这个文件的路径有两个,一个是上文提到的cmake安装目录下的share/cmake-<version>/Modules目录,另一个使我们指定的CMAKE_MODULE_PATH的所在目录。

如果Module模式搜索失败,没有找到对应的Find<LibraryName>.cmake文件,则转入Config模式进行搜索。它主要通过<LibraryName>Config.cmake or <lower-case-package-name>-config.cmake这两个文件来引入我们需要的库。以我们刚刚安装的glog库为例,在我们安装之后,它在/usr/local/lib/cmake/glog/目录下生成了glog-config.cmake文件,而/usr/local/lib/cmake/<LibraryName>/正是find_package函数的搜索路径之一。(find_package的搜索路径是一系列的集合,而且在linux,windows,mac上都会有所区别,需要的可以参考官方文档find_package)

由以上的例子可以看到,对于原生支持Cmake编译和安装的库通常会安装Config模式的配置文件到对应目录,这个配置文件直接配置了头文件库文件的路径以及各种cmake变量供find_package使用。而对于非由cmake编译的项目,我们通常会编写一个Find<LibraryName>.cmake,通过脚本来获取头文件、库文件等信息。通常,原生支持cmake的项目库安装时会拷贝一份XXXConfig.cmake到系统目录中,因此在没有显式指定搜索路径时也可以顺利找到。

编写自己的Find<LibraryName>.cmake模块

假设我们编写了一个新的函数库,我们希望别的项目可以通过find_package对它进行引用我们应该怎么办呢。

我们在当前目录下新建一个ModuleMode的文件夹,在里面我们编写一个计算两个整数之和的一个简单的函数库。库函数以手工编写Makefile的方式进行安装,库文件安装在/usr/lib目录下,头文件放在/usr/include目录下。其中的Makefile文件如下:

# 1、准备工作,编译方式、目标文件名、依赖库路径的定义。
CC = g++
CFLAGS  := -Wall -O3 -std=c++11 OBJS = libadd.o #.o文件与.cpp文件同名
LIB = libadd.so # 目标文件名
INCLUDE = ./ # 头文件目录
HEADER = libadd.h # 头文件all : $(LIB)# 2. 生成.o文件 
$(OBJS) : libadd.cc$(CC) $(CFLAGS) -I ./ -fpic -c $< -o $@# 3. 生成动态库文件
$(LIB) : $(OBJS)rm -f $@g++ $(OBJS) -shared -o $@ rm -f $(OBJS)# 4. 删除中间过程生成的文件 
clean:rm -f $(OBJS) $(TARGET) $(LIB)# 5.安装文件
install:cp $(LIB) /usr/libcp $(HEADER) /usr/include

编译安装

make
sudo make install

接下来我们回到我们的Cmake项目中来,在cmake文件夹下新建一个FindAdd.cmake的文件。我们的目标是找到库的头文件所在目录和共享库文件的所在位置。

# 在指定目录下寻找头文件和动态库文件的位置,可以指定多个目标路径
find_path(ADD_INCLUDE_DIR libadd.h /usr/include/ /usr/local/include ${CMAKE_SOURCE_DIR}/ModuleMode)
find_library(ADD_LIBRARY NAMES add PATHS /usr/lib/add /usr/local/lib/add ${CMAKE_SOURCE_DIR}/ModuleMode)if(ADD_INCLUDE_DIR AND ADD_LIBRARY)set(ADD_FOUND TRUE)
endif()

这时我们便可以像引用curl一样引入我们自定义的库了。

在CMakeLists.txt中添加

# 将项目目录下的cmake文件夹加入到CMAKE_MODULE_PATH中,让find_pakcage能够找到我们自定义的函数库
set(CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake;${CMAKE_MODULE_PATH}")
add_executable(addtest addtest.cc)
find_package(ADD)
if(ADD_FOUND)target_include_directories(addtest PRIVATE ${ADD_INCLUDE_DIR})target_link_libraries(addtest ${ADD_LIBRARY})
else()message(FATAL_ERROR "ADD library not found")
endif()

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

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

相关文章

Todesk与向日葵:哪款远程工具更胜一筹?

在数字化时代&#xff0c;远程工具已成为许多个人和企业不可或缺的一部分。其中&#xff0c;Todesk和向日葵是两款备受瞩目的远程桌面软件。它们各自拥有独特的功能和优势&#xff0c;但究竟哪一款更适合您的需求呢&#xff1f;本文将从稳定性、易用性、价格和安全性等方面对这…

一个H5页面中直接使用React的示例与说明

示例 如题&#xff0c;下面的个简单代码示例—在H5页面中直接使用React <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta name"viewport" content"widthdevice-width, initial-scale1.0&q…

Pytorch从零开始实战21

Pytorch从零开始实战——Pix2Pix理论与实战 本系列来源于365天深度学习训练营 原作者K同学 文章目录 Pytorch从零开始实战——Pix2Pix理论与实战内容介绍数据集加载模型实现开始训练总结 内容介绍 Pix2Pix是一种用于用于图像翻译的通用框架&#xff0c;即图像到图像的转换。…

【数学】【计算几何】1453. 圆形靶内的最大飞镖数量

作者推荐 视频算法专题 本文涉及知识点 数学 计算几何 LeetCoce:1453. 圆形靶内的最大飞镖数量 Alice 向一面非常大的墙上掷出 n 支飞镖。给你一个数组 darts &#xff0c;其中 darts[i] [xi, yi] 表示 Alice 掷出的第 i 支飞镖落在墙上的位置。 Bob 知道墙上所有 n 支飞…

【Maven 加速 下载】使用 | 阿里云 Maven 中央仓库

阿里云 Maven 中央仓库: 是 阿里云云效 提供的公共代理仓库。 优势: 相比于 Maven 中央仓库,下载更快,更稳定。 仓库地址: 仓库名称阿里云仓库地址阿里云仓库地址(老版)源地址centralhttps://maven.aliyun.com/repository/centralhttps://maven.aliyun.com/nexus/content/…

分布式之网关Gateway

Spring Cloud Gateway 1、网关简介 网关作为流量的入口&#xff0c;常用的功能包括路由转发&#xff0c;权限校验&#xff0c;限流等。 2、Gateway简介 Spring Cloud Gateway 是Spring Cloud官方推出的第二代网关框架&#xff0c;定位于取代 Netflix Zuul。相比 Zuul 来说&…

抖音在线点赞任务发布接单运营平台PHP网站源码

源码简介 抖音在线点赞任务发布接单运营平台PHP网站源码 多个支付通道分级会员制度 介绍&#xff1a; 1、三级代理裂变&#xff0c;静态返佣/动态返佣均可设置。&#xff08;烧伤制度&#xff09;。 2、邀请二维码接入防红跳转。 3、自动机器人做任务&#xff0c;任务时间…

【安卓与苹果区别】详细讲解

安卓和苹果 安卓(Android)和苹果(Apple)在移动操作系统和智能手机市场是两个主要的竞争对手。这里的“苹果”指的是苹果公司设计的iOS操作系统以及苹果自己生产的iPhone手机&#xff0c;而“安卓”是指谷歌开发的Android操作系统&#xff0c;它被多个手机制造商用于他们的设备…

软考高级:信息系统分类-业务处理系统(TPS)概念和例题

作者&#xff1a;明明如月学长&#xff0c; CSDN 博客专家&#xff0c;大厂高级 Java 工程师&#xff0c;《性能优化方法论》作者、《解锁大厂思维&#xff1a;剖析《阿里巴巴Java开发手册》》、《再学经典&#xff1a;《Effective Java》独家解析》专栏作者。 热门文章推荐&am…

创新发展,探索智慧园区平台架构设计与实现

随着信息技术的快速发展&#xff0c;智慧园区平台作为集成物联网、大数据、人工智能等技术的综合性服务平台&#xff0c;正逐步成为推动企业数字化转型的重要驱动力。本文将深入探讨智慧园区平台的架构设计思路、关键技术和应用场景&#xff0c;助力读者了解如何打造智慧化、协…

C# 连接neo4j数据库,包括非默认的neo4j默认库

官方文档没找见&#xff0c;自己在源码里面找到的 private string _dbHost "bolt://localhost:7687"; private string _dbUser "neo4j"; private string _dbPassword "******"; private IDriver? _driver;public CQLOperation(string _data…

【微服务-Nacos】Nacos集群的工作原理及集群间数据同步过程

上篇文章我们介绍了Nacos集群的搭建方法及步骤&#xff0c;下面我们来看一下Nacos集群的工作原理&#xff0c;一共有两部分&#xff1a;Leader节点选举及各节点数据同步。 1、Nacos集群中Leader节点是如何产生的 Nacos集群采用了Raft算法实现。它是一种比较简单的选举算法&am…

汽车电子零部件(2):EPS控制器

前言: 这里介绍一个EPS控制器EPS Controller。电动助力转向(EPS)是实现高度自动化驾驶的关键技术,比如博世EPS车型满足小型、中型、跑车以及轻型商用车的要求。EPS有一个控制车辆转向的电机。通过电机,EPS控制和辅助车辆转向,并提供最佳和享受的转向感觉。此外,新一代控…

【MIT 6.S081】2020, 实验记录(8),Lab: locks

目录 Task 1&#xff1a;Memory allocator (moderate)</font>Task 2&#xff1a;Buffer cache (hard)</font> Task 1&#xff1a;Memory allocator (moderate) 这个任务就是练习将一把大锁拆分为多个小锁&#xff0c;同时可以更加深入地理解 memory allocator 运行…

【项目研究】MeetingServer项目小研究

目录 项目研究 【vscode】 unable to connect to github.com-CSDN博客 解决跨域问题 项目截图 websocket-webrtc-chat 项目研究 完整参考 https://github.com/nnn149/MeetingServer C:\Users\duanxiongwen\Downloads\MeetingServer-master\MeetingServer-master meeting.…

边缘计算与物联网的核心 —— 低功耗芯片

一、低功耗芯片 在边缘计算与物联网&#xff08;IoT&#xff09;中&#xff0c;低功耗芯片扮演了至关重要的角色&#xff0c;主要体现在以下几个方面&#xff1a; 延长设备寿命&#xff1a;物联网设备通常需要部署在难以更换电池或不方便进行频繁维护的环境中&#xff0c;比如…

固态硬盘有缓存和没缓存有什么区别

固态硬盘&#xff08;SSD&#xff09;已经成为现代计算机的重要组成部分&#xff0c;它们提供了比传统机械硬盘更快的读写速度&#xff0c;从而显著提升了操作系统的运行速度和应用程序的加载效率。 其中&#xff0c;缓存&#xff08;Cache&#xff09;是固态硬盘中一个重要的…

基于word2vec 和 fast-pytorch-kmeans 的文本聚类实现,利用GPU加速提高聚类速度

文章目录 简介GPU加速 代码实现kmeans聚类结果kmeans 绘图函数相关资料参考 简介 本文使用text2vec模型&#xff0c;把文本转成向量。使用text2vec提供的训练好的模型权重进行文本编码&#xff0c;不重新训练word2vec模型。 直接用训练好的模型权重&#xff0c;方便又快捷 完整…

软考高级:遗留系统演化策略(集成、淘汰、改造、继承)概念和例题

作者&#xff1a;明明如月学长&#xff0c; CSDN 博客专家&#xff0c;大厂高级 Java 工程师&#xff0c;《性能优化方法论》作者、《解锁大厂思维&#xff1a;剖析《阿里巴巴Java开发手册》》、《再学经典&#xff1a;《Effective Java》独家解析》专栏作者。 热门文章推荐&am…

【刷题训练】Leetcode415.字符串相加

字符串相加 题目要求 示例 1&#xff1a; 输入&#xff1a;num1 “11”, num2 “123” 输出&#xff1a;“134” 示例 2&#xff1a; 输入&#xff1a;num1 “456”, num2 “77” 输出&#xff1a;“533” 示例 3&#xff1a; 输入&#xff1a;num1 “0”, num2 “0”…