This question already has an answer here:
cpp preprocessor output not able to understand? [duplicate]
(1 answer)
Closed 5 years ago.
For gcc -E sample.c -o sample.i with the following input C program,
#include <stdio.h>
int main() {
printf("hello world\n");
return 0;
}
the sample.i have the following output preceded by # symbols and I wonder what the line with # exactly means.
# 1 "sample.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 1 "<command-line>" 2
# 1 "sample.c"
# 1 "/usr/include/stdio.h" 1 3 4
# 27 "/usr/include/stdio.h" 3 4
...
There are comments that help a person identify how the preprocessor expanded the various #include <...> macros and other items.
Reading these lines provides the equivalent of reading the logging messages of the preprocessor as it encounters the macros and expands them.
# 1 "sample.c"
Start on line one of the input "sample.c"
# 1 "<built-in>"
Process the built-in c pre-procssor directive (must be an implementation detail), but is presented as a fake "file".
# 1 "<command-line>"
Process the command line directive (again implementation detail), presented as a fake "file".
# 1 "/usr/include/stdc-predef.h" 1 3 4
Include (at line 1) the stdc-predef.h file, it's the start of the file, suppress warnings permitted for system header files, assure that the symbols are treated like C symbols.
# 1 "<command-line>" 2
Return from the command line "fake" file.
# 1 "sample.c"
Back in sample.c.
# 1 "/usr/include/stdio.h" 1 3 4
Now starting with file "stdio.h", suppress permitted system warnings, treat symbols in the file a C symbols.
# 27 "/usr/include/stdio.h" 3 4
And so on...
The documentation is here.
Related
I came across the following in a Makefile:
CPP =cpp
GFLAGS =-traditional-cpp -Dlinux64 -DWM_ARCH_OPTION=64 -DWM_DP \
-DWM_LABEL_SIZE=32 -Dlinux64 -DWM_ARCH_OPTION=64 -DWM_DP -DWM_LABEL_SIZE=32
op1: ./Make/options
#$(CPP) $(GFLAGS) ./Make/options | sed -e 's# *# #g' > op1
The content in the ./Make/options is as follows:
EXE_INC = -I$/project/src/finiteVolume/lnInclude
EXE_LIBS = -lfiniteVolume
I checked to op1 file generated and the content is as follows:
# 1 "options"
# 1 "<built-in>"
# 1 "<command-line>"
# 8 "<command-line>"
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 17 "/usr/include/stdc-predef.h" 3 4
I finally come to know this is related with c-preprocessor. I have no idea what those , mean. Can anyone explain what it tries to do by doing this?
cpp is the C preprocessor. This particular makefile appears to be using cpp (and sed) to generate the file op1 from the ./Make/options file.
I am trying to understand the compiling process. We can see the preprocessor intermediate file by using:
gcc -E hello.c -o hello.i
or
cpp hello.c > hello.i
I roughly know what the preprocessor does, but I have difficulties understanding the numbers in some of the lines. For example:
# 1 "/usr/include/stdc-predef.h" 1 3 4
# 1 "<command-line>" 2
# 1 "hello.c"
# 1 "/usr/include/stdio.h" 1 3 4
# 27 "/usr/include/stdio.h" 3 4
# 1 "/usr/include/features.h" 1 3 4
# 374 "/usr/include/features.h" 3 4
The numbers can help debugger to display the line numbers. So my guess for the first column is the line number for column #2 file. But what do the following numbers do?
The numbers following the filename are flags:
1: This indicates the start of a new file.
2: This indicates returning to a file (after having included another file).
3: This indicates that the following text comes from a system header file, so certain warnings should be suppressed.
4: This indicates that the following text should be treated as being wrapped in an implicit extern "C" block.
Source: https://gcc.gnu.org/onlinedocs/cpp/Preprocessor-Output.html
This question already has answers here:
What is the meaning of lines starting with a hash sign and number like '# 1 "a.c"' in the gcc preprocessor output?
(3 answers)
Closed 9 years ago.
See following example:
$ cat foo.c
#include <stdio.h>
int main()
{
return 0;
}
$ gcc -E foo.c | head
# 1 "foo.c"
# 1 "<built-in>"
# 1 "<command line>"
# 1 "foo.c"
# 1 "/usr/include/stdio.h" 1 3 4
# 36 "/usr/include/stdio.h" 3 4
# 1 "/usr/include/sys/feature_tests.h" 1 3 4
# 30 "/usr/include/sys/feature_tests.h" 3 4
#pragma ident "%Z%%M% %I% %E% SMI"
$
I tried Google but I don't know what keywords I should use for searching. Any links to the documentation?
They are linemarkers for identifying which source file and line a particular line of code came from. They can be used to generate more accurate diagnostic messages, for example. Documentation links:
Preprocessor Output
Line Control
You can use the -P option to omit them if you'd like.
Is there a definitive way to see where a given #include <example.h> resolves to? I have a #include <linux/unistd.h> in my code but I don't know which unistd.h is being used.
If you use the -E command line option to get the preprocessor output, it will tell you the full path to every header file included, including those included by other headers. For example:
$ cat test.c
#include <unistd.h>
$ gcc -E test.c
# 1 "test.c"
# 1 "<built-in>"
# 1 "<command-line>"
# 1 "test.c"
# 1 "/usr/include/unistd.h" 1 3 4
# 71 "/usr/include/unistd.h" 3 4
# 1 "/usr/include/_types.h" 1 3 4
# 27 "/usr/include/_types.h" 3 4
# 1 "/usr/include/sys/_types.h" 1 3 4
# 32 "/usr/include/sys/_types.h" 3 4
# 1 "/usr/include/sys/cdefs.h" 1 3 4
# 33 "/usr/include/sys/_types.h" 2 3 4
# 1 "/usr/include/machine/_types.h" 1 3 4
# 34 "/usr/include/machine/_types.h" 3 4
# 1 "/usr/include/i386/_types.h" 1 3 4
# 37 "/usr/include/i386/_types.h" 3 4
typedef signed char __int8_t;
(lots more output)
So in this case, the header that's being used is /usr/include/unistd.h.
From the GCC documentation,
On a normal Unix system, if you do not
instruct it otherwise, it will look
for headers requested with #include
in:
/usr/local/include
libdir/gcc/target/version/include
/usr/target/include
/usr/include
In the above, target is the canonical
name of the system GCC was configured
to compile code for; often but not
always the same as the canonical name
of the system it runs on. version is
the version of GCC in use.
You can add to this list with the
-Idir command line option. All the directories named by -I are searched,
in left-to-right order, before the
default directories. The only
exception is when dir is already
searched by default. In this case, the
option is ignored and the search order
for system directories remains
unchanged.
So unless you're adding the -I (capital eye, not ell) switch, the version included is the version found in the first of those directories that holds it.
I would like to be able to get a list of all possible files included in a C source file.
I understand there are complications with other # directives (for instance, an #ifdef could either prevent an include or cause an extra include). All I'm looking for is a list of files that may have been included.
Is there a tool that already does this?
The files I'm compiling are only going to .o, and the standard C libraries are not included. I know that sounds wonky, but we have our reasons.
The reason I want to be able to do this is I want to have a list of files which may have contributed something to the .o, so I can check to see if they have changed.
Quoting the man page for gcc:
-M Instead of outputting the result of preprocessing, output a rule
suitable for make describing the dependencies of the main source
file. The preprocessor outputs one make rule containing the object
file name for that source file, a colon, and the names of all the
included files, including those coming from -include or -imacros
command line options.
This basically does what you want. There are several other related options (all starting with -M) that give you different variants of this output.
my syntax is rusty, but ...
grep -ir "#include " *.c
might work ...
If you use gcc you can inspect preprocessor dump:
[~]> gcc -E /usr/include/cups/dir.h|grep "#"
# 1 "/usr/include/cups/dir.h"
# 1 "<built-in>"
# 1 "<command line>"
# 1 "/usr/include/cups/dir.h"
# 26 "/usr/include/cups/dir.h"
# 1 "/usr/include/sys/stat.h" 1 3 4
# 73 "/usr/include/sys/stat.h" 3 4
# 1 "/usr/include/sys/_types.h" 1 3 4
# 32 "/usr/include/sys/_types.h" 3 4
# 1 "/usr/include/sys/cdefs.h" 1 3 4
# 33 "/usr/include/sys/_types.h" 2 3 4
# 1 "/usr/include/machine/_types.h" 1 3 4
# 34 "/usr/include/machine/_types.h" 3 4
# 1 "/usr/include/i386/_types.h" 1 3 4
# 37 "/usr/include/i386/_types.h" 3 4
# 70 "/usr/include/i386/_types.h" 3 4
# 35 "/usr/include/machine/_types.h" 2 3 4
# 34 "/usr/include/sys/_types.h" 2 3 4
# 58 "/usr/include/sys/_types.h" 3 4
# 94 "/usr/include/sys/_types.h" 3 4
# 74 "/usr/include/sys/stat.h" 2 3 4
# 1 "/usr/include/sys/_structs.h" 1 3 4
# 88 "/usr/include/sys/_structs.h" 3 4
# 79 "/usr/include/sys/stat.h" 2 3 4
# 152 "/usr/include/sys/stat.h" 3 4
# 228 "/usr/include/sys/stat.h" 3 4
# 248 "/usr/include/sys/stat.h" 3 4
# 422 "/usr/include/sys/stat.h" 3 4
# 27 "/usr/include/cups/dir.h" 2
# 42 "/usr/include/cups/dir.h"
You could do the preprocessor step only. Most compilers allow this.
Of course that would require some busywork reading the resulting file.
All POSSIBLE files? No way to do that.
Alas, simply grepping the source for #include is not guaranteed to be enough, because someone may have committed ...
#define tricksy(foo,bar) <foo##bar>
#define precious tricksy(ios, tream)
#include precious
int main(int, char **)
{
std::cout << "Hobbits!" << std::endl;
return 0;
}
... though you would be able to tell by inspection that something nonstandard was going on with the #include precious because of the missing <> or "".
A non-perverse example would be token-pasting different library root directories depending on command-line definitions.