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

【CMake】message函数

目录

一.message函数

1.1.不带任何mode(默认NOTICE)

1.2.STATUS

1.3.WARNING

1.4.SEND_ERROR

1.5.FATAL_ERROR


一.message函数

大家可以去官网看看:message — CMake 4.1.1 Documentation

事实上,message函数最常见的就是下面这种形式

message([STATUS|WARNING|AUTHOR_WARNING|FATAL_ERROR|SEND_ERROR] "要打印的内容" ...)

1.1.不带任何mode(默认NOTICE)

不带任何模式的 message 命令是 CMake 中最基础的消息输出形式。

该命令将指定的文本内容直接记录到日志中,其基本语法为

message("message text" ...)

当提供多个消息字符串时,它们会被自动连接成一个单独的字符串,中间不添加任何分隔符。

这些消息没有任何自动添加的前缀,如 STATUS 模式的 "-- " 或 WARNING 模式的 "CMake Warning:",完全按照用户提供的文本内容原样输出。

话不多说,我们直接来看例子

CMakeLists.txt

cmake_minimum_required(VERSION 3.15)
project(PrintVarDemo LANGUAGES CXX)message("你好,")
message("CMake.")set(MY_NAME "流云")
message("我的名字是:${MY_NAME}")

我们来构建一下

mkdir build && cd build && cmake ..


事实上呢!!在 CMake 中,命令 message 在不显式指定模式参数时,其行为等同于使用 NOTICE 模式。

也就是说

message("text")

等价于

message(NOTICE "text")

我们可以去修改一下我们上面那个CMakeLists.txt即可

cmake_minimum_required(VERSION 3.15)
project(PrintVarDemo LANGUAGES CXX)message(NOTICE "你好,")
message(NOTICE "CMake.")set(MY_NAME "流云")
message(NOTICE "我的名字是:${MY_NAME}")

是不是一模一样的啊!!!

1.2.STATUS

示例一

我们直接来看我们自己写的例子,首先我们的整个项目的结构是下面这样子的

cmake_minimum_required(VERSION 3.10)
project(MessageStatus)message(STATUS "这是一个状态提示:正在配置项目...")

接下来我们来构建项目

mkdir build && cd build && cmake ..

