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

CMake模块的使用和自定义模块

CMake模块的使用和自定义模块

  • 一、前言
  • 二、使用Find模块
    • 2.1、准备工作
    • 2.2、添加头文件路径和库文件
    • 2.3、< name >_FOUND 来控制工程特性
  • 三、编写自定义的Find模块
    • 3.1、 准备工作
    • 3.2、cmake 模块
    • 3.3、使用自定义的FindHELLO 模块构建工程
    • 3.4、如果没有找到hello library
  • 四、总结

一、前言

本文将着重介绍系统预定义的Find 模块的使用以及自己编写Find 模块,系统中提供了其他各种模块,一般情况需要使用INCLUDE 指令显式的调用,FIND_PACKAGE 指令是一个特例,可以直接调用预定义的模块。

其实使用纯粹依靠cmake 本身提供的基本指令来管理工程是一件非常复杂的事情,所以, cmake 设计成了可扩展的架构,可以通过编写一些通用的模块来扩展cmake.

本文首先介绍一下cmake 提供的 FindCURL 模块的使用。然后,基于共享库编写一个FindHello.cmake 模块。

二、使用Find模块

FIND_PACKAGE 指令:

FIND_PACKAGE(<name> [major.minor] [QUIET] [NO_MODULE]
[[REQUIRED|COMPONENTS] [componets...]])

可以使用多种参数,QUIET 参数,REQUIRED 参数,其含义是指这个共享库是否是工程必须的,如果使用了这个参数,说明这个链接库是必备库,如果找不到这个链接库,则工程不能编译。

2.1、准备工作

(1)建立 t5 目录,用于存放我们的CURL 的例子。

mkdir t5

(2)建立src 目录,并建立src/main.c

cd t5
mkdir src
cd src
vim main.c

内容如下:

#include <curl/curl.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
FILE *fp = NULL;
int write_data(void *ptr, size_t size, size_t nmemb, void *stream) {int written = fwrite(ptr, size, nmemb, (FILE *)fp);return written;
}
int main(void) {const char * path = "/tmp/curl-test";const char * mode = "w";fp = fopen(path, mode);curl_global_init(CURL_GLOBAL_ALL);CURL *curl = curl_easy_init();curl_easy_setopt(curl, CURLOPT_URL, "http://www.baidu.com");curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, write_data);curl_easy_setopt(curl, CURLOPT_VERBOSE, 1);CURLcode res = curl_easy_perform(curl);curl_easy_cleanup(curl);return 0;
}

这段代码的作用是通过curl 取回http://www.linux-ren.org 的首页并写入/tmp/curl-test文件中。

(3)建立主工程文件CMakeLists.txt。

cd t5
vim CMakeLists.txt

内容如下:

PROJECT(CURLTEST)
ADD_SUBDIRECTORY(src)

(4)建立src/CMakeLists.txt,内容如下:

ADD_EXECUTABLE(curltest main.c)

现在自然是没办法编译的,我们需要添加 curl 的头文件路径和库文件。

2.2、添加头文件路径和库文件

(1)方法1:

直接通过INCLUDE_DIRECTORIES 和TARGET_LINK_LIBRARIES 指令添加:我们可以直接在src/CMakeLists.txt 中添加:

INCLUDE_DIRECTORIES(/usr/include) 
TARGET_LINK_LIBRARIES(curltest curl)

然后建立build 目录进行外部构建即可。

(2)方法2,使用FindCURL 模块。

现在是使用cmake 提供的 FindCURL 模块,向 src/CMakeLists.txt 中添加:

FIND_PACKAGE(CURL)
IF(CURL_FOUND)
INCLUDE_DIRECTORIES(${CURL_INCLUDE_DIR})
TARGET_LINK_LIBRARIES(curltest ${CURL_LIBRARY})
ELSE(CURL_FOUND)
MESSAGE(FATAL_ERROR ”CURL library not found”)
ENDIF(CURL_FOUND)

