如何在 GCC 和 Xcode 中手动抛出编译器错误
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2994490/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to manually throw a compiler error in GCC and Xcode
提问by coneybeare
In xcode, while compiling apps with gcc, I want to throw compilation time errors if things like NSZombieEnabled is on for a distribution release, thus ensuring that compilation will fail and I won't accidentally do something stupid.
在 xcode 中,在使用 gcc 编译应用程序时,如果诸如 NSZombieEnabled 之类的东西在发行版中启用,我想抛出编译时间错误,从而确保编译会失败并且我不会意外地做一些愚蠢的事情。
I did some googling, but could not figure out how to cause the compiler to bail if a certain condition is met. Surely it must be easy, am I just not finding it?
我做了一些谷歌搜索,但无法弄清楚如果满足某个条件,如何使编译器保释。当然它一定很容易,我只是没有找到它吗?
回答by Mark Rushakoff
Use the #error
directive:
使用的#error
指令:
#if SHOULD_FAIL
#error "bad compiler!"
#endif
int main()
{
return 0;
}
$ gcc a.c -DSHOULD_FAIL=0 # passes fine $ gcc a.c -DSHOULD_FAIL=1 a.c:2:2: error: #error "bad compiler!"
Since NSZombieEnabled
is an environment variable, you'll need to do something clever in your build script to define your macro as zero or one.
由于NSZombieEnabled
是一个环境变量,您需要在构建脚本中做一些聪明的事情来将宏定义为零或一。
Strictly speaking, the #error
directive occurs in the C Preprocessor, not gcc
. But that shouldn't matter in the case you've described.
严格来说,该#error
指令出现在 C 预处理器中,而不是gcc
. 但这在你描述的情况下应该无关紧要。
回答by Joseph Quinsey
A complile-time assert()--a.k.a. static assert--may be helpful. Here is mine, derived mostly from http://www.pixelbeat.org/programming/gcc/static_assert.html:
编译时 assert()——又名静态断言——可能会有所帮助。这是我的,主要来自http://www.pixelbeat.org/programming/gcc/static_assert.html:
/*-----------------------------------------------------------------------------
* Compile-time ASSERT(). Similar to the BOOST_STATIC_ASSERT(). And the C++0x
* static_assert(), which also has a parameter for a useless error message
* (see correction!). Our ASSERT() can be placed anywhere in the code, except:
*
* o In a twice-included header file, without a #ifndef...#endif wrapper.
* o In the middle of a structure definition (or enum definition).
* o In C89 or C90, after a statement. But you can wrap it in braces!
*
* If you want stick something in the middle of a structure definition
* you'll need to use the ugly, three-line construct #if...#error...#endif.
* And if you do do this, the pre-processor has a much more limited idea of
* what a "constant expression" is.
*
* This is a refinement of ideas from the web (www.pixebeat.org is good). It
* is shorter than BOOST. And, I believe, is better than Linus Torvald's
* suggestion for an improved BUILD_BUG_ON(). And the do{...}while(0) wrapper
* you commonly see is totally inapplicable here: it limits permissible
* locations.
*
* The web has many suggestions using arrays with a negative index. But with
* GCC, most of these do not detect a NON-CONSTANT arg (which is easy enough
* to do in error), except for the attractive 'extern int foo[expression]',
* which also gives an 'unused variable' warning (which might be fixable via
* (void)foo). GCC 4.3 apparently has a built-in static_assert(). Update:
* typedef int array[expression] seems also to be good.
*/
#define CONCAT_TOKENS(a, b) a ## b
#define EXPAND_THEN_CONCAT(a,b) CONCAT_TOKENS(a, b)
#define ASSERT(e) enum {EXPAND_THEN_CONCAT(ASSERT_line_,__LINE__) = 1/!!(e)}
But I corrected my opinion about the 'useless' message in C++0x:
但我更正了我对 C++0x 中“无用”消息的看法:
/*-----------------------------------------------------------------------------
* Correction!: The message in static_assert() isn't quite useless, and we've
* added it to ASSERTM(). This is needed for the case where two different
* header files happen by chance to have two ASSERT()'s on the same line, or
* likewise for a source file and a header file.
*
* We could also handle this via __COUNTER__, but this isn't supported by
* the SGI compiler (and is uglier). And we can't use __FILE__, because it
* doesn't usually expand to a valid C token (e.g. it has a dot c or dot h).
*/
#define ASSERTM(e,m) enum{EXPAND_THEN_CONCAT(m##_ASSERT_line_,__LINE__)=1/!!(e)}
Some examples:
一些例子:
/*-----------------------------------------------------------------------------
* Example:
*/
ASSERTM (sizeof (int16) == 2, my_global_header_h);
ASSERTM (sizeof (ord32) == 4, my_global_header_h);
ASSERTM (sizeof (int64) == 8, my_global_header_h);
/*-----------------------------------------------------------------------------
* Equally good, I believe, is the following variant, but it is slightly
* longer (and not used by us at the present time):
*/
#define ASSERTt(e) typedef int EXPAND_THEN_CONCAT(ASSERT_line_,__LINE__)[1-2*!(e)]
回答by fbrereto
NSZombieEnabled
is an environment flag and, to my knowledge, should not affect the resulting binary (though it may affect the speed of the compilation.)
NSZombieEnabled
是一个环境标志,据我所知,不应影响生成的二进制文件(尽管它可能会影响编译速度。)
回答by Dave DeLong
Another interesting thing you can do is manipulate the output of your build script. If you're using a custom build script as part of your build process, you can do something like:
您可以做的另一件有趣的事情是操作构建脚本的输出。如果您在构建过程中使用自定义构建脚本,您可以执行以下操作:
echo "error: this build step failed!"
Or:
或者:
echo "warning: this build step could be potentially faulty"
Those will produce errors or warnings (respectively) that will show up in the build results window. I've used this a couple times, and it's reallyuseful.
这些将产生错误或警告(分别)并显示在构建结果窗口中。我已经用过几次了,它真的很有用。