This is the mail archive of the
gcc-bugs@gcc.gnu.org
mailing list for the GCC project.
Re: cpp seems not to include # line "file" output for empty files
> > > It appears that cpp is deciding that it doesn't have to generate the #
> > > line output if there is no output from the file. This makes sense for
> > > the intend use of these directives for telling the compiler what
> > > filename/line number a line of cpp output came from, but it badly
> > > hoses dependency generators and other programs that rely on this
> > > output for getting a list of files that cpp read.
>
> The format of cpp's output is not to be depended upon by anyone. It's
> a private interface between cpp and cc1. It's not secret, but the
> details can change at any time.
>
> > > Such functionality is essential for writing portable dependency
> > > generators.
>
> I can think of several better ways to write a portable dependency
> generator. First, if the existing -M options don't do what you want,
> please tell us what is missing so we can improve them. If you want a
> raw dump of each header file entered, use -H. If all else fails, you
> can grovel through the code with awk, although I don't recommend it.
Since I made the claim that I had been using this method with a dozen
compilers for years and since I also fully agree with your and others'
analysis, I decided to reread the code for my dependency generator
which I wrote years ago. What it actually does is look at the cpp
output for lines starting with # (but not #pragma lines) and
containing a double-quoted string. It then checks to see whether the
contents of that string name a file. If so, it considers it a
dependency. The ISO standard does discuss #line, and it appears that
many of the compilers are generating this for the benefit of the
compiler. I guess this is why it works on so many platforms.
> > > I feel like I've read this in the ISO standard but I can't seem
> > > to find any documentation that firmly states that ISO requires
> > > this behavior.
>
> You have not read it in the standard. The standard says nothing
> whatsoever about the interface between cpp and cc1. Matter of fact,
> it doesn't even treat the preprocessor as a separate function.
> Preprocessing is phases 1-4 of translation, which are immediately
> followed by phases 5-8. All eight phases can happen in the same
> process. Or they can communicate by external files, pipes, smoke
> signals, whatever. The standard doesn't care.
Right. It does talk about #line though. I looked at the preprocessor
section yesterday and this is what I remember reading. I realize that
this is a totally different issue. Thanks for setting me straight.
> > If you want dependency info from cpp, use the switches to tell it to
> > give you dependency info.
>
> I generally tend to agree.
In a debate about the "right" way to generate dependencies, I also
agree. However, my bug report points out a change in behavior in the
preprocessor that I noticed because it caused things to break. In
truth, I didn't catch this from my own dependency generator since
virtually all my code is C++ and so I have no header files that
contain all #defines. The place where I actually caught this was in
building zsh 3.1.9-dev-6. The zsh configure.in code uses cpp output
to figure out which header file includes a list of signals. With the
cpp in the (unfortunately "released" by RedHat) 2.96 gcc not
generating any output for files with only defines, it failed to find
the signal list. I reported to the zsh mailing list that a bug in cpp
was breaking zsh. I am going to send a new report strongly suggesting
that they rewrite this piece of the configure.in code to not rely on
the cpp output.
Anyway, the various responses to my post have thoroughly convinced me
that I've been living dangerously relying on cpp output for dependency
generation even if it has worked well for so long. What I'll probably
end up doing is putting a special case in my dependency generator that
if the underlying compiler has a clean way to generate dependency
information, use it; otherwise fall back to the old way which works in
most cases. Trying to use some stand-alone system doesn't work well
enough since many #includes are dependent upon preprocessor symbols
that are defined internally by compilers. This is the reason that my
dependency generator uses cpp in the first place.
Jay