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

江苏艾立泰跨国资源接力:废料变黄金的绿色供应链革命
在华东塑料包装行业面临限塑令深度调整的背景下,江苏艾立泰以一场跨国资源接力的创新实践,重新定义了绿色供应链的边界。 跨国回收网络:废料变黄金的全球棋局 艾立泰在欧洲、东南亚建立再生塑料回收点,将海外废弃包装箱通过标准…...

MySQL 8.0 OCP 英文题库解析(十三)
Oracle 为庆祝 MySQL 30 周年,截止到 2025.07.31 之前。所有人均可以免费考取原价245美元的MySQL OCP 认证。 从今天开始,将英文题库免费公布出来,并进行解析,帮助大家在一个月之内轻松通过OCP认证。 本期公布试题111~120 试题1…...

使用 SymPy 进行向量和矩阵的高级操作
在科学计算和工程领域,向量和矩阵操作是解决问题的核心技能之一。Python 的 SymPy 库提供了强大的符号计算功能,能够高效地处理向量和矩阵的各种操作。本文将深入探讨如何使用 SymPy 进行向量和矩阵的创建、合并以及维度拓展等操作,并通过具体…...
Oracle11g安装包
Oracle 11g安装包 适用于windows系统,64位 下载路径 oracle 11g 安装包...
go 里面的指针
指针 在 Go 中,指针(pointer)是一个变量的内存地址,就像 C 语言那样: a : 10 p : &a // p 是一个指向 a 的指针 fmt.Println(*p) // 输出 10,通过指针解引用• &a 表示获取变量 a 的地址 p 表示…...
32单片机——基本定时器
STM32F103有众多的定时器,其中包括2个基本定时器(TIM6和TIM7)、4个通用定时器(TIM2~TIM5)、2个高级控制定时器(TIM1和TIM8),这些定时器彼此完全独立,不共享任何资源 1、定…...

CTF show 数学不及格
拿到题目先查一下壳,看一下信息 发现是一个ELF文件,64位的 用IDA Pro 64 打开这个文件 然后点击F5进行伪代码转换 可以看到有五个if判断,第一个argc ! 5这个判断并没有起太大作用,主要是下面四个if判断 根据题目…...

大模型——基于Docker+DeepSeek+Dify :搭建企业级本地私有化知识库超详细教程
基于Docker+DeepSeek+Dify :搭建企业级本地私有化知识库超详细教程 下载安装Docker Docker官网:https://www.docker.com/ 自定义Docker安装路径 Docker默认安装在C盘,大小大概2.9G,做这行最忌讳的就是安装软件全装C盘,所以我调整了下安装路径。 新建安装目录:E:\MyS…...

【技巧】dify前端源代码修改第一弹-增加tab页
回到目录 【技巧】dify前端源代码修改第一弹-增加tab页 尝试修改dify的前端源代码,在知识库增加一个tab页"HELLO WORLD",完成后的效果如下 [gif01] 1. 前端代码进入调试模式 参考 【部署】win10的wsl环境下启动dify的web前端服务 启动调试…...

AWSLambda之设置时区
目标 希望Lambda运行的时区是东八区。 解决 只需要设置lambda的环境变量TZ为东八区时区即可,即Asia/Shanghai。 参考 使用 Lambda 环境变量...