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启动参数中,可以设置跟内存、垃圾回收相关的一些参数设置,默认情况不做任何设置JVM会工作的很好,但对一些配置很好的Server和具体的应用必须仔细调优才能获得最佳性能。通过设置我们希望达到一些目标: GC的时间足够的小 GC的…...
Leetcode.1567 乘积为正数的最长子数组长度
题目链接 Leetcode.1567 乘积为正数的最长子数组长度 Rating : 1710 题目描述 给你一个整数数组 nums,请你求出乘积为正数的最长子数组的长度。 一个数组的子数组是由原数组中零个或者更多个连续数字组成的数组。 请你返回乘积为正数的最长子数组长度…...
部分库与使用方法总结(自用)
1.tqdm tqdm是Python的进度条库,可以在长循环操作中显示进度提示 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.初始化(构造函数)3.对日期进行天数推算4.比较相关的运算符重载5.前置后置自增或自减6.日期相减与流插入流提取1.日期相减2.重载流插入和流提取3.总结前言 之前介绍了C…...
想成为一名专业黑客,但不知道从哪里学起?我来教你。
成为一名黑客需要学什么? 想成为一名专业黑客,但不知道从哪里学起”很多人在后台问过这个问题,今天就为你介绍成为专业黑客必须学习的十个方面的知识,希望能为迷惘中的你指明方向。 想要成为网络hacker黑客?先来学习…...
VMware ESXi 7.0 U3k Unlocker OEM BIOS 集成网卡驱动和 NVMe 驱动 (集成驱动版)
ESXi 7 U3 标准版集成 Intel 网卡、USB 网卡 和 NVMe 驱动 请访问原文链接:https://sysin.org/blog/vmware-esxi-7-u3-sysin/,查看最新版。原创作品,转载请保留出处。 作者主页:www.sysin.org 本次针对 2023-02-21 发布的 ESXi …...
新的计算方法:预测益生菌在不同生长条件下的相互作用
谷禾健康 益生菌可以产生有益的维生素、消化酶、必需氨基酸、免疫调节和抗菌代谢产物,从而促进人体健康,预防肠道炎症性疾病、自身免疫性疾病和胃肠道感染。其宝贵特性已得到健康行业、医疗专业人士和公众的认可。 比起单菌株益生菌,多菌株益…...
python自学之《21天学通Python》(13)——第16章 数据库编程
数据库指的是以一定方式存储在一起、能为多个用户共享、具有尽可能小的冗余度、与应用程序彼此独立的数据集合。而我们平时所说的数据库实际上是包含了数据库管理系统(DBMS)的,数据库管理系统是为管理数据库而设计的软件系统,它一…...
[架构之路-118]-《软考-系统架构设计师》-软架构设计-11-可靠性相关设计
第11节 可靠性相关设计11.1 可靠性基本概念可靠性工程是研究产品生命周期中故障的发生、发展规律,达到预防故障,消灭故障,提高产品可用性的工程技术。信息系统的可靠性是指系统在满足一定条件的应用环境中能够正常工作的能力,可以…...
电阻串联的作用
电阻串联常见作用 第一个作用是:阻抗匹配: 因为信号源的阻抗很低,跟信号线之间阻抗不匹配,串上一个电阻后,可以改善匹配情况,以减少反射,避免振荡等。 常见的阻抗匹配方法 1、使用变压器来做…...
leetcode 1675. Minimize Deviation in Array(最小化数组偏差)
数组里面有n个正整数,里面的数字可以无限次进行如下操作: 1.偶数可以除以2 2.奇数可以乘以2 数组中任意两元素差的最大值称为偏差。 把数组中的元素进行上面2种操作,使偏差最小。 思路: 数组中现有2种数字,一种是奇数…...
特征向量中心度(eigenvector centrality)算法原理与源码解析
前言 随着图谱应用的普及,图深度学习技术也逐渐被越来越多的数据挖掘团队所青睐。传统机器学习主要是对独立同分布个体的统计学习,而图深度学习则是在此基础上扩展到了非欧式空间的图数据之上,通过借鉴NLP和CV方向的模型思想,衍生…...
Vue3 中组件的使用(上)
目录前言:一、什么是组件二、注册组件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,不需要花费太多的时间,轻松从2D平面图生成3D楼梯模型,生成的楼梯模型细节丰富真实。 【主要功能】 1.简单:轻松实现2D到3D建模。 2.具有最详细三维结构的台阶平面图。 3.楼梯各部件完全参数化…...
OpenShift 简介
OpenShift 是红帽 Red Hat 公司基于开源的云平台,是平台即服务(PaaS),是一种容器应用平台。允许开发人员构建、测试和部署云应用。该系统是在 K8S 核心之上添加工具,从而实现更快的应用开发、部署及扩展。 在 OpenShi…...
netty自定义封包实现
文章目录说明分享内置编码器和解码器解码器编码器代码实现创建核心类消息实体类自定义编码类自定义解码类服务端ServerHandler入口类客户端ClientHandler入口类测试参考总结说明 netty是java重要的企业级NIO,使用它可以快速实现很多功能通信功能如:http、…...
ORA error集锦
1、oralce 数据客户端需要安装的问题 保存信息为: “无法连接到数据库,因为数据库客户端软件无法加载。确保已正确安装并配置数据库客户端软件” 从百度网盘下载,并安装win32 oracle client 安装包 2、ORA错误 “执行异常,ORA-00911: inval…...
格雷码的实现
格雷码:任意两个相邻的二进制数之间只有一位不同 想必通信专业的学生应该都接触过格雷码,它出现在数电、通信原理等课程里。 如下图所示一个四位格雷码是什么样子的: 格雷码的特点: 其最大的特点是任意上下相邻的两个码值间&am…...
应用升级/灾备测试时使用guarantee 闪回点迅速回退
1.场景 应用要升级,当升级失败时,数据库回退到升级前. 要测试系统,测试完成后,数据库要回退到测试前。 相对于RMAN恢复需要很长时间, 数据库闪回只需要几分钟。 2.技术实现 数据库设置 2个db_recovery参数 创建guarantee闪回点,不需要开启数据库闪回。…...
2025年能源电力系统与流体力学国际会议 (EPSFD 2025)
2025年能源电力系统与流体力学国际会议(EPSFD 2025)将于本年度在美丽的杭州盛大召开。作为全球能源、电力系统以及流体力学领域的顶级盛会,EPSFD 2025旨在为来自世界各地的科学家、工程师和研究人员提供一个展示最新研究成果、分享实践经验及…...
【Java学习笔记】Arrays类
Arrays 类 1. 导入包:import java.util.Arrays 2. 常用方法一览表 方法描述Arrays.toString()返回数组的字符串形式Arrays.sort()排序(自然排序和定制排序)Arrays.binarySearch()通过二分搜索法进行查找(前提:数组是…...
Swagger和OpenApi的前世今生
Swagger与OpenAPI的关系演进是API标准化进程中的重要篇章,二者共同塑造了现代RESTful API的开发范式。 本期就扒一扒其技术演进的关键节点与核心逻辑: 🔄 一、起源与初创期:Swagger的诞生(2010-2014) 核心…...
JVM虚拟机:内存结构、垃圾回收、性能优化
1、JVM虚拟机的简介 Java 虚拟机(Java Virtual Machine 简称:JVM)是运行所有 Java 程序的抽象计算机,是 Java 语言的运行环境,实现了 Java 程序的跨平台特性。JVM 屏蔽了与具体操作系统平台相关的信息,使得 Java 程序只需生成在 JVM 上运行的目标代码(字节码),就可以…...
无人机侦测与反制技术的进展与应用
国家电网无人机侦测与反制技术的进展与应用 引言 随着无人机(无人驾驶飞行器,UAV)技术的快速发展,其在商业、娱乐和军事领域的广泛应用带来了新的安全挑战。特别是对于关键基础设施如电力系统,无人机的“黑飞”&…...
免费数学几何作图web平台
光锐软件免费数学工具,maths,数学制图,数学作图,几何作图,几何,AR开发,AR教育,增强现实,软件公司,XR,MR,VR,虚拟仿真,虚拟现实,混合现实,教育科技产品,职业模拟培训,高保真VR场景,结构互动课件,元宇宙http://xaglare.c…...
淘宝扭蛋机小程序系统开发:打造互动性强的购物平台
淘宝扭蛋机小程序系统的开发,旨在打造一个互动性强的购物平台,让用户在购物的同时,能够享受到更多的乐趣和惊喜。 淘宝扭蛋机小程序系统拥有丰富的互动功能。用户可以通过虚拟摇杆操作扭蛋机,实现旋转、抽拉等动作,增…...
Python 训练营打卡 Day 47
注意力热力图可视化 在day 46代码的基础上,对比不同卷积层热力图可视化的结果 import torch import torch.nn as nn import torch.optim as optim from torchvision import datasets, transforms from torch.utils.data import DataLoader import matplotlib.pypl…...
认识CMake并使用CMake构建自己的第一个项目
1.CMake的作用和优势 跨平台支持:CMake支持多种操作系统和编译器,使用同一份构建配置可以在不同的环境中使用 简化配置:通过CMakeLists.txt文件,用户可以定义项目结构、依赖项、编译选项等,无需手动编写复杂的构建脚本…...
