Andreas
Andreas

Reputation: 5301

gcc flag -include ignored when compiling .i or .ii files

I recently found out gcc skips preprocessing if file ending is .i or .ii and decided to give it a go. Compiling a hello world program without including stdio.h:

gcc -Wall file.c; # compiles with preprocessor, implicit declaration of puts
gcc -Wall file.i; # compiles without preprocessor, implicit declaration of puts 

I can't include stdio.h without a preprocessor directive, but I remember the -include flag to gcc can be used to "force include" headers. It led to following test:

gcc -Wall -include stdio.h file.c; # no warnings, "hello world". hooray
gcc -Wall -include stdio.h file.i; # implicit declaration of puts WAIT WHAT?!

I find it odd how gcc does not include stdio.h if compiling a file without preprocessing. Even odder how no warning is emitted; the -include stdio.h has no apparent effect, which is erroneous use of gcc at best.

Why is it not working?

GCC version 6.3.0.

Upvotes: 1

Views: 1584

Answers (3)

melpomene
melpomene

Reputation: 85757

-include is listed under Preprocessor Options:

3.12 Options Controlling the Preprocessor

These options control the C preprocessor, which is run on each C source file before actual compilation.

[...]

-include file

Process file as if #include "file" appeared as the first line of the primary source file. [...]

However, for .i files the preprocessor never runs, so the option has no effect.

GCC generally doesn't warn about options that have no effect. You can also run gcc -Wall -funsigned-char foo.o, which doesn't even invoke the compiler. -Wall and -funsigned-char are simply ignored.

You can think of compilation as a pipeline:

  1. C code (.c) passes through the preprocessor, which produces ...
  2. preprocessed C code (.i), which is processed by the compiler producing ...
  3. assembler code (.s), which is processed by the assembler producing ...
  4. object code (.o), which is processed by the linker, giving you ...
  5. an executable.

The file name tells GCC which stage to start from.

Options can be used to tell GCC where to stop:

  • -P stops after preprocessing
  • -S stops after compilation
  • -c stops after assembling

Other options are passed to the corresponding stage in the pipeline. If that part of the pipeline never runs, nothing happens.

Upvotes: 1

Thomas Jager
Thomas Jager

Reputation: 5265

From the GCC documentation:

-include file

Process file as if #include "file" appeared as the first line of the primary source file. However, the first directory searched for file is the preprocessor’s working directory instead of the directory containing the main source file. If not found there, it is searched for in the remainder of the #include "…" search chain as normal.

If multiple -include options are given, the files are included in the order they appear on the command line.

That first phrase

Process file as if #include "file" appeared as the first line of the primary source file.

indicates that one would expect the behaviour you see.

If GCC doesn't apply preprocessing directives, it won't include that file, because it doesn't blindly add the contents of stdio.h to the front of the file being compiled, it acts as if it added the preprocessor include directive.

Upvotes: 0

Joshua
Joshua

Reputation: 43188

It makes sense. .i files have already been preprocessed, so there is no preprocess step so there is no include.

Operating on already preprocessed files is an extremely advanced topic so perhaps they just assumed anybody doing it knows what they're doing.

Or maybe it's just an oversight and you should get a warning.

Upvotes: 0

Related Questions