Include CPP preprocessor dependencies in -M output
Motivation
GHC's -M
option provides a convenient way to compute file dependencies when compiling Haskell modules (see dependency generation). This is useful for build systems and is already in use by Hadrian. As it should, the CPP preprocessor is run (if the language feature is enabled) before computing dependencies. Unfortunately, ghc -M
currently does not output dependencies within the preprocessor stage itself. Consider this example:
- Main.hs
{-# LANGUAGE CPP #-} module Main where #include "A.hs" main = putStrLn a
- A.hs
import B #include "C.hs" a = "Hello " ++ b ++ c
- B.hs
module B where b = "World"
- C.hs
c = "!"
Running ghc Main.hs -M -dep-suffix ''
outputs the following Makefile:
# DO NOT DELETE: Beginning of Haskell dependencies
B.o : B.hs
Main.o : Main.hs
Main.o : B.hi
# DO NOT DELETE: End of Haskell dependencies
Notice that A.hs
nor C.hs
appear as a dependency of Main.o
even though they are included via #include "A.hs"
. If a build system relies on this to track dependencies, then it may fail to rebuild Main.o
when A.hs
or C.hs
changes.
Proposal
This proposes that preprocessor dependencies be included in the output Makefile with the -M
ghc option, when the new -include-cpp-deps
option is used. In the above scenario, running ghc Main.hs -M -dep-suffix '' -include-cpp-deps
would output the following Makefile:
# DO NOT DELETE: Beginning of Haskell dependencies
B.o : B.hs
Main.o : Main.hs
Main.o : A.hs
Main.o : C.hs
Main.o : /usr/include/stdc-predef.h
Main.o : /path/to/package-db/rts-1.0/include/ghcversion.h
Main.o : B.hi
# DO NOT DELETE: End of Haskell dependencies
(**) Note that ghc produces a tmp file containing package version macros e.g. /tmp/ghc5478_0/ghc_4.h. cpp correctly reports it as a dependency, but since ghc always generate it while building, it isn't a true dependency in this context. Hence it is explicitly excluded from the output. External builders using ghc's -M option will not benefit from know about this tmp file and it's location will also change with every run of ghc.
Implementation
The c preprocessor, cpp
, supports a -M option. The output from that command will be parsed, the temporary package version macros file will be dropped, and the rest will be included in ghc's output makefile.