多通道源代码到cpp

时间:2014-08-16 04:22:35

标签: c gcc compiler-construction c-preprocessor

基本上,我试图将源代码两次传递给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等结合使用),但是很好地说明了这种尝试清楚。

然后我尝试了:

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

我知道在GCC中,在启动编译之后,它由cpp预处理,然后c编译器在语法上解析代码(将i转换为抽象语法树),然后静默调用所有程序集命名(对于链接器)和诸如此类的预处理器。

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

所以也许我们可以预处理它4次(因为我们预先对它进行了两次预处理)。因此上面的黑客。

但它给出了什么:

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

现在,这是cpp无法预处理4次或者输入错误的CLI命令的根本错误吗?

1 个答案:

答案 0 :(得分:1)

GCC只会预处理一次您的源代码。如果它在构建过程中稍后再调用预处理器,那就无关紧要了,因为它在那个阶段的预处理不是你的源代码;它生成了汇编代码或其他东西。

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

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

然而,这种双重预处理对于一个不明确的问题来说是一个相当尴尬的解决方案。可能有更好的方法来实现你实际上想要完成的任何事情。


BTW,你的命令

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

无法将您gcc标准输出流输入cpp。您正在说&#34;编译我的程序,并在编译器打印到屏幕上的任何消息上运行cpp。&#34;将| cpp放在任何命令的末尾意味着预处理其输出,而不是其输入。