【问题标题】:GCC dump preprocessor definesGCC 转储预处理器定义
【发布时间】:2011-01-14 12:35:11
【问题描述】:

gcc/g++ 有没有办法从命令行转储其预处理器定义? 我的意思是__GNUC____STDC__ 等。

【问题讨论】:

    标签: gcc g++ c-preprocessor


    【解决方案1】:

    是的,使用-E -dM 选项而不是-c。 示例(将它们输出到标准输出):

     gcc -dM -E - < /dev/null
    

    对于 C++

     g++ -dM -E -x c++ - < /dev/null
    

    来自gcc manual

    不是正常输出,而是生成 所有的“#define”指令列表 期间定义的宏 预处理器的执行, 包括预定义的宏。这 给你一种方法来找出什么是 在您的版本中预定义 预处理器。假设你没有 文件 foo.h,命令

    touch foo.h; cpp -dM foo.h
    

    将显示所有预定义的宏。

    如果您使用 -dM 而没有 -E 选项, -dM 被解释为 -fdump-rtl-mach 的同义词。

    【讨论】:

    • gcc 存在于 /dev/null 无意义的系统上。
    • @Pavel 然后你可以使用一个空文件,或者使用 gcc 或者预处理器 - cpp。
    • 我添加了一种更便携的方法作为替代答案:echo | gcc -dM -E - 也适用于 Windows。
    • 是否可以确定这些定义来自哪里(即在哪个文件中)?
    • 另外,在 Windows 上,cpp -dM -E - &lt; NUL 也可以使用。
    【解决方案2】:

    我通常这样做:

    $ 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
    

    【讨论】:

      【解决方案3】:

      迟到的答案 - 我发现其他答案很有用 - 并想补充一点。


      如何转储来自特定头文件的预处理器宏?

      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
      $ 
      

      【讨论】:

      • 您可以使用-include 编译器选项来避免管道
      【解决方案4】:

      简单的方法 (gcc -dM -E - &lt; /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: command line option ‘-std=c++11’ is valid for C++/ObjC++ but not for C

      因为(非 C++)gcc 将从不支持“模板别名”(参见 http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2258.pdf),您必须添加 -x c++ 选项以强制调用 C++ 编译器(Credits for using -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
      

      注意到当使用-std=c++11 调用时,g++ 4.9.1 确实支持“模板别名”。

      【讨论】:

      • 您不必使用虚拟文件。 GCC 支持 -x 参数,所以 g++ -x c++ -dM -E -std=c++11 - &lt; /dev/null | grep cpp 应该可以工作。
      • @yuyichao 谢谢,这样更容易使用。我不知道 -x 选项。支持您的评论并将其整合到原始答案中。
      【解决方案5】:

      在 Linux 或 Windows(没有 /dev/null 的情况下)上同样适用的可移植方法:

      echo | gcc -dM -E -
      

      对于 c++,您可以使用(将 c++11 替换为您使用的任何版本):

      echo | gcc -x c++ -std=c++11 -dM -E -
      

      它通过告诉 gcc 预处理 stdin(由 echo 产生)和 print all preprocessor defines(搜索 -dletters)来工作。如果您想知道在包含头文件时添加了哪些定义,您可以使用类似于 -dM 但不包含预定义宏的-dD 选项:

      echo "#include <stdlib.h>" | gcc -x c++ -std=c++11 -dD -E -
      

      但是请注意,空输入仍然会产生大量带有 -dD 选项的定义。

      【讨论】:

      • @rubenvb 这无关紧要。关键是让 cmd 行至少在 Windows 和 unix 上同样有效。如果你使用NUL,你又回到了第一点:它不会在没有它的系统上工作。
      • 为 C++ 添加完整答案,适用于 Windows 和 Linux(尽管 sort 的行为略有不同):echo | gcc -x c++ -std=c++17 -dM -E - | sort
      • 这会在 git-bash 中产生空输出。
      • @LennartRolland 它有 gcc 吗?在我的 git-bash 中,我无法运行 gcc
      • @pavel 我使用的是 mingw32 gcc,它带有 Windows 的 Qt5 二进制分发版。
      【解决方案6】:

      在构建系统复杂且难以直接获取(或修改)gcc/g++ 命令的大型项目中工作时,还有另一种方法可以查看宏扩展的结果。 只需重新定义宏,您将获得类似于以下的输出:

      file.h: note: this is the location of the previous definition
      #define MACRO current_value
      

      【讨论】:

      • 我正在寻找用于它的警告标志。你知道吗?
      猜你喜欢
      • 2021-11-27
      • 2011-06-06
      • 1970-01-01
      • 2015-02-25
      • 1970-01-01
      • 1970-01-01
      • 2017-06-02
      • 1970-01-01
      相关资源
      最近更新 更多