Can gcc output C code after preprocessing?
Solution 1
Yes. Pass gcc the -E
option. This will output preprocessed source code.
Solution 2
cpp
is the preprocessor.
Run cpp filename.c
to output the preprocessed code, or better, redirect it to a file with
cpp filename.c > filename.preprocessed
.
Solution 3
-save-temps
This is another good option to have in mind:
gcc -save-temps -c -o main.o main.c
main.c
#define INC 1
int myfunc(int i) {
return i + INC;
}
and now, besides the normal output main.o
, the current working directory also contains the following files:
main.i
is the desired prepossessed file containing:# 1 "main.c" # 1 "<built-in>" # 1 "<command-line>" # 31 "<command-line>" # 1 "/usr/include/stdc-predef.h" 1 3 4 # 32 "<command-line>" 2 # 1 "main.c" int myfunc(int i) { return i + 1; }
main.s
is a bonus :-) and contains the generated assembly:.file "main.c" .text .globl myfunc .type myfunc, @function myfunc: .LFB0: .cfi_startproc pushq %rbp .cfi_def_cfa_offset 16 .cfi_offset 6, -16 movq %rsp, %rbp .cfi_def_cfa_register 6 movl %edi, -4(%rbp) movl -4(%rbp), %eax addl $1, %eax popq %rbp .cfi_def_cfa 7, 8 ret .cfi_endproc .LFE0: .size myfunc, .-myfunc .ident "GCC: (Ubuntu 8.3.0-6ubuntu1) 8.3.0" .section .note.GNU-stack,"",@progbits
If you want to do it for a large number of files, consider using instead:
-save-temps=obj
which saves the intermediate files to the same directory as the -o
object output instead of the current working directory, thus avoiding potential basename conflicts.
The advantage of this option over -E
is that it is easy to add it to any build script, without interfering much in the build itself.
Another cool thing about this option is if you add -v
:
gcc -save-temps -c -o main.o -v main.c
it actually shows the explicit files being used instead of ugly temporaries under /tmp
, so it is easy to know exactly what is going on, which includes the preprocessing / compilation / assembly steps:
/usr/lib/gcc/x86_64-linux-gnu/8/cc1 -E -quiet -v -imultiarch x86_64-linux-gnu main.c -mtune=generic -march=x86-64 -fpch-preprocess -fstack-protector-strong -Wformat -Wformat-security -o main.i
/usr/lib/gcc/x86_64-linux-gnu/8/cc1 -fpreprocessed main.i -quiet -dumpbase main.c -mtune=generic -march=x86-64 -auxbase-strip main.o -version -fstack-protector-strong -Wformat -Wformat-security -o main.s
as -v --64 -o main.o main.s
Tested in Ubuntu 19.04 amd64, GCC 8.3.0.
CMake predefined targets
CMake automatically provides a targets for the preprocessed file:
make help
shows us that we can do:
make main.i
and that target runs:
Preprocessing C source to CMakeFiles/main.dir/main.c.i
/usr/bin/cc -E /home/ciro/bak/hello/main.c > CMakeFiles/main.dir/main.c.i
so the file can be seen at CMakeFiles/main.dir/main.c.i
Tested on cmake 3.16.1.
Solution 4
I'm using gcc as a preprocessor (for html files.) It does just what you want. It expands "#--" directives, then outputs a readable file. (NONE of the other C/HTML preprocessors I've tried do this- they concatenate lines, choke on special characters, etc.) Asuming you have gcc installed, the command line is:
gcc -E -x c -P -C -traditional-cpp code_before.cpp > code_after.cpp
(Doesn't have to be 'cpp'.) There's an excellent description of this usage at http://www.cs.tut.fi/~jkorpela/html/cpre.html.
The "-traditional-cpp" preserves whitespace & tabs.
Solution 5
Run:
gcc -E <file>.c
or
g++ -E <file>.cpp
LGTrader
Retired semiconductor design engineer looking to program interesting things for fun.
Updated on February 07, 2022Comments
-
LGTrader about 2 years
I'm using an open source library which seems to have lots of preprocessing directives to support many languages other than C. So that I can study what the library is doing I'd like to see the C code that I'm compiling after preprocessing, more like what I'd write.
Can gcc (or any other tool commonly available in Linux) read this library but output C code that has the preprocessing converted to whatever and is also readable by a human?
-
Tor Klingberg about 9 yearsIf your compiler commands already has a parameter like
-o something.o
you may also want to change it to-o something.i
. Otherwise the preprocessed output will be in the.o
file. -
user2808264 over 7 years@TorKlingberg Can I do this for multiple files at a time?
-
amirouche almost 6 yearsMany thanks, this is very helpful to generate python cffi cdef!
-
lee8oi over 5 yearsI think this is the best answer because it demonstrates cpp directly. Linux systems (at least Manjaro) seem to have -E by default too. I get the same results from this command either way.
diff
turns up no difference in the files. This is also looks like a useful way to preprocess the code looking for errors in your macros. Great question and a great answer (IALCTHW). -
Matthieu over 5 years@user2808264
gcc -E file1.c file2.c ...
-
EvertW almost 5 yearsMuch more elegant than -E because I can just add -save-temps to CFLAGS without changing the overall behaviour of the build script. Thank you!
-
C-- almost 5 yearsThis is indeed very useful, and -E is very convenient for single files.
-
mercury0114 over 3 yearsIs there an option for the preprocessor to expand only macroses like
#define SIZE 1000
or#ifdef Something #endif
but not#include <other_file.h>
I want to see a preprocessed file but without external functions imported into a single file. -
user64742 about 3 years@lee8oi I was curious what IALCTHW meant but my attempt to web search for it only resulted in this page as a search result. What does that acronym mean? I am quite curious.
-
Alex Measday over 2 yearsA little late! You can skip steps 2 and 3 -- g++/gcc recognize .i files as preprocessed source code. First, #define the PQR macro in the source file. Then: Step 1: g++ -E Message.cpp > Message.i Step 2: g++ Message.i > MessageApp
-
MrMesees over 2 yearscpre article link jkorpela.fi/html/cpre.html I am guessing this is what is filling the suggested edit queue...
-
Pedro Perez about 2 yearsIncredibly useful! thanks!