是否有 GCC pragma 指令可以停止、暂停或中止编译过程?
我正在使用 GCC 4.1,但我希望该编译指示也可以在 GCC 3.x 版本中使用。
您可能想要
#error
:
$ cd /tmp
$ g++ -Wall -DGoOn -o stopthis stopthis.cpp
$ ./stopthis
Hello, world
$ g++ -Wall -o stopthis stopthis.cpp
stopthis.cpp:7:6: error: #error I had enough
#include <iostream>
int main(void) {
std::cout << "Hello, world\n";
#ifndef GoOn
#error I had enough
#endif
return 0;
}
我不知道
#pragma
,但是#error
应该做你想做的事:
#error Failing compilation
它将终止编译并显示错误消息“编译失败”。
这有效:
#include <stophere>
GCC 在找不到包含文件时停止。如果不支持 C++14,我希望 GCC 停止。
#if __cplusplus<201300L
#error need g++14
#include <stophere>
#endif
虽然通常
#error
就足够了(并且可移植),但有时您想要使用 pragma
,即当您想要选择在宏内引发错误时。
这是一个示例使用,取决于 C11 的
_Generic
和 _Pragma
。
此示例确保
var
不是 int *
或 short *
,但在编译时不是 const int *
。
示例:
#define MACRO(var) do { \
(void)_Generic(var, \
int *: 0, \
short *: 0, \
const int *: 0 _Pragma("GCC error \"const not allowed\"")); \
\
MACRO_BODY(var); \
} while (0)
#pragma GCC error "error message"
参考:7 指令
您可以使用:
#pragma GCC error "my message"
但这不是标准。
另一种方法是使用
static_assert
:
#if defined(_MSC_VER) && _MSC_VER < 1916
static_assert(false, "MSVC supported versions are 1916 and later");
#endif
正如一些人指出的,在没有解释为什么的情况下,
#error
不会立即停止编译。我认为为什么值得一些解释。
如果我们参考#error
的行为是“导致实现生成包含指定的预处理标记序列的诊断消息。”4 #error
处理指令的预处理翻译单元,除非它是通过条件包含跳过的组的一部分”。
#error
的实际实现取决于编译器。为了使实现保持一致,“必须”做的是生成诊断消息并且不成功翻译翻译单元。 GCC 两者都做到了,因此它的
#error
实现是一致的。
标准未指定实现是否立即停止编译。
如果我们查看 gcc,我们可以编译以下文件,error.c
#error Error
void f(int a) {
*a = 12;
}
$ gcc -c error.c -o /dev/null
error.c:1:2: error: #error Error
1 | #error Error
| ^~~~~
error.c: In function ‘f’:
error.c:4:3: error: invalid type argument of unary ‘*’ (have ‘int’)
4 | *a = 12;
| ^~
GCC 发出两个错误,其中一个在
#error
之后。显然,gcc并没有立即停止编译。Mosh
的
This回答提供了一种立即停止编译的解决方法:包括不存在的标头。这被认为是一个“致命”错误(如“这个”答案中指出的),并且 gcc 在遇到致命错误时将立即停止编译。
#error
生成的错误不是致命的,因此允许 gcc 以任何它想要的方式继续处理输入。
要将 #error
变成即时编译停止,我们可以遵循相同的答案,只需将 -Wfatal-errors
添加到命令行,以便 gcc 在遇到任何类型的错误时立即停止。$ gcc -c error.c -Wfatal-errors -o /dev/null
error.c:1:2: error: #error Error
1 | #error Error
| ^~~~~
compilation terminated due to -Wfatal-errors.
请注意,
-Wfatal-errors
仅适用于 GCC 4.x 及以上版本。对于 GCC 3.x 及更早版本,包含不存在标头的 mosh 解决方案仍然是最佳解决方案。总的来说,mosh 的解决方案巧妙地解决了这个问题:它适用于所有版本的 GCC,并且不会将每个错误都变成立即停止。