alliedmodders/ambuild

Header dependency parsing fails for GCC when using `-include`

Closed this issue · 2 comments

If a project compiles with GCC and uses e.g. -include common.h on the compiler command line to auto-include a header on each source file that's compiled, then the AMBuild's hacky gcc -H-based header dependency parsing state machine in ParseGCCDeps fails to work properly.

GCC's -H option doesn't seem to print the header trace for -include'd header files. So not only does AMBuild miss dependency information, but part of the -H dump is inadvertently printed out to the user instead of being stripped as intended.

(ParseGCCDeps will be in state sFoundIncludeGuard, and then will run into one of the "multiple include guards may be useful for" filename lines that is not in its deps set, and so will enter the sIgnoring state prematurely.)

Maybe it's time to switch to a more proper gcc -Mx-based dependency parsing system? Perhaps using a pipe for the dependency "file"? It would certainly avoid many of the problems and ugliness of the current approach.

Both require some fiddly parsing, so I'd rate them as equally "hacky". But if -MD -E is more accurate and won't have localization issues, that seems like an obviously better choice.

I'm not sure when I'll have a chance to look at it though, probably not for a few weeks at least. If the bug is that we're missing the dependency, scanning the options seems like an acceptable quick fix to me. If the bug is that we're missing dependencies because we stop scanning the output early, that seems more serious, and probably biting the -MD bullet is the way to go.

I'm going to add support for this since it's needed for other tools (like protoc), but, it's just as idiosyncratic as parsing -H.

  • gcc -H with a precompiled header includes the .gch file and the source header file.
  • clang -H with a precompiled header includes neither the .pch file nor anything that it depends on.
  • gcc and clang with -M do not list .gch/.pch files.
  • gcc -MD with a precompiled header does not include the .gch file, does include the source header, but does not include anything the header depends on.
  • gcc -M, clang -M, and clang -MD all list the recursive dependencies of .gch/.pch files, but not those files themselves.

My gut feeling, is that we should switch to -MD, which will be roughly the same as -H. Or -MMD to not blow up the graph size, but I haven't thought about that much yet.

The difference in how GCC and clang treat precompiled headers is vaguely annoying. But I think it's okay. In both cases there will be strong dependencies between source .h files and the unified .h file. Then another strong dependency between that and each C/C++ file. And because there's a special, order-enforcing dependency between PCH generation and source compilation, everything should work out nicely.