是否有一种方法可以让gcc/g++从命令行转储其默认的预处理器定义? 我的意思是像__GNUC__, __STDC__,等等。
当前回答
是的,使用-E -dM选项而不是-c。 示例(输出到stdout):
echo | gcc -dM -E -
echo | clang -dM -E -
美国小妞C + +
echo | g++ -dM -E -x c++ -
echo | clang++ -dM -E -x c++ -
来自gcc手册:
而不是正常的输出,生成 所有“#define”指令的列表 过程中定义的宏 预处理器的执行, 包括预定义的宏。这 给你一种方法来找出什么是 的版本中预定义的 预处理器。假设你没有 文件foo.h,命令 触摸foo;cpp -dM foo.h 将显示所有预定义宏。 如果使用-dM而不带-E选项, -dM被解释为-fdump-rtl-mach的同义词。
其他回答
是的,使用-E -dM选项而不是-c。 示例(输出到stdout):
echo | gcc -dM -E -
echo | clang -dM -E -
美国小妞C + +
echo | g++ -dM -E -x c++ -
echo | clang++ -dM -E -x c++ -
来自gcc手册:
而不是正常的输出,生成 所有“#define”指令的列表 过程中定义的宏 预处理器的执行, 包括预定义的宏。这 给你一种方法来找出什么是 的版本中预定义的 预处理器。假设你没有 文件foo.h,命令 触摸foo;cpp -dM foo.h 将显示所有预定义宏。 如果使用-dM而不带-E选项, -dM被解释为-fdump-rtl-mach的同义词。
我通常是这样做的:
$ gcc -dM -E - < /dev/null
请注意,一些预处理器定义依赖于命令行选项——您可以通过向上面的命令行添加相关选项来测试这些定义。例如,要查看哪些SSE3/SSE4选项默认启用:
$ gcc -dM -E - < /dev/null | grep SSE[34]
#define __SSE3__ 1
#define __SSSE3__ 1
然后在指定-msse4时进行比较:
$ gcc -dM -E -msse4 - < /dev/null | grep SSE[34]
#define __SSE3__ 1
#define __SSE4_1__ 1
#define __SSE4_2__ 1
#define __SSSE3__ 1
类似地,你可以看到在两组不同的命令行选项中哪些选项不同,例如比较优化级别的预处理器定义-O0(无)和-O3(满):
$ gcc -dM -E -O0 - < /dev/null > /tmp/O0.txt
$ gcc -dM -E -O3 - < /dev/null > /tmp/O3.txt
$ sdiff -s /tmp/O0.txt /tmp/O3.txt
#define __NO_INLINE__ 1 <
> #define __OPTIMIZE__ 1
当工作在一个具有复杂构建系统的大项目中,并且很难直接获得(或修改)gcc/g++命令时,还有另一种方法可以查看宏扩展的结果。 简单地重新定义宏,你会得到类似如下的输出:
file.h: note: this is the location of the previous definition
#define MACRO current_value
简单的方法(gcc - dm - e - < /dev/null)适用于gcc,但不适用于g++。最近我需要一个c++ 11/ c++ 14特性的测试。对应的宏名称的建议发布在https://isocpp.org/std/standing-documents/sd-6-sg10-feature-test-recommendations上。但是:
g++ -dM -E - < /dev/null | fgrep __cpp_alias_templates
总是失败,因为它会默默地调用c驱动程序(就像被gcc调用一样)。您可以通过将其输出与gcc的输出进行比较,或者通过添加特定于g++的命令行选项(如(-std=c++11))来看到这一点,该选项会发出错误消息cc1: warning:命令行选项' -std=c++11 '对c++ / objc++有效,但对c无效。
因为(非c++) gcc永远不会支持“模板别名”(参见http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2258.pdf),你必须添加-x c++选项来强制调用c++编译器(使用-x c++选项而不是空虚拟文件的功劳请访问yuyichao,见下文):
g++ -dM -E -x c++ /dev/null | fgrep __cpp_alias_templates
不会有输出,因为g++(修订版4.9.1,默认为-std=gnu++98)默认情况下不启用c++ 11特性。要做到这一点,使用
g++ -dM -E -x c++ -std=c++11 /dev/null | fgrep __cpp_alias_templates
最终会让步
#define __cpp_alias_templates 200704
注意到g++ 4.9.1在使用-std=c++11调用时支持“模板别名”。
晚回答——我发现其他答案很有用——想再补充一点。
如何转储来自特定头文件的预处理器宏?
echo "#include <sys/socket.h>" | gcc -E -dM -
或者(感谢@mymedia的建议):
gcc -E -dM -include sys/socket.h - < /dev/null
特别是,我想知道在我的系统上SOMAXCONN定义为什么。我知道我可以直接打开标准头文件,但有时我必须搜索一下才能找到头文件的位置。相反,我可以使用以下一行代码:
$ gcc -E -dM -include sys/socket.h - < /dev/null | grep SOMAXCONN
#define SOMAXCONN 128
$