对于系统预定义的Find.cmake 模块,使用方法一般如上例所示。每一个模块都会定义以下几个变量

<name>_FOUND
<name>_INCLUDE_DIR or <name>_INCLUDES
<name>_LIBRARY or <name>_LIBRARIES

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

如果< name>_FOUND 为真,则将< name>_INCLUDE_DIR 加入INCLUDE_DIRECTORIES,将< name >_LIBRARY 加入 TARGET_LINK_LIBRARIES 中。

然后建立build 目录进行外部构建:

mkdir build
cd build
cmake ..

如果库不存在,则会报错【CMake Error at src/CMakeLists.txt:7 (MESSAGE): CURL library not found】:

-- The C compiler identification is GNU 8.4.0
-- The CXX compiler identification is GNU 8.4.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /usr/bin/cc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Detecting CXX compiler ABI info
-- Detecting CXX compiler ABI info - done
-- Check for working CXX compiler: /usr/bin/c++ - skipped
-- Detecting CXX compile features
-- Detecting CXX compile features - done
-- Could NOT find CURL (missing: CURL_LIBRARY CURL_INCLUDE_DIR) 
CMake Error at src/CMakeLists.txt:7 (MESSAGE):CURL library not foundCMake Warning (dev) in CMakeLists.txt:No cmake_minimum_required command is present.  A line of code such ascmake_minimum_required(VERSION 3.21)should be added at the top of the file.  The version specified may be lowerif you wish to support older CMake versions for this project.  For moreinformation run "cmake --help-policy CMP0000".
This warning is for project developers.  Use -Wno-dev to suppress it.-- Configuring incomplete, errors occurred!
See also "/home/fly/workspace/cmakeProj/t5/build/CMakeFiles/CMakeOutput.log".

2.3、< name >_FOUND 来控制工程特性

再来看一个复杂的例子,通过_FOUND 来控制工程特性:

