Commit 197ca35a authored by Andrey Mokhov's avatar Andrey Mokhov Committed by GitHub
Browse files

Merge pull request #279 from michalt/gcc-mm-mg/1

Use GCC's `-MM`/`-MG` to find missing dependencies
parents a931066d c2d7e2aa
......@@ -21,7 +21,8 @@ import Stage
-- 3) Linking object files & static libraries into an executable.
-- We have CcMode for CC and GhcMode for GHC.
data CcMode = CompileC | FindCDependencies
-- TODO: Consider merging FindCDependencies and FindMissingInclude
data CcMode = CompileC | FindCDependencies | FindMissingInclude
deriving (Eq, Generic, Show)
data GhcMode = CompileHs | FindHsDependencies | LinkHs
......
......@@ -5,9 +5,16 @@ import Context
import Expression
import Oracles.Dependencies
import Rules.Actions
import Rules.Generate
import Settings.Paths
import Target
import Development.Shake.Util
import Data.Maybe
import Data.List
import qualified Data.Set as Set
compilePackage :: [(Resource, Int)] -> Context -> Rules ()
compilePackage rs context@Context {..} = do
let path = buildPath context
......@@ -22,6 +29,9 @@ compilePackage rs context@Context {..} = do
if ("//*.c" ?== src)
then do
need $ src : deps
-- TODO: Improve parallelism by collecting all dependencies and
-- need'ing them all at once
mapM_ (needGenerated context) . filter ("//*.c" ?==) $ src : deps
build $ Target context (Cc CompileC stage) [src] [obj]
else do
need $ src : deps
......@@ -39,3 +49,33 @@ needCompileDependencies :: Context -> Action ()
needCompileDependencies context@Context {..} = do
when (isLibrary package) $ need =<< return <$> pkgConfFile context
needContext =<< contextDependencies context
needGenerated :: Context -> FilePath -> Action ()
needGenerated context origFile = go Set.empty
where
go :: Set.Set String -> Action ()
go done = withTempFile $ \outFile -> do
let builder = Cc FindMissingInclude $ stage context
target = Target context builder [origFile] [outFile]
build target
deps <- parseFile outFile
-- Get the full path if the include refers to a generated file and call
-- `need` on it.
needed <- liftM catMaybes $
interpretInContext context (mapM getPathIfGenerated deps)
need needed
let newdone = Set.fromList needed `Set.union` done
-- If we added a new file to the set of needed files, let's try one more
-- time, since the new file might include a genreated header of itself
-- (which we'll `need`).
when (Set.size newdone > Set.size done) (go newdone)
parseFile :: FilePath -> Action [String]
parseFile file = do
input <- liftIO $ readFile file
case parseMakefile input of
[(_file, deps)] -> return deps
_ -> return []
module Rules.Generate (
generatePackageCode, generateRules, installTargets, copyRules,
includesDependencies, derivedConstantsPath, generatedDependencies
includesDependencies, derivedConstantsPath, generatedDependencies,
getPathIfGenerated
) where
import qualified System.Directory as IO
......@@ -196,3 +197,17 @@ generateRules = do
emptyTarget :: Context
emptyTarget = vanillaContext (error "Rules.Generate.emptyTarget: unknown stage")
(error "Rules.Generate.emptyTarget: unknown package")
getPathIfGenerated :: FilePath -> Expr (Maybe FilePath)
getPathIfGenerated include = do
generated <- generatedFiles
-- For includes of generated files, we cannot get the full path of the file
-- (since it might be included due to some include dir, i.e., through `-I`).
-- So here we try both the name and the path.
let nameOrPath (name, path) = include == name || include == path
return . fmap snd $ find nameOrPath generated
generatedFiles :: Expr [(FilePath, FilePath)]
generatedFiles = do
deps <- generatedDependencies
return [ (takeFileName fp, fp) | fp <- deps ]
......@@ -26,7 +26,18 @@ ccBuilderArgs = mconcat
, arg $ dropExtension output -<.> "o"
, arg "-x"
, arg "c"
, arg =<< getInput ] ]
, arg =<< getInput ]
, builder (Cc FindMissingInclude) ? do
mconcat [ arg "-E"
, arg "-MM"
, arg "-MG"
, commonCcArgs
, arg "-MF"
, arg =<< getOutput
, arg =<< getInput
]
]
commonCcArgs :: Args
commonCcArgs = mconcat [ append =<< getPkgDataList CcArgs
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment