如何获取C源文件中包含的所有头文件列表?
我尝试用Python来解析文件,使用了#include
。我还试着用sed
命令来匹配模式。但这两种方法得到的数据都很乱。例如,如果在某个注释里有/* #include "header.h" */
,我也会把这些行提取出来。请问怎么才能避免这种情况呢?
6 个回答
我使用的是re模块,其中有Match和Search这两个函数。Search可以在字符串的任何位置找到文本,而Match则是从字符串的开头开始查找。
如果你的编译器支持 -E
(或者类似的选项),那么像下面这样的做法可能会对你有帮助:
cc -E myprogram.c | grep '^# 1 '
-E
这个选项的意思是只运行预处理阶段,并显示结果。
这种方法的一个好处是,你可以像正常编译那样,包含任何重要的 -I
和 -D
命令行选项,这样就能捕捉到这些选项可能带来的行为变化。
一旦你开始考虑一些复杂的情况,比如
/* #include <header.h> */
你很快就会发现,自己写一个依赖提取器已经不太实际了。
比如考虑这些情况:
#define PLUGIN "my_extension.h"
#include PLUGIN
#ifdef WITH_CURSES
# include <curses.h>
#endif
你可以无限地继续列下去。如果想要正确处理这些情况,你最终会需要实现一个完整的预处理器。
我不知道你想用生成的文件列表做什么,但一个常见的情况是确定一个编译单元依赖哪些文件,比如用来生成makefile。大多数编译器都提供了特别的支持。在GCC中,可以使用-M
这个选项。
main.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.h、gamma.h、delta.h和epsilon.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支持一个叫做-H
的选项。假设我们有一个源文件叫hw.c
:
#include <stdio.h>
int main(void) { puts("Hello world"); return 0; }
在Mac OS X 10.9.4上,使用GCC 4.8.1版本:
$ 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
$
你有没有想过用像 pycparser 这样的工具来解析C语言文件?虽然这可能对你的问题来说有点复杂,但它确实提供了更多高级的解析选项。