Commit 4a46d14e authored by Andrey Mokhov's avatar Andrey Mokhov
Browse files

Factor out cabal parsing functionality into the library

See #347
parent 8fc676e4
...@@ -27,6 +27,7 @@ executable hadrian ...@@ -27,6 +27,7 @@ executable hadrian
, Flavour , Flavour
, GHC , GHC
, Hadrian.Expression , Hadrian.Expression
, Hadrian.Haskell.Cabal
, Hadrian.Oracles.ArgsHash , Hadrian.Oracles.ArgsHash
, Hadrian.Oracles.DirectoryContents , Hadrian.Oracles.DirectoryContents
, Hadrian.Oracles.KeyValue , Hadrian.Oracles.KeyValue
......
module Hadrian.Haskell.Cabal (readCabal, cabalNameVersion, cabalDependencies) where
import Development.Shake
import Distribution.Package
import Distribution.PackageDescription
import Distribution.PackageDescription.Parse
import Distribution.Text
import Distribution.Types.CondTree
import Distribution.Verbosity
-- TODO: Track the values?
-- | Read a given @.cabal@ file and return the 'GenericPackageDescription'.
readCabal :: FilePath -> Action GenericPackageDescription
readCabal cabal = do
need [cabal]
liftIO $ readGenericPackageDescription silent cabal
-- | Read a given @.cabal@ file and return the package name and version.
cabalNameVersion :: FilePath -> Action (String, String)
cabalNameVersion cabal = do
identifier <- package . packageDescription <$> readCabal cabal
return (unPackageName $ pkgName identifier, display $ pkgVersion identifier)
-- | Read a given @.cabal@ file and return the package dependencies.
cabalDependencies :: FilePath -> Action [String]
cabalDependencies cabal = do
gpd <- readCabal cabal
let depsLib = collectDeps $ condLibrary gpd
depsExes = map (collectDeps . Just . snd) $ condExecutables gpd
deps = concat $ depsLib : depsExes
return $ [ unPackageName name | Dependency name _ <- deps ]
collectDeps :: Maybe (CondTree v [Dependency] a) -> [Dependency]
collectDeps Nothing = []
collectDeps (Just (CondNode _ deps ifs)) = deps ++ concatMap f ifs
where
f (CondBranch _ t mt) = collectDeps (Just t) ++ collectDeps mt
module Rules.Cabal (cabalRules) where module Rules.Cabal (cabalRules) where
import Distribution.Package as DP import Hadrian.Haskell.Cabal
import Distribution.PackageDescription
import Distribution.PackageDescription.Parse
import Distribution.Text
import Distribution.Types.CondTree
import Distribution.Verbosity
import Base import Base
import GHC import GHC
...@@ -18,32 +13,18 @@ cabalRules = do ...@@ -18,32 +13,18 @@ cabalRules = do
bootPkgs <- stagePackages Stage0 bootPkgs <- stagePackages Stage0
let pkgs = filter (\p -> p /= compiler && isLibrary p) bootPkgs let pkgs = filter (\p -> p /= compiler && isLibrary p) bootPkgs
constraints <- forM (sort pkgs) $ \pkg -> do constraints <- forM (sort pkgs) $ \pkg -> do
need [pkgCabalFile pkg] (name, version) <- cabalNameVersion (pkgCabalFile pkg)
pd <- liftIO . readGenericPackageDescription silent $ pkgCabalFile pkg return $ name ++ " == " ++ version
let identifier = package . packageDescription $ pd
version = display . pkgVersion $ identifier
return $ unPackageName (DP.pkgName identifier) ++ " == " ++ version
writeFileChanged out . unlines $ constraints writeFileChanged out . unlines $ constraints
putSuccess $ "| Successfully generated boot package constraints" putSuccess $ "| Successfully generated boot package constraints"
-- Cache package dependencies. -- Cache package dependencies.
"//" -/- packageDependencies %> \out -> do "//" -/- packageDependencies %> \out -> do
pkgDeps <- forM (sort knownPackages) $ \pkg -> do pkgDeps <- forM (sort knownPackages) $ \pkg -> do
exists <- doesFileExist $ pkgCabalFile pkg exists <- doesFileExist (pkgCabalFile pkg)
if not exists then return $ pkgNameString pkg if not exists then return $ pkgNameString pkg
else do else do
need [pkgCabalFile pkg] deps <- sort <$> cabalDependencies (pkgCabalFile pkg)
pd <- liftIO . readGenericPackageDescription silent $ pkgCabalFile pkg return . unwords $ pkgNameString pkg : (deps \\ [pkgNameString pkg])
let depsLib = collectDeps $ condLibrary pd
depsExes = map (collectDeps . Just . snd) $ condExecutables pd
deps = concat $ depsLib : depsExes
depNames = [ unPackageName name | Dependency name _ <- deps ]
return . unwords $ pkgNameString pkg : (sort depNames \\ [pkgNameString pkg])
writeFileChanged out $ unlines pkgDeps writeFileChanged out $ unlines pkgDeps
putSuccess $ "| Successfully generated package dependencies" putSuccess $ "| Successfully generated package dependencies"
collectDeps :: Maybe (CondTree v [Dependency] a) -> [Dependency]
collectDeps Nothing = []
collectDeps (Just (CondNode _ deps ifs)) = deps ++ concatMap f ifs
where
f (CondBranch _ t mt) = collectDeps (Just t) ++ collectDeps mt
module Settings.Packages.GhcCabal (ghcCabalPackageArgs) where module Settings.Packages.GhcCabal (ghcCabalPackageArgs) where
import Distribution.Package (pkgVersion) import Hadrian.Haskell.Cabal
import Distribution.PackageDescription (packageDescription)
import Distribution.PackageDescription.Parse
import qualified Distribution.PackageDescription as DP
import Distribution.Text (display)
import Distribution.Verbosity (silent)
import Base import Base
import Expression import Expression
...@@ -15,11 +10,7 @@ import Utilities ...@@ -15,11 +10,7 @@ import Utilities
ghcCabalPackageArgs :: Args ghcCabalPackageArgs :: Args
ghcCabalPackageArgs = stage0 ? package ghcCabal ? builder Ghc ? do ghcCabalPackageArgs = stage0 ? package ghcCabal ? builder Ghc ? do
cabalDeps <- expr $ pkgDependencies cabal cabalDeps <- expr $ pkgDependencies cabal
expr $ need [pkgCabalFile cabal] (_, cabalVersion) <- expr $ cabalNameVersion (pkgCabalFile cabal)
pd <- exprIO . readGenericPackageDescription silent $ pkgCabalFile cabal
let identifier = DP.package . packageDescription $ pd
cabalVersion = display . pkgVersion $ identifier
mconcat mconcat
[ pure [ "-package " ++ pkgNameString pkg | pkg <- cabalDeps ] [ pure [ "-package " ++ pkgNameString pkg | pkg <- cabalDeps ]
, arg "--make" , arg "--make"
......
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