大家看到了吗,这个message打印的东西前面有两条杠(也就是"--“),这个是STATUS的特点哦!

大家可能疑惑,这玩意和NOTICE模式有什么区别呢?

其实还是有一点区别的

  • 所有通过无模式 message 命令输出的信息都会被发送到标准错误流(stderr)
  • 所有通过 STATUS 模式 message 命令输出的信息都会被发送到标准输出流(stdout)

我们可以看个例子


📂 项目结构

MsgDemo/
└── CMakeLists.txt

📄 CMakeLists.txt

cmake_minimum_required(VERSION 3.15)
project(MsgDemo)# 无 mode(等同于 NOTICE,输出到 stderr)
message("这是无模式 message(NOTICE),输出到 stderr")# 显式 STATUS,输出到 stdout
message(STATUS "这是 STATUS message,输出到 stdout")

🛠️ 运行方法

mkdir build && cd build# 把 stdout 和 stderr 分别重定向到不同文件
cmake .. >log.txt 2>err.txt

我们看看这两个文件里面的内容

cat log.txt

输出示例:

我们看看另外一个

cat err.txt

输出示例:


这样就能很直观地看到:

  • STATUS → stdout

  • 无 mode(NOTICE) → stderr

1.3.WARNING

用于向用户输出一个警告(Warning)信息。其核心目的是:提醒用户某个潜在的问题、非理想的情况或已弃用的用法,但允许配置和生成过程继续执行

它就像一个“黄灯”,告诉用户“请注意,但你可以继续前进”。

1. 输出目的地和格式

  • 目的地: 输出到 标准错误 (stderr)。这与 STATUS(输出到 stdout)有根本区别。

  • 前缀和格式: 消息会以显眼的 CMake Warning: 为前缀。此外,CMake 会自动附上文件名和行号,极大地方便了用户定位问题代码。

  • 颜色高亮: 在许多终端中,警告信息会以黄色或红色等醒目的颜色显示,以吸引用户注意。

  • 示例

    # 在 CMakeLists.txt 的第 10 行
    message(WARNING "This is a custom warning message.")

    输出

    CMake Warning at CMakeLists.txt:10 (message):This is a custom warning message.

2. 设计初衷和用途

WARNING 消息的设计目标是:在不停止流程的前提下,最大限度地引起用户对某个问题的关注

典型用途包括:

  • 功能弃用警告:告知用户某个变量、函数或目标即将被移除,应使用新的替代方案。

  • 兼容性警告:提醒用户当前配置可能导致与其他软件或旧版本的兼容性问题。

  • 非致命的条件检查:当某个条件不满足时,使用回退方案,但警告用户这不是最优配置(例如,找不到首选库,转而使用捆绑的版本)。

  • 可疑的用户输入:检查用户设置的变量值是否在合理范围内,如果不在,则发出警告。

  • 平台或编译器限制:告知用户在特定平台或编译器上,某些功能被禁用或可能无法正常工作。

3. 行为:不会中断过程

这是 WARNING 与 SEND_ERROR 和 FATAL_ERROR 最关键的区别。

  • WARNING: 打印消息,继续正常执行所有后续的配置和生成步骤。

  • SEND_ERROR: 打印消息,继续配置,但跳过生成(不会生成 Makefile 或项目文件)。

  • FATAL_ERROR: 打印消息,立即停止所有处理

4.示例

我们来看看这个目录结构

📂 目录结构

WarningExample/
├── CMakeLists.txt
└── main.cpp

📄 main.cpp

#include <iostream>
int main() {std::cout << "Hello, CMake!" << std::endl;return 0;
}

📄 CMakeLists.txt

cmake_minimum_required(VERSION 3.10)
project(WarningExample)# 输出一个警告,但不会中断配置
message(WARNING "⚠️ 这是一个警告:你没有开启优化选项!")add_executable(hello main.cpp)

其实我们可以一键复制下面这个命令来一键搭建出这个目录结构和文件

mkdir -p WarningExample && \
cat > WarningExample/main.cpp <<'EOF'
#include <iostream>
int main() {std::cout << "Hello, CMake!" << std::endl;return 0;
}
EOFcat > WarningExample/CMakeLists.txt <<'EOF'
cmake_minimum_required(VERSION 3.10)
project(WarningExample)# 输出一个警告,但不会中断配置
message(WARNING "⚠️ 这是一个警告:你没有开启优化选项!")add_executable(hello main.cpp)
EOF

接下来我们就来构建我们的项目

cd WarningExample && \
mkdir build && cd build && \
cmake ..

我们看到这里出现了黄色字体,这就是message的WARNING模式。

接下来我们进行构建

cmake --build .

我们看看当前的build目录

然后项目还是能继续正常生成。

1.4.SEND_ERROR

简要介绍

message(SEND_ERROR) 是 CMake 的 message() 函数的一种特殊模式。它的核心作用是:生成一个错误消息,允许当前配置阶段继续完成,但会阻止生成阶段的进行

为了理解这句话,我们首先要区分 CMake 的两个主要阶段:

  1. 配置阶段 (Configure Stage):

    • CMake 读取并处理你的 CMakeLists.txt 文件。

    • 它评估变量、解析命令、检查编译器、寻找依赖包等。

    • 最终,它会在你的构建目录(通常是 build/)中生成一个本地构建系统(如 Makefile文件等)。

  2. 生成阶段 (Generate Stage):

    • 紧随配置阶段之后。

    • CMake 使用配置阶段收集的所有信息,实际编写出最终的构建系统文件(如 Makefile.sln 等)。

message(SEND_ERROR) 的行为正是围绕这两个阶段设计的。


详细行为解析

当你调用 message(SEND_ERROR “Your error message”) 时,会发生以下事情:

  1. 输出错误信息

    • 消息会以错误的格式打印到终端(通常在 Unix-like 系统上表现为红色文字)。

    • 消息内容会明确包含 “CMake Error” 字样,使其很容易被识别和定位。

  2. 配置阶段继续执行

    • 这是 SEND_ERROR 与 FATAL_ERROR 最关键的区别。

    • CMake 不会在遇到 SEND_ERROR 时立即停止。它会继续处理 CMakeLists.txt 文件中该命令之后的所有内容。

    • 这意味着,在一次配置运行中,你可能会看到多个 SEND_ERROR 消息。

  3. 设置内部错误标志

    • 虽然配置继续了,但 CMake 会记录下“至少发生了一个错误”的状态。

  4. 阻止生成阶段

    • 当配置阶段完全结束后,CMake 会检查错误状态。

    • 如果存在任何 SEND_ERROR(或 FATAL_ERROR),CMake 将跳过生成阶段

    • 它不会创建或更新任何构建系统文件(如 Makefile)。如果你之前已经成功生成过,旧的构建文件依然存在,但它们很可能是基于过时的配置,不应该被使用。

  5. 返回非零退出码

    • 整个过程结束时,CMake 会返回一个非零的退出代码,这对于 CI/CD 流水线或其他脚本化流程来说非常重要,因为它们可以据此判断构建失败。


一个简单的例子

假设我们有如下 CMakeLists.txt 文件:

cmake_minimum_required(VERSION 3.10)
project(MyProject)message(STATUS "This is a status message. Configuration is proceeding...")# 假设我们检查某个必备的依赖项
if (NOT EXISTS "/usr/include/somelib.h")message(SEND_ERROR "Critical library 'somelib' was not found!")
endif()# 即使上面出错了,下面的代码依然会被执行
message(STATUS "This message will still be printed.")
set(SOURCES main.cpp)# 尝试添加一个目标,这也会被执行,但最终不会生成构建系统
add_executable(my_app ${SOURCES})

运行 cmake -B build 后,输出将会是:

-- This is a status message. Configuration is proceeding...
CMake Error at CMakeLists.txt:7 (message):Critical library 'somelib' was not found!
-- This message will still be printed.
-- Configuring incomplete, errors occurred!

你会注意到:

  • 两个 STATUS 消息都打印了。

  • add_executable 命令也被处理了(虽然你看不到直接输出,但 CMake 内部已经知道了 my_app 目标)。

  • 最后,CMake 报告 “Configuring incomplete, errors occurred!”。

  • 查看 build/ 目录,你会发现没有生成 Makefile(或者它没有被更新)。


主要用途

message(SEND_ERROR) 的典型使用场景是:在配置阶段进行条件检查,如果条件不满足就报错,但同时希望收集所有可能的错误,而不是在第一个错误处就停止。

  • 检查必需的编译器标志:检查编译器是否支持某个必需的标志,如果不支持则报错。

  • 验证用户提供的选项:检查用户通过 -D 传递的参数是否有效、是否相互兼容。

  • 寻找强制性依赖:如上例所示,如果项目绝对需要一个第三方库,但没找到,就使用 SEND_ERROR。这比立即 FATAL_ERROR 更好,因为你可以一次性地告诉用户所有缺失的依赖,而不是让他们修复一个,重新运行,再发现下一个,如此反复。


与其他 message() 类型的对比

类型

目的

对流程的影响

STATUS

打印信息性消息,通常用于向用户报告进度。

无。配置和生成照常进行。

WARNING

打印警告消息。警告通常表示有问题,但构建仍可继续。

无。配置和生成照常进行,但会高亮显示警告。

SEND_ERROR

打印错误消息。表示遇到了问题。

配置阶段继续,但生成阶段被跳过。构建无法进行。

FATAL_ERROR

打印错误消息。表示遇到了严重问题。

立即终止整个 CMake 进程(配置和生成都立即停止)。

DEPRECATION

警告用户某个功能已被弃用。

如果 CMAKE_ERROR_DEPRECATED 为 ON,则视为错误;如果 CMAKE_WARN_DEPRECATED 为 ON(默认),则视为警告;否则无输出。

最佳实践和注意事项

  1. 不要滥用SEND_ERROR 应该用于真正的错误条件,即会使后续构建失败的条件。对于可以绕过的可选功能或仅仅是警告,使用 WARNING

  2. 提供清晰的错误信息:错误信息应该明确地指出是什么错了以及用户应该如何修复它。例如,不要只说 “Library not found”,最好说 “LibXYZ not found. Please install the libxyz-dev package or set -DXYZ_ROOT to its installation directory.”

  3. 与 option() 或 set(CACHE) 结合使用:通常,你会先提供一个选项让用户设置路径,如果路径无效,再使用 SEND_ERROR 报错。

  4. 与 find_package() 结合使用:很多 FindXXX.cmake 模块在找不到包时会使用 SEND_ERROR 或 FATAL_ERROR

总结

message(SEND_ERROR) 是 CMake 中一个非常有用的流程控制命令。它就像一个“温和的杀手”:

  • 温和在于:它允许配置阶段完成其工作,让你能一次性看到所有问题,极大提高了调试效率。

  • 杀手在于:它最终会阻止构建系统的生成,确保在有问题的情况下不会进行徒劳的构建。

示例

我们来看看这个目录结构

📂 目录结构

test/
├── CMakeLists.txt
└── main.cpp

📄 main.cpp

#include <iostream>
int main() {std::cout << "Hello, CMake!" << std::endl;return 0;
}

📄 CMakeLists.txt

cmake_minimum_required(VERSION 3.10)
project(SendErrorExample)# 输出一个错误,但配置继续进行
message(SEND_ERROR "❌ 这是一个错误:缺少依赖库 foo")add_executable(hello main.cpp)
message("我是最后一句")

其实我们可以一键复制下面这个命令来一键搭建出这个目录结构和文件

mkdir -p test && \
cat > test/main.cpp <<'EOF'
#include <iostream>
int main() {std::cout << "Hello, CMake!" << std::endl;return 0;
}
EOFcat > test/CMakeLists.txt <<'EOF'
cmake_minimum_required(VERSION 3.10)
project(SendErrorExample)# 输出一个错误,但配置继续进行
message(SEND_ERROR "❌ 这是一个错误:缺少依赖库 foo")add_executable(hello main.cpp)
message("我是最后一句")
EOF

接下来我们就来构建我们的项目

cd test && \
mkdir build && cd build && \
cmake ..

我们看到这里出现了红色字体,并且执行完了整个CMakeLists.txt。

接下来我们进行构建

cmake --build .

我们发现构建不了项目了!!这就是message的SEND_ERROR模式的特别之处。

WARNING和SEND_ERROR模式的区别是:

  • WARNING → 只提示警告,构建继续

  • SEND_ERROR → 报错,但不会立刻中止 CMake 配置,会继续执行完剩余的 CMake 脚本。但是最后生成的 Makefile 是不完整的,无法编译成功

1.5.FATAL_ERROR

1️⃣ FATAL_ERROR 的关键特点

  • 一旦遇到 message(FATAL_ERROR ...),CMake 立即中断,不会再执行后续命令。

  • 配置阶段结束时,只会生成很少的临时文件,不会产生 Makefile


2️⃣ SEND_ERROR 的对比

如果是 SEND_ERROR

  • 会报错,但 CMakeLists.txt 后面的语句会继续执行

  • 但是配置最后依然失败 → 没有可用的 Makefile。

示例1

我们来看看这个目录结构

📂 目录结构

test/
├── CMakeLists.txt
└── main.cpp

📄 main.cpp

#include <iostream>
int main() {std::cout << "Hello, CMake!" << std::endl;return 0;
}

📄 CMakeLists.txt

cmake_minimum_required(VERSION 3.10)
project(FatalErrorExample)# 输出一个致命错误,直接中止配置
message(FATAL_ERROR "💥 致命错误:缺少关键依赖,无法继续!")add_executable(hello main.cpp)
message("我是最后一句")

其实我们可以一键复制下面这个命令来一键搭建出这个目录结构和文件

mkdir -p test && \
cat > test/main.cpp <<'EOF'
#include <iostream>
int main() {std::cout << "Hello, CMake!" << std::endl;return 0;
}
EOFcat > test/CMakeLists.txt <<'EOF'
cmake_minimum_required(VERSION 3.10)
project(FatalErrorExample)# 输出一个致命错误,直接中止配置
message(FATAL_ERROR "💥 致命错误:缺少关键依赖,无法继续!")add_executable(hello main.cpp)
message("我是最后一句")
EOF

接下来我们就来构建我们的项目

cd test && \
mkdir build && cd build && \
cmake ..

我们看到这里出现了红色字体,但是我们发现这里没有打印出我们在CMakeLists.txt里面最后写的message("我是最后一句")。

这就是message的FATAL_ERROR模式的特点——CMake 直接中断,不会继续执行message(FATAL_ERROR……)后面的的语句

接下来我们进行构建

cmake --build .

我们发现构建不了项目了!!这里和SEND_ERROR其实是一样的。

⚠️ 和 SEND_ERROR 的不同:

  • FATAL_ERROR:CMake 直接中断,不会继续执行后面的 add_executable

  • SEND_ERROR:报错,但会继续执行剩下的命令,最后仍然失败。

http://www.dtcms.com/a/365977.html

相关文章:

  • C++对象构造与析构
  • numpy meshgrid 转换成pygimli规则网格
  • cppreference_docs
  • 稳居全球TOP3:鹏辉能源“3+N” 布局,100Ah/50Ah等户储电芯产品筑牢市场优势
  • 【C++】Vector核心实现:类设计到迭代器陷阱
  • MySQL:表的约束上
  • C# 代码中的“熵增”概念
  • 单片机:GPIO、按键、中断、定时器、蜂鸣器
  • 《单链表经典问题全解析:5 大核心题型(移除元素 / 反转 / 找中点 / 合并 / 回文判断)实现与详解》
  • 【面试题】词汇表大小如何选择?
  • PS大神级AI建模技巧!效率翻倍工作流,悄悄收藏!
  • 本地化AI问答:告别云端依赖,用ChromaDB + HuggingFace Transformers 搭建离线RAG检索系统
  • OpenCV的阈值处理
  • ChartView的基本介绍与使用
  • shell编程从0基础--进阶 1
  • 如何高效记单词之:抓住首字母——以find、fund、fond、font为例
  • Linux `epoll` 机制的入口——`epoll_create`函数
  • Java并发编程中的CountDownLatch与CompletableFuture:同步与异步的完美搭档
  • 驱动增长的双引擎:付费搜索与自然搜索的终极平衡策略
  • Loot模板系统
  • helm应该安装在哪些节点
  • ABAQUS多尺度纤维增强混凝土二维建模
  • 微信小程序-day3
  • 【mac】macOS上的实用Log用法
  • 使用Navicat去批量传输数据库的表结构
  • fastlio配置与过程中遇到的问题
  • 51单片机----LED与数码管模块
  • C 语言标准输入输出库:`stdio.h` 的使用详解
  • 【WPS】WPSPPT 快速抠背景
  • Python学习笔记--使用Django修改和删除数据