【问题标题】:How to get list of all header files included in C source file? [duplicate]如何获取 C 源文件中包含的所有头文件的列表? [复制]
【发布时间】:2014-09-10 05:52:52
【问题描述】:

我曾尝试通过 Python 使用 #include 解析文件。我尝试使用sed 命令匹配模式。这两种方式我都会得到垃圾数据。例如,如果在某些评论中我有 /* #include "header.h" */ 我也会得到这些行。如何避免这种情况?

【问题讨论】:

  • 您可以发布您尝试过的代码吗?
  • 到目前为止你有没有试过的代码!!
  • 我试过了:sed -nr \'/#include/p\' file.c

标签: python c parsing


【解决方案1】:

GCC 支持-H 选项。考虑源文件hw.c

#include <stdio.h>
int main(void) { puts("Hello world"); return 0; }

在带有 GCC 4.8.1 的 Mac OS X 10.9.4 上:

$ gcc -H -c hw.c
. /usr/include/stdio.h
.. /usr/include/sys/cdefs.h
... /usr/include/sys/_symbol_aliasing.h
... /usr/include/sys/_posix_availability.h
.. /usr/include/Availability.h
... /usr/include/AvailabilityInternal.h
.. /usr/include/_types.h
... /usr/include/sys/_types.h
.... /usr/include/machine/_types.h
..... /usr/include/i386/_types.h
.. /usr/include/sys/_types/_va_list.h
.. /usr/include/sys/_types/_size_t.h
.. /usr/include/sys/_types/_null.h
.. /usr/include/sys/_types/_off_t.h
.. /usr/include/sys/_types/_ssize_t.h
.. /usr/include/secure/_stdio.h
... /usr/include/secure/_common.h
Multiple include guards may be useful for:
/usr/include/secure/_stdio.h
/usr/include/sys/_posix_availability.h
/usr/include/sys/_symbol_aliasing.h
$

【讨论】:

  • +1 这是最简单的方法。一些新知识。
【解决方案2】:

一旦你开始考虑像

这样的不平凡的案例
/* #include <header.h> */

您很快就会达到编写自己的依赖项提取器不再实际的地步。

考虑以下示例:

#define PLUGIN "my_extension.h"
#include PLUGIN

#ifdef WITH_CURSES
#  include <curses.h>
#endif

您可以无限期地继续该列表。如果你想正确处理所有这些,你最终会实现一个完整的预处理器。

我不知道你想对生成的苍蝇列表做什么,但常见的情况是确定编译单元依赖于哪些文件,例如生成 makefile。大多数编译器都为此提供了特殊支持。在 GCC 中,它是 -M 选项。

ma​​in.c

#include <alpha.h>

/* #include <beta.h> */

#ifdef PLUGIN
#include PLUGIN
#endif

#if WITH_DELTA
#include <delta.h>
#endif

alpha.h

#include <epsilon.h>

beta.hgamma.hdelta.hepsilon.h 为空(或者,至少不是#include 任何东西)。

$ gcc -I. -M main.c
main.o: main.c /usr/include/stdc-predef.h alpha.h epsilon.h

$ gcc -I. -DPLUGIN='<gamma.h>' -M main.c
main.o: main.c /usr/include/stdc-predef.h alpha.h epsilon.h gamma.h

$ gcc -I. -DWITH_DELTA=1 -M main.c
main.o: main.c /usr/include/stdc-predef.h alpha.h epsilon.h delta.h

即使您最终并未尝试生成 makefile,解析预处理器的输出也将比您自己浏览源文件容易很多

【讨论】:

  • 我尝试使用 GCC 的 -M 选项。如果标题与带有源文件的标题不在同一目录中,我会收到错误:没有这样的文件或目录
  • 您必须通过-I 选项将各个目录添加到包含路径中,就像您实际在编译一样。
  • makedepend 帮助我获取头文件
【解决方案3】:

您是否考虑过使用类似 pycparser 的东西来解析 C 文件?对于您的问题来说,这可能有点矫枉过正,但它确实允许更高级的解析选项。

【讨论】:

  • re 模块搜索#includes 的所有匹配项。问题是当评论是多行时,如果我得到 ex 的垃圾值,我将无法过滤多行 cmets。 /*---------------
  • 你能告诉我如何使用pycparser吗?
【解决方案4】:

如果你的编译器支持-E(或类似的)选项,这样的东西可能会有用:

cc -E myprogram.c | grep '^# 1 '

-E 选项表示只运行预处理阶段并显示结果。

此方法的一个优点是您可以像正常编译一样包含任何重要的-I-D 命令行选项,从而捕获可能产生的任何行为变化。

【讨论】:

  • 这将适用于 gcc 和 clang,但您可以使用 -MD-H 以获得更好的效果。
【解决方案5】:

您可以使用 grep 实用程序(Linux、MacOS X):

grep '/^\s*#/' my_file.c

或(用于多文件搜索)

grep '/^\s*#/' *.c

【讨论】:

  • 这似乎根本不起作用......
  • Grep 不理解 \s(除非你使用 gnu grep,即使那样你也需要指定 -P 来启用 Perl 风格的正则表达式)。请改用[[:space:]]。但无论如何,如果假定的 #include/* 评论中,这仍然可能失败。
【解决方案6】:

我使用带有匹配和搜索功能的 re 模块。搜索将在字符串中找到任何文本,而匹配从字符串的开头开始

【讨论】:

  • re 模块搜索#includes 的所有匹配项。问题是当评论是多行时,如果我得到 ex 的垃圾值,我将无法过滤多行 cmets。 /*--------------- #include 东西 ---------*/
  • 你是对的,我在考虑每行匹配。不解析整个文件你觉得怎么做?
  • 我需要使用一些编译器或任何开源解析器的工具
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-14
  • 2011-11-23
  • 1970-01-01
  • 1970-01-01
  • 2011-01-11
  • 2013-04-10
相关资源
最近更新 更多