C - multipass一个源代码到cpp



基本上,我试图传递源代码两次到gcc的cpp,然后直接到gcc的c编译器。

至于为什么,我认为有些东西永远不能在宏中内联。

这里有一个例子:

/* say i want to make an inline definition that can be inserted to any other macros */
#include <stdio.h>
#define DEF_X                 #define X           22
int main(void)
{
    DEF_X
    printf("%u", X);
    return 1;
}

然后简单编译:gcc $MY_DIR/test_multi_pass.c -o $MY_DIR/test.exe

当然,这是行不通的,因为当你编译它时(无论是否在GCC中),它会被预处理,然后直接传递给编译器(至少是官方的):

    # 1 "d:/Projects/Research/tests/test_multi_pass.c"
# 1 "<command-line>"
# 1 "d:/Projects/Research/tests/test_multi_pass.c"
# 1 "c:\mingw\bin\../lib/gcc/mingw32/4.7.2/../../../../include/stdio.h" 1 3
# 19 "c:\mingw\bin\../lib/gcc/mingw32/4.7.2/../../../../include/stdio.h" 3
# 1 "c:\mingw\bin\../lib/gcc/mingw32/4.7.2/../../../../include/_mingw.h" 1 3
# 32 "c:\mingw\bin\../lib/gcc/mingw32/4.7.2/../../../../include/_mingw.h" 3
# 33 "c:\mingw\bin\../lib/gcc/mingw32/4.7.2/../../../../include/_mingw.h" 3
# 20 "c:\mingw\bin\../lib/gcc/mingw32/4.7.2/../../../../include/stdio.h" 2 3
# 1 "c:\mingw\bin\../lib/gcc/mingw32/4.7.2/include/stddef.h" 1 3 4
# 213 "c:\mingw\bin\../lib/gcc/mingw32/4.7.2/include/stddef.h" 3 4
typedef unsigned int size_t;
# 325 "c:\mingw\bin\../lib/gcc/mingw32/4.7.2/include/stddef.h" 3 4
typedef short unsigned int wchar_t;
# 354 "c:\mingw\bin\../lib/gcc/mingw32/4.7.2/include/stddef.h" 3 4
typedef short unsigned int wint_t;
# 27 "c:\mingw\bin\../lib/gcc/mingw32/4.7.2/../../../../include/stdio.h" 2 3
# 1 "c:\mingw\bin\../lib/gcc/mingw32/4.7.2/include/stdarg.h" 1 3 4
# 40 "c:\mingw\bin\../lib/gcc/mingw32/4.7.2/include/stdarg.h" 3 4
typedef __builtin_va_list __gnuc_va_list;
# 29 "c:\mingw\bin\../lib/gcc/mingw32/4.7.2/../../../../include/stdio.h" 2 3
# 129 "c:\mingw\bin\../lib/gcc/mingw32/4.7.2/../../../../include/stdio.h" 3
ETC_ETC_ETC_IGNORED_FOR_BREVITY_BUT_LOTS_OF_DECLARATIONS
int main(void)
{
    #define X 22
    printf("%u", X);
    return 1;
}

现在把重点放在上面预处理文件的最底部。

纯粹地说,就c编译器而言,"#define X 22"不是有效的语法,任何编译器都可能会说有一个"#"。

所以我尝试了一些技巧:

cpp /$MY_DIR/test_multi_pass.c | cpp

,输出为:

    # 1 "<stdin>"
# 1 "<command-line>"
# 1 "<stdin>"
# 1 "d:/Projects/Research/tests/test_multi_pass.c"
# 1 "<command-line>"
# 1 "d:/Projects/Research/tests/test_multi_pass.c"
# 1 "c:\mingw\bin\../lib/gcc/mingw32/4.7.2/../../../../include/stdio.h" 1 3
# 19 "c:\mingw\bin\../lib/gcc/mingw32/4.7.2/../../../../include/stdio.h" 3
# 1 "c:\mingw\bin\../lib/gcc/mingw32/4.7.2/../../../../include/_mingw.h" 1 3
# 32 "c:\mingw\bin\../lib/gcc/mingw32/4.7.2/../../../../include/_mingw.h" 3
# 33 "c:\mingw\bin\../lib/gcc/mingw32/4.7.2/../../../../include/_mingw.h" 3
# 20 "c:\mingw\bin\../lib/gcc/mingw32/4.7.2/../../../../include/stdio.h" 2 3
# 1 "c:\mingw\bin\../lib/gcc/mingw32/4.7.2/include/stddef.h" 1 3 4
# 213 "c:\mingw\bin\../lib/gcc/mingw32/4.7.2/include/stddef.h" 3 4
typedef unsigned int size_t;
# 325 "c:\mingw\bin\../lib/gcc/mingw32/4.7.2/include/stddef.h" 3 4
typedef short unsigned int wchar_t;
# 354 "c:\mingw\bin\../lib/gcc/mingw32/4.7.2/include/stddef.h" 3 4
typedef short unsigned int wint_t;
# 27 "c:\mingw\bin\../lib/gcc/mingw32/4.7.2/../../../../include/stdio.h" 2 3
# 1 "c:\mingw\bin\../lib/gcc/mingw32/4.7.2/include/stdarg.h" 1 3 4
# 40 "c:\mingw\bin\../lib/gcc/mingw32/4.7.2/include/stdarg.h" 3 4
typedef __builtin_va_list __gnuc_va_list;
# 29 "c:\mingw\bin\../lib/gcc/mingw32/4.7.2/../../../../include/stdio.h" 2 3
# 129 "c:\mingw\bin\../lib/gcc/mingw32/4.7.2/../../../../include/stdio.h" 3
ETC_ETC_ETC_IGNORED_FOR_BREVITY_BUT_LOTS_OF_DECLARATIONS
int main(void)
{
    printf("%u", 22);
    return 1;
}

现在它完全完成了我们想要它做的并定义X为22。这并不是我打算在我的代码库中使用的方式(我将把它与#undef等结合起来),但它非常清楚地说明了这种尝试。

then I try:

gcc -o $MY_DIR/test.exe < cpp /$MY_DIR/test_multi_pass.c | cpp

我知道在GCC中,在启动编译后,它由cpp预处理,然后c编译器对代码进行语法解析(将其转换为抽象语法树),然后悄悄地再次调用预处理器以进行所有程序集命名(用于链接器)和诸如此类的操作。

因此,至少在gcc中,代码要经过两次预处理。因此,可能有的机会,前面的文件再次以与下一次预处理迭代相同的格式(希望,如果它不引入更多额外的代码,破坏代码在未来进一步预处理)。

所以也许我们可以预处理它4次(因为我们事先预处理了两次)。因此上面的hack。

但它给出的是:

sh: cpp: No such file or directory
# 1 "<stdin>"
# 1 "<command-line>"
# 1 "<stdin>"

现在,这是cpp无法预处理它4次的根本错误还是我只是输入了错误的CLI命令??

GCC只预处理源代码一次。如果它在构建过程的后期额外调用预处理器,那就无关紧要了,因为它在那个阶段预处理的不是你的源代码;它生成了汇编代码之类的。

如果您想要在实际编译之前在源代码上运行两次预处理器的效果,您可以手动运行一次预处理器,然后在输出上正常运行GCC(这将自动执行另一次预处理器传递)。例如:

cpp foo.cpp.in -o foo.cpp
gcc -c foo.cpp

然而,这种双重预处理对于一个不明确的问题是一个相当尴尬的解决方案。也许有更好的方法来完成你真正想要完成的事情。


顺便说一句,你的命令

gcc -o $MY_DIR/test.exe < cpp /$MY_DIR/test_multi_pass.c | cpp

不起作用是您将gcc标准输出流输入cpp。你说的是"编译我的程序,并对编译器打印到屏幕上的任何消息运行cpp。"将| cpp放在任何命令的末尾意味着预处理其输出,而不是其输入。

最新更新