SET(mySources viewer.c)
SET(optionalSources)
SET(optionalLibs)
FIND_PACKAGE(JPEG)IF(JPEG_FOUND)
SET(optionalSources ${optionalSources} jpegview.c)
INCLUDE_DIRECTORIES( ${JPEG_INCLUDE_DIR} )
SET(optionalLibs ${optionalLibs} ${JPEG_LIBRARIES} )
ADD_DEFINITIONS(-DENABLE_JPEG_SUPPORT)
ENDIF(JPEG_FOUND)IF(PNG_FOUND)
SET(optionalSources ${optionalSources} pngview.c)
INCLUDE_DIRECTORIES( ${PNG_INCLUDE_DIR} )
SET(optionalLibs ${optionalLibs} ${PNG_LIBRARIES} )
ADD_DEFINITIONS(-DENABLE_PNG_SUPPORT)
ENDIF(PNG_FOUND)ADD_EXECUTABLE(viewer ${mySources} ${optionalSources} ) TARGET_LINK_LIBRARIES(viewer ${optionalLibs}

通过判断系统是否提供了JPEG 库来决定程序是否支持JPEG 功能。

三、编写自定义的Find模块

3.1、 准备工作

编写属于自己的FindHello 模块。

(1)建立cmake/中建立t6 目录,并在其中建立cmake 目录用于存放我们自己定义的FindHELLO.cmake 模块。同时建立src 目录,用于存放我们的源文件。

mkdir t6
cd t6
mkdir cmake
mkdir src

(2)定义 cmake/FindHELLO.cmake 模块。

FIND_PATH(HELLO_INCLUDE_DIR hello.h /usr/include/hello /usr/local/include/hello)
FIND_LIBRARY(HELLO_LIBRARY NAMES hello PATH /usr/lib /usr/local/lib)IF (HELLO_INCLUDE_DIR AND HELLO_LIBRARY)SET(HELLO_FOUND TRUE)
ENDIF (HELLO_INCLUDE_DIR AND HELLO_LIBRARY)IF (HELLO_FOUND) IF (NOT HELLO_FIND_QUIETLY)MESSAGE(STATUS "Found Hello: ${HELLO_LIBRARY}")ENDIF (NOT HELLO_FIND_QUIETLY)
ELSE (HELLO_FOUND)IF (HELLO_FIND_REQUIRED)MESSAGE(FATAL_ERROR "Could not find hello library")ENDIF (HELLO_FIND_REQUIRED)
ENDIF (HELLO_FOUND)

可以使用多种参数,QUIET 参数,对应与我们编写的 FindHELLO 中的 HELLO_FIND_QUIETLY,如果不指定这个参数,就会执行:

MESSAGE(STATUS "Found Hello: ${HELLO_LIBRARY}")

REQUIRED 参数,其含义是指这个共享库是否是工程必须的,如果使用了这个参数,说明这个链接库是必备库,如果找不到这个链接库,则工程不能编译。对应于 FindHELLO.cmake 模块中的HELLO_FIND_REQUIRED 变量。

在上面的模块中定义了HELLO_FOUND, HELLO_INCLUDE_DIR,HELLO_LIBRARY 变量供开发者在FIND_PACKAGE 指令中使用。

3.2、cmake 模块

hello的库使用之前文章介绍的示例。

下面建立src/main.c,内容为:

#include <hello.h>
int main()
{HelloFunc();return 0;
} 

建立src/CMakeLists.txt 文件,内容如下:

FIND_PACKAGE(HELLO)
IF(HELLO_FOUND)
ADD_EXECUTABLE(hello main.c)
INCLUDE_DIRECTORIES(${HELLO_INCLUDE_DIR})
TARGET_LINK_LIBRARIES(hello ${HELLO_LIBRARY})
ENDIF(HELLO_FOUND)

为了能够让工程找到FindHELLO.cmake 模块(存放在工程中的 cmake 目录),我们在主工程文件CMakeLists.txt 中加入:

SET(CMAKE_MODULE_PATH ${PROJECT_SOURCE_DIR}/cmake)

3.3、使用自定义的FindHELLO 模块构建工程

仍然采用外部编译的方式,建立build 目录,进入目录运行:

mkdir build
cd build
cmake ..

我们可以从输出中看到:

Found Hello: /usr/lib/libhello.so

如果把上面的FIND_PACKAGE(HELLO)修改为FIND_PACKAGE(HELLO QUIET),则不会看到上面的输出。

接下来就可以使用make 命令构建工程,运行:

./src/hello 

可以得到输出:

Hello World

说明工程成功构建。

3.4、如果没有找到hello library

我们可以尝试将/usr/lib/libhello.x 移动到/tmp 目录,这样,按照 FindHELLO 模块的定义,就找不到hello library 了,我们再来看一下构建结果:

cmake ..

仍然可以成功进行构建,但是这时候是没有办法编译的。

修改FIND_PACKAGE(HELLO)为FIND_PACKAGE(HELLO REQUIRED),将hello library 定义为工程必须的共享库。

这时候再次运行cmake …

我们得到如下输出:

CMake Error: Could not find hello library.

因为找不到libhello.x,所以,整个Makefile 生成过程被出错中止。

四、总结

使用系统提供的 Find< NAME>模块并学习编写Find< NAME>模块以及如何在工程中使用这些模块。
在这里插入图片描述

相关文章:

CMake模块的使用和自定义模块

CMake模块的使用和自定义模块一、前言二、使用Find模块2.1、准备工作2.2、添加头文件路径和库文件2.3、< name >_FOUND 来控制工程特性三、编写自定义的Find模块3.1、 准备工作3.2、cmake 模块3.3、使用自定义的FindHELLO 模块构建工程3.4、如果没有找到hello library四、…...

jvm调优参数配置

在JVM启动参数中&#xff0c;可以设置跟内存、垃圾回收相关的一些参数设置&#xff0c;默认情况不做任何设置JVM会工作的很好&#xff0c;但对一些配置很好的Server和具体的应用必须仔细调优才能获得最佳性能。通过设置我们希望达到一些目标&#xff1a; GC的时间足够的小 GC的…...

Leetcode.1567 乘积为正数的最长子数组长度

题目链接 Leetcode.1567 乘积为正数的最长子数组长度 Rating &#xff1a; 1710 题目描述 给你一个整数数组 nums&#xff0c;请你求出乘积为正数的最长子数组的长度。 一个数组的子数组是由原数组中零个或者更多个连续数字组成的数组。 请你返回乘积为正数的最长子数组长度…...

部分库与使用方法总结(自用)

1.tqdm tqdm是Python的进度条库&#xff0c;可以在长循环操作中显示进度提示 tqdm.tqdm:传入数字 from tqdm import tqdm for i in tqdm(range(1, 5)):print(i)使用bar_format "{l_bar}{bar}"可以只显示进度条 from tqdm import tqdm for i in tqdm(range(1, 5), ba…...

C++实现日期类

文章目录前言1.日期类的功能分析1.大致分析2.接口设计2.具体实现1.日期类的成员函数和成员变量2.初始化(构造函数&#xff09;3.对日期进行天数推算4.比较相关的运算符重载5.前置后置自增或自减6.日期相减与流插入流提取1.日期相减2.重载流插入和流提取3.总结前言 之前介绍了C…...

想成为一名专业黑客,但不知道从哪里学起?我来教你。

成为一名黑客需要学什么&#xff1f; 想成为一名专业黑客&#xff0c;但不知道从哪里学起”很多人在后台问过这个问题&#xff0c;今天就为你介绍成为专业黑客必须学习的十个方面的知识&#xff0c;希望能为迷惘中的你指明方向。 想要成为网络hacker黑客&#xff1f;先来学习…...

VMware ESXi 7.0 U3k Unlocker OEM BIOS 集成网卡驱动和 NVMe 驱动 (集成驱动版)

ESXi 7 U3 标准版集成 Intel 网卡、USB 网卡 和 NVMe 驱动 请访问原文链接&#xff1a;https://sysin.org/blog/vmware-esxi-7-u3-sysin/&#xff0c;查看最新版。原创作品&#xff0c;转载请保留出处。 作者主页&#xff1a;www.sysin.org 本次针对 2023-02-21 发布的 ESXi …...

新的计算方法:预测益生菌在不同生长条件下的相互作用

谷禾健康 益生菌可以产生有益的维生素、消化酶、必需氨基酸、免疫调节和抗菌代谢产物&#xff0c;从而促进人体健康&#xff0c;预防肠道炎症性疾病、自身免疫性疾病和胃肠道感染。其宝贵特性已得到健康行业、医疗专业人士和公众的认可。 比起单菌株益生菌&#xff0c;多菌株益…...

python自学之《21天学通Python》(13)——第16章 数据库编程

数据库指的是以一定方式存储在一起、能为多个用户共享、具有尽可能小的冗余度、与应用程序彼此独立的数据集合。而我们平时所说的数据库实际上是包含了数据库管理系统&#xff08;DBMS&#xff09;的&#xff0c;数据库管理系统是为管理数据库而设计的软件系统&#xff0c;它一…...

[架构之路-118]-《软考-系统架构设计师》-软架构设计-11-可靠性相关设计

第11节 可靠性相关设计11.1 可靠性基本概念可靠性工程是研究产品生命周期中故障的发生、发展规律&#xff0c;达到预防故障&#xff0c;消灭故障&#xff0c;提高产品可用性的工程技术。信息系统的可靠性是指系统在满足一定条件的应用环境中能够正常工作的能力&#xff0c;可以…...

电阻串联的作用

电阻串联常见作用 第一个作用是&#xff1a;阻抗匹配&#xff1a; 因为信号源的阻抗很低&#xff0c;跟信号线之间阻抗不匹配&#xff0c;串上一个电阻后&#xff0c;可以改善匹配情况&#xff0c;以减少反射&#xff0c;避免振荡等。 常见的阻抗匹配方法 1、使用变压器来做…...

leetcode 1675. Minimize Deviation in Array(最小化数组偏差)

数组里面有n个正整数&#xff0c;里面的数字可以无限次进行如下操作&#xff1a; 1.偶数可以除以2 2.奇数可以乘以2 数组中任意两元素差的最大值称为偏差。 把数组中的元素进行上面2种操作&#xff0c;使偏差最小。 思路&#xff1a; 数组中现有2种数字&#xff0c;一种是奇数…...

特征向量中心度(eigenvector centrality)算法原理与源码解析

前言 随着图谱应用的普及&#xff0c;图深度学习技术也逐渐被越来越多的数据挖掘团队所青睐。传统机器学习主要是对独立同分布个体的统计学习&#xff0c;而图深度学习则是在此基础上扩展到了非欧式空间的图数据之上&#xff0c;通过借鉴NLP和CV方向的模型思想&#xff0c;衍生…...

Vue3 中组件的使用(上)

目录前言&#xff1a;一、什么是组件二、注册组件1. 全局注册2. 局部注册二、传递数据【父 -> 子】1. 字符串数组的形式2. 对象的形式三、组件事件【子 -> 父】1. 字符串数组式声明自定义事件2. 【子组件】触发组件事件3. 【父组件】监听子组件自定义事件4. 组件事件例子…...

spring-boot、spring-cloud、spring-cloud-alibaba版本对应

一、查询 spring-boot(spring-boot-starter-parent) 版本号 https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-parent 二、查询 spring-cloud(spring-cloud-dependencies) 版本号 https://mvnrepository.com/artifact/org.springframework…...

【沐风老师】3DMAX一键楼梯脚本插件StairGenerator使用教程

3DMAX一键楼梯插件StairGenerator&#xff0c;不需要花费太多的时间&#xff0c;轻松从2D平面图生成3D楼梯模型&#xff0c;生成的楼梯模型细节丰富真实。 【主要功能】 1.简单&#xff1a;轻松实现2D到3D建模。 2.具有最详细三维结构的台阶平面图。 3.楼梯各部件完全参数化…...

OpenShift 简介

OpenShift 是红帽 Red Hat 公司基于开源的云平台&#xff0c;是平台即服务&#xff08;PaaS&#xff09;&#xff0c;是一种容器应用平台。允许开发人员构建、测试和部署云应用。该系统是在 K8S 核心之上添加工具&#xff0c;从而实现更快的应用开发、部署及扩展。 在 OpenShi…...

netty自定义封包实现

文章目录说明分享内置编码器和解码器解码器编码器代码实现创建核心类消息实体类自定义编码类自定义解码类服务端ServerHandler入口类客户端ClientHandler入口类测试参考总结说明 netty是java重要的企业级NIO&#xff0c;使用它可以快速实现很多功能通信功能如&#xff1a;http、…...

ORA error集锦

1、oralce 数据客户端需要安装的问题 保存信息为&#xff1a; “无法连接到数据库&#xff0c;因为数据库客户端软件无法加载。确保已正确安装并配置数据库客户端软件” 从百度网盘下载&#xff0c;并安装win32 oracle client 安装包 2、ORA错误 “执行异常,ORA-00911: inval…...

格雷码的实现

格雷码&#xff1a;任意两个相邻的二进制数之间只有一位不同 想必通信专业的学生应该都接触过格雷码&#xff0c;它出现在数电、通信原理等课程里。 如下图所示一个四位格雷码是什么样子的&#xff1a; 格雷码的特点&#xff1a; 其最大的特点是任意上下相邻的两个码值间&am…...

利用ngx_stream_return_module构建简易 TCP/UDP 响应网关

一、模块概述 ngx_stream_return_module 提供了一个极简的指令&#xff1a; return <value>;在收到客户端连接后&#xff0c;立即将 <value> 写回并关闭连接。<value> 支持内嵌文本和内置变量&#xff08;如 $time_iso8601、$remote_addr 等&#xff09;&a…...

Java-41 深入浅出 Spring - 声明式事务的支持 事务配置 XML模式 XML+注解模式

点一下关注吧&#xff01;&#xff01;&#xff01;非常感谢&#xff01;&#xff01;持续更新&#xff01;&#xff01;&#xff01; &#x1f680; AI篇持续更新中&#xff01;&#xff08;长期更新&#xff09; 目前2025年06月05日更新到&#xff1a; AI炼丹日志-28 - Aud…...

ElasticSearch搜索引擎之倒排索引及其底层算法

文章目录 一、搜索引擎1、什么是搜索引擎?2、搜索引擎的分类3、常用的搜索引擎4、搜索引擎的特点二、倒排索引1、简介2、为什么倒排索引不用B+树1.创建时间长,文件大。2.其次,树深,IO次数可怕。3.索引可能会失效。4.精准度差。三. 倒排索引四、算法1、Term Index的算法2、 …...

GitHub 趋势日报 (2025年06月08日)

&#x1f4ca; 由 TrendForge 系统生成 | &#x1f310; https://trendforge.devlive.org/ &#x1f310; 本日报中的项目描述已自动翻译为中文 &#x1f4c8; 今日获星趋势图 今日获星趋势图 884 cognee 566 dify 414 HumanSystemOptimization 414 omni-tools 321 note-gen …...

C# SqlSugar:依赖注入与仓储模式实践

C# SqlSugar&#xff1a;依赖注入与仓储模式实践 在 C# 的应用开发中&#xff0c;数据库操作是必不可少的环节。为了让数据访问层更加简洁、高效且易于维护&#xff0c;许多开发者会选择成熟的 ORM&#xff08;对象关系映射&#xff09;框架&#xff0c;SqlSugar 就是其中备受…...

Python基于历史模拟方法实现投资组合风险管理的VaR与ES模型项目实战

说明&#xff1a;这是一个机器学习实战项目&#xff08;附带数据代码文档&#xff09;&#xff0c;如需数据代码文档可以直接到文章最后关注获取。 1.项目背景 在金融市场日益复杂和波动加剧的背景下&#xff0c;风险管理成为金融机构和个人投资者关注的核心议题之一。VaR&…...

纯 Java 项目(非 SpringBoot)集成 Mybatis-Plus 和 Mybatis-Plus-Join

纯 Java 项目&#xff08;非 SpringBoot&#xff09;集成 Mybatis-Plus 和 Mybatis-Plus-Join 1、依赖1.1、依赖版本1.2、pom.xml 2、代码2.1、SqlSession 构造器2.2、MybatisPlus代码生成器2.3、获取 config.yml 配置2.3.1、config.yml2.3.2、项目配置类 2.4、ftl 模板2.4.1、…...

Web中间件--tomcat学习

Web中间件–tomcat Java虚拟机详解 什么是JAVA虚拟机 Java虚拟机是一个抽象的计算机&#xff0c;它可以执行Java字节码。Java虚拟机是Java平台的一部分&#xff0c;Java平台由Java语言、Java API和Java虚拟机组成。Java虚拟机的主要作用是将Java字节码转换为机器代码&#x…...

【LeetCode】算法详解#6 ---除自身以外数组的乘积

1.题目介绍 给定一个整数数组 nums&#xff0c;返回 数组 answer &#xff0c;其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法&#xff0c;且在 O…...

算法打卡第18天

从中序与后序遍历序列构造二叉树 (力扣106题) 给定两个整数数组 inorder 和 postorder &#xff0c;其中 inorder 是二叉树的中序遍历&#xff0c; postorder 是同一棵树的后序遍历&#xff0c;请你构造并返回这颗 二叉树 。 示例 1: 输入&#xff1a;inorder [9,3,15,20,7…...