CMake 使用教程 (四)

news2024/12/25 23:38:24

1.0 日志

在 CMake 中可以用用户显示一条消息,该命令的名字为 message:

message([STATUS|WARNING|AUTHOR_WARNING|FATAL_ERROR|SEND_ERROR] "message to display" ...)
  • (无) :重要消息
  • STATUS :非重要消息
  • WARNING:CMake 警告,会继续执行
  • AUTHOR_WARNING:CMake 警告 (dev), 会继续执行
  • SEND_ERROR:CMake 错误,继续执行,但是会跳过生成的步骤
  • FATAL_ERROR:CMake 错误,终止所有处理过程

CMake 的命令行工具会在 stdout 上显示 STATUS 消息,在 stderr 上显示其他所有消息。CMake 的 GUI 会在它的 log 区域显示所有消息。
CMake 警告和错误消息的文本显示使用的是一种简单的标记语言。文本没有缩进,超过长度的行会回卷,段落之间以新行做为分隔符。

# 输出一般日志信息
message(STATUS "source path: ${PROJECT_SOURCE_DIR}")
# 输出警告信息
message(WARNING "source path: ${PROJECT_SOURCE_DIR}")
# 输出错误信息
message(FATAL_ERROR "source path: ${PROJECT_SOURCE_DIR}")

1.1 变量操作

1.1.1 追加

有时候项目中的源文件并不一定都在同一个目录中,但是这些源文件最终却需要一起进行编译来生成最终的可执行文件或者库文件。如果我们通过 file 命令对各个目录下的源文件进行搜索,最后还需要做一个字符串拼接的操作,关于字符串拼接可以使用 set 命令也可以使用 list 命令。
使用 set 拼接
如果使用 set 进行字符串拼接,对应的命令格式如下:

set(变量名1 ${变量名1} ${变量名2} ...)

关于上面的命令其实就是将从第二个参数开始往后所有的字符串进行拼接,最后将结果存储到第一个参数中,如果第一个参数中原来有数据会对原数据就行覆盖。

cmake_minimum_required(VERSION 3.0)
project(TEST)
set(TEMP "hello,world")
file(GLOB SRC_1 ${PROJECT_SOURCE_DIR}/src1/*.cpp)
file(GLOB SRC_2 ${PROJECT_SOURCE_DIR}/src2/*.cpp)
# 追加(拼接)
set(SRC_1 ${SRC_1} ${SRC_2} ${TEMP})
message(STATUS "message: ${SRC_1}")


使用 list 拼接
如果使用 list 进行字符串拼接,对应的命令格式如下:

list(APPEND <list> [<element> ...])

list 命令的功能比 set 要强大,字符串拼接只是它的其中一个功能,所以需要在它第一个参数的位置指定出我们要做的操作,APPEND 表示进行数据追加,后边的参数和 set 就一样了。

cmake_minimum_required(VERSION 3.0)
project(TEST)
set(TEMP "hello,world")
file(GLOB SRC_1 ${PROJECT_SOURCE_DIR}/src1/*.cpp)
file(GLOB SRC_2 ${PROJECT_SOURCE_DIR}/src2/*.cpp)
# 追加(拼接)
list(APPEND SRC_1 ${SRC_1} ${SRC_2} ${TEMP})
message(STATUS "message: ${SRC_1}")

在 CMake 中,使用 set 命令可以创建一个 list。一个在 list 内部是一个由分号; 分割的一组字符串。例如,set(var a b c d e) 命令将会创建一个 list:a;b;c;d;e,但是最终打印变量值的时候得到的是 abcde。

set(tmp1 a;b;c;d;e)
set(tmp2 a b c d e)
message(${tmp1})
message(${tmp2})

输出的结果:

abcde
abcde

1.1.2 字符串移除

我们在通过 file 搜索某个目录就得到了该目录下所有的源文件,但是其中有些源文件并不是我们所需要的,比如:

$ tree
.
├── add.cpp
├── div.cpp
├── main.cpp
├── mult.cpp
└── sub.cpp

0 directories, 5 files

在当前这么目录有五个源文件,其中 main.cpp 是一个测试文件。如果我们想要把计算器相关的源文件生成一个动态库给别人使用,那么只需要 add.cpp、div.cp、mult.cpp、sub.cpp 这四个源文件就可以了。此时,就需要将 main.cpp 从搜索到的数据中剔除出去,想要实现这个功能,也可以使用 list

list(REMOVE_ITEM <list> <value> [<value> ...])

通过上面的命令原型可以看到删除和追加数据类似,只不过是第一个参数变成了 REMOVE_ITEM

cmake_minimum_required(VERSION 3.0)
project(TEST)
set(TEMP "hello,world")
file(GLOB SRC_1 ${PROJECT_SOURCE_DIR}/*.cpp)
# 移除前日志
message(STATUS "message: ${SRC_1}")
# 移除 main.cpp
list(REMOVE_ITEM SRC_1 ${PROJECT_SOURCE_DIR}/main.cpp)
# 移除后日志
message(STATUS "message: ${SRC_1}")

可以看到,在第8行把将要移除的文件的名字指定给 list 就可以了。但是一定要注意通过 file 命令搜索源文件的时候得到的是文件的绝对路径(在 list 中每个文件对应的路径都是一个 item,并且都是绝对路径),那么在移除的时候也要将该文件的绝对路径指定出来才可以,否是移除操作不会成功。

1.2 宏定义

在进行程序测试的时候,我们可以在代码中添加一些宏定义,通过这些宏来控制这些代码是否生效,如下所示:

#include <stdio.h>
#define NUMBER  3

int main()
{
    int a = 10;
#ifdef DEBUG
    printf("我是一个程序猿, 我不会爬树...\n");
#endif
    for(int i=0; i<NUMBER; ++i)
    {
        printf("hello, GCC!!!\n");
    }
    return 0;
}

在程序的第七行对 DEBUG 宏进行了判断,如果该宏被定义了,那么第八行就会进行日志输出,如果没有定义这个宏,第八行就相当于被注释掉了,因此最终无法看到日志输入出(上述代码中并没有定义这个宏)。

为了让测试更灵活,我们可以不在代码中定义这个宏,而是在测试的时候去把它定义出来,其中一种方式就是在 gcc/g++ 命令中去指定,如下:

 gcc test.c -DDEBUG -o app

在 gcc/g++ 命令中通过参数 -D 指定出要定义的宏的名字,这样就相当于在代码中定义了一个宏,其名字为 DEBUG。
在 CMake 中我们也可以做类似的事情,对应的命令叫做 add_definitions:

add_definitions(-D宏名称)

针对于上面的源文件编写一个 CMakeLists.txt,内容如下:

cmake_minimum_required(VERSION 3.0)
project(TEST)
# 自定义 DEBUG 宏
add_definitions(-DDEBUG)
add_executable(app ./test.c)

通过这种方式,上述代码中的第八行日志就能够被输出出来了。

1.3. 预定义宏

下面的列表中为大家整理了一些 CMake 中常用的宏:
在这里插入图片描述

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

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

相关文章

51从零开始学Java之详解Java中的包装类

作者&#xff1a;孙玉昌&#xff0c;昵称【一一哥】&#xff0c;另外【壹壹哥】也是我哦 千锋教育高级教研员、CSDN博客专家、万粉博主、阿里云专家博主、掘金优质作者 前言 在上一篇文章中&#xff0c;壹哥给大家介绍了Java中的Object类&#xff0c;它属于我们开发时的常用类…

2023(WAIC)智能驾驶科技峰会丨拓数派大模型下的数据计算系统,助力汽车智能化产业数据增值

2023 智能驾驶科技峰会在上海圆满落幕&#xff0c;本次大会由世界人工智能大会&#xff08;WAIC&#xff09;组委会办公室指导&#xff0c;浦东新区人民政府支持&#xff0c;浦东新区科技和经济委员会、中国 &#xff08;上海&#xff09;自由贸易试验区管理委员会金桥管理局主…

【SAP-ABAP】RPR_ABAP_SOURCE_SCAN 搜索带特定字符串的程序

昨日问了懒神&#xff0c;才知道还有这功能&#xff0c;真好用 业务背景&#xff1a;需要查找系统中有哪些程序带了特定的字符串&#xff08;一般类似于某些条件写死了&#xff09; 程序&#xff1a;RPR_ABAP_SOURCE_SCAN 程序&#xff1a;RS_ABAP_SOURCE_SCAN SE38执行程序…

Blazor前后端框架Known功能介绍:系统安装激活及自定义

本章介绍系统安装与激活及其自定义功能。 概述 框架内置简单的系统安装功能。录入企业编码、名称、系统名称、产品密钥、管理员密码信息完成安装。可自定义高级安装功能&#xff0c;如安装数据库等您产品所需的安装信息。框架默认无需注册产品密钥&#xff0c;若产品需要安装…

【腾讯云IM】即时通讯的登录,登出,用户列表,私聊,图片发送

uniapp即时通讯 1&#xff0c;初始化&#xff08;刚开始就紧跟着文档走&#xff09;2&#xff0c;App.vue中项目引入腾讯云&#xff0c;&#xff08;附上账号在其他地方登陆的监听&#xff09;3&#xff0c;登录前必需3.1&#xff0c;获取登录id3.2&#xff0c;生成userSig&…

K8s 内存泄漏处理方法

问题描述&#xff1a; 1. 安装go环境 2. 下载地址: https://golang.google.cn/dl/[rootk8s-master home]# rm -rf /usr/local/go && tar -C /usr/local/ -zxvf go1.17.3.linux-amd64.tar.gz3. 永久配置go 环境[rootk8s-master home]# vim /etc/profile export GOPATH…

win10、mac如何使用desktop中的docker

1、安装相应系统的docker&#xff0c;安装完什么都不需要修改。 2、需要安装mysql的话首先使用命令行 3、需要把mysql等其他软件端口映射出来使用的命令 4、搞定&#xff1b;点击关闭和启动 可以安装很多软件哦&#xff0c;非常方便两条命令搞定&#xff0c;mysql、redis、mogo…

建筑物防雷工程的设计与施工

本文会介绍建筑物防雷工程的设计与施工的基本原理、方法和要求&#xff0c;以及一些典型的案例分析。建筑物防雷工程是为了保护建筑物及其内部设备、人员和财产免受雷电危害而采取的一系列技术措施。建筑物防雷工程应遵循《建筑物防雷设计规范》GB 50057-2010和《建筑物防雷工程…

ros2 机器人imu传感器 加速度计 陀螺仪精度和数据填充单位换算

起因&#xff0c;imu解算出了加速度 角速度&#xff0c;但原始数据是没有单位的&#xff0c;只是在一个精度范围的值&#xff0c;要使用这些数据&#xff0c;就需要把这些没有单位的数据换算成带单位的数据&#xff0c;下面解说一下换算原理。 imu读取数据代码参考上期的博客&…

什么是操作系统中的kernel

什么是操作系统中的kernel 一&#xff0c;图解&#xff0c;kernel在操作系统中的结构位置 二&#xff0c;文字描述解释 系统启动后,Kernel会常驻内存,负责系统的基础功能, 如进程调度,硬件管理.普通程序就是用户态程序, 在Kernel中的程序叫做内核态程序. 普通程序如果想申请…

经典图像识别卷积神经网络总结记录

这篇博文主要是延续前文系列的总结记录&#xff0c;这里主要是总结汇总日常主流的图像识别模型相关知识内容。 下面对上述列出的卷积神经网络模型进行逐个详细介绍、算法原理分析以及优缺点总结&#xff1a; (1)LeNet-5 算法原理&#xff1a; LeNet-5是最早应用于手写数字识别…

(22)LED灯(外部)

文章目录 前言 22.1 带有I2C连接的RGB LEDs/显示器 22.2 串行连接的设备 22.3 NTF LED的含义 前言 外部 LED 或 LED 显示屏可以通过连接到自动驾驶仪的 I2C 端口&#xff0c;或者在 4.0 及以后的版本中&#xff0c;如果是串行编程的设备&#xff0c;可以通过输出使用 SERV…

【Redis】3、Redis 作为缓存(Redis中的穿透、雪崩、击穿、工具类)

目录 一、什么是缓存二、给业务添加缓存&#xff08;减少数据库访问次数&#xff09;三、给店铺类型查询业务添加缓存(1) 使用 String 类型(2) 使用 List 类型 四、缓存的更新策略(1) 主动更新(2) 最佳实现方案(3) 给查询商铺的缓存添加超时剔除和主动更新的策略① 存缓存&…

mysql 练习---表和表的字段的增删改

环境&#xff1a; 命令&#xff1a; (1)create database Market; (2) create table customers( c_num int(11) primary key auto_increment, c_name varchar(50), c_contact varchar(50), c_city varchar(50), c_birth datetime not null );(3) alter table customers mod…

[github-100天机器学习]day1 data preprocessing-版本问题已修正

https://github.com/LiuChuang0059/100days-ML-code/blob/master/Day1_Data_preprocessing/README.md#step-6-feature-scaling—特征缩放 数据预处理 导入库&#xff1a;numpy包含数学计算函数&#xff0c;pandas用于导入和管理数据集 #!/usr/bin/env python3 # -*- coding: …

flutter 更新分支内容

有三个分支&#xff0c;主分支&#xff0c;A分支&#xff0c;B分支&#xff0c;别人在B分支开发了内容&#xff0c;我在A分支进行开发。别人在B分支提交了代码&#xff0c;让我去拉下来。这时候我就是需要切到B分支&#xff0c;拉代码下来&#xff0c;然后再回到A分支&#xff…

python使用代理ip——案例

python爬虫是指使用Python编写的程序&#xff0c;通过网络爬取信息并提取有效数据。它通过模拟浏览器请求&#xff0c;获取网页数据&#xff0c;并通过解析HTML/XML等文档结构&#xff0c;从中提取数据。 Python爬虫常用的库和工具包括&#xff1a; Requests&#xff1a;用于…

Lightroom Classic 2023(12.4) for Mac

Lightroom Classic是一款图像处理软件&#xff0c;是数字摄影后期制作的重要工具之一。与其他图像处理软件相比&#xff0c; Lightroom Classic具有以下特点&#xff1a; 高效的图像管理&#xff1a;Lightroom Classic提供了强大的图像管理功能&#xff0c;可以轻松导入、整理…

Springboot接口返回参数以及入参RSA加密解密

网上有好多通过aop切面以及自定义的RSA工具类进行加密解密的方法&#xff0c;期中的过程繁琐也不好用&#xff0c;博主研究了一天从网上到了超好用的基于Springboot框架实现的接口RSA加密解密方式&#xff0c;通过rsa-encrypt-body-spring-boot实现了对Spring Boot接口返回值、…