multipass a source code to cpp

南笙酒味 提交于 2020-01-24 00:22:59

问题


basically, i'm trying to pass source code twice to gcc's cpp, then directly to gcc's c compiler.

as to why, i believe there are just things that can never be made inline within a macro.

here's an example:

/* 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;
}

then simply compile: gcc $MY_DIR/test_multi_pass.c -o $MY_DIR/test.exe

of course, this won't work as when you compile it (whether in gcc or not) it gets preprocessed, then directly passed to the compiler (at least officially):

    # 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;
}

now focus on the very bottom of preprocessed file above.

purely speaking, as far as the c compiler is concerned, that "#define X 22" is not valid syntax and any compiler would probably say that there is a stray "#".

so i try a few tricks:

cpp /$MY_DIR/test_multi_pass.c | cpp

and the output is:

    # 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;
}

now it's done exactly what we wanted it to do and defined X as 22. this is not exactly how i intend to use in my codebase (and i would be coupling this with #undef, etc), but illustrates the attempt quite clearly.

then i tried:

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

i know that in GCC, after initiating the compilation, it is preprocessed by the cpp, then the c compiler syntactically parses the code (to turn i into abstract syntax tree) and along then quietly calls the preprocessor again for all the assembly naming (for the linker) and whatnot.

therefore, at least in gcc, a code is twice preprocessed. so there might be a chance that a previous file is again in the same format as the next iteration of the preprocessing (hopefully, if it doesn't introduce a lot more extra code that breaks the code further more preprocessing in the future).

so perhaps we can preprocess it 4 times (because we preprocess it twice beforehand). hence the hack above.

but what it gives out:

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

now, is this a fundamental mistake of the cpp not being able to preprocess it 4 times or did i just enter the wrong CLI command??


回答1:


GCC only preprocesses your source code once. If it invokes the preprocessor additional times later in the build process, that's irrelevant, because what it's preprocessing at that stage is not your source code; it's generated assembly code or something.

If you want the effect of running the preprocessor twice on your source code before the actual compilation, you can run the preprocessor once manually, then run GCC normally on the output (which will perform another preprocessor pass automatically). For example:

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

However, this double-preprocessing is a rather awkward solution to an unclear problem. There's probably a better way to accomplish whatever it is that you're actually trying to accomplish.


BTW, the reason your command

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

doesn't work is that you're feeding the standard output stream of gcc into cpp. You're saying "compile my program, and run cpp on any messages that the compiler prints to the screen." Putting | cpp at the end of any command means to preprocess its output, not its input.



来源:https://stackoverflow.com/questions/25336905/multipass-a-source-code-to-cpp

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!