Unverified Commit 8dc4f73f authored by Andrey Mokhov's avatar Andrey Mokhov Committed by GitHub

Clean up remaining bits related to ghc-cabal (#658)

* Drop ghcCabal package
* Merge GhcCabal and CabalFlags builders
* Use more consistent naming
* Resolve import cycle
* Rename parseCabal to parseCabalFile
* Remove outdated references to ghc-cabal from comments
parent a804d57a
......@@ -33,6 +33,6 @@ ghc %ghcArgs%
if %ERRORLEVEL% NEQ 0 EXIT /B %ERRORLEVEL%
rem Unset GHC_PACKAGE_PATH variable, as otherwise ghc-cabal complains
rem Unset GHC_PACKAGE_PATH variable, as otherwise Cabal complains
set GHC_PACKAGE_PATH=
bin\hadrian %hadrianArgs%
......@@ -36,13 +36,15 @@ executable hadrian
, Hadrian.Builder.Tar
, Hadrian.Expression
, Hadrian.Haskell.Cabal
, Hadrian.Haskell.Cabal.CabalData
, Hadrian.Haskell.Cabal.PackageData
, Hadrian.Haskell.Cabal.Parse
, Hadrian.Haskell.Cabal.Type
, Hadrian.Oracles.ArgsHash
, Hadrian.Oracles.DirectoryContents
, Hadrian.Oracles.Path
, Hadrian.Oracles.TextFile
, Hadrian.Oracles.TextFile.Rules
, Hadrian.Oracles.TextFile.Type
, Hadrian.Package
, Hadrian.Package.Type
, Hadrian.Target
......@@ -70,13 +72,13 @@ executable hadrian
, Rules.Test
, Settings
, Settings.Builders.Alex
, Settings.Builders.Cabal
, Settings.Builders.Common
, Settings.Builders.Cc
, Settings.Builders.Configure
, Settings.Builders.DeriveConstants
, Settings.Builders.GenPrimopCode
, Settings.Builders.Ghc
, Settings.Builders.GhcCabal
, Settings.Builders.GhcPkg
, Settings.Builders.Haddock
, Settings.Builders.Happy
......
{-# LANGUAGE InstanceSigs #-}
module Builder (
-- * Data types
ArMode (..), CcMode (..), GhcCabalMode (..), GhcMode (..), GhcPkgMode (..), HaddockMode (..),
SphinxMode (..), TarMode (..), Builder (..),
ArMode (..), CcMode (..), ConfigurationInfo (..), GhcMode (..),
GhcPkgMode (..), HaddockMode (..), SphinxMode (..), TarMode (..),
Builder (..),
-- * Builder properties
builderProvenance, systemBuilderPath, builderPath, isSpecified, needBuilder,
......@@ -53,20 +54,36 @@ instance Binary GhcMode
instance Hashable GhcMode
instance NFData GhcMode
-- | GHC cabal mode. Can configure, copy and register packages.
data GhcCabalMode = Conf | HsColour | Check | Sdist
deriving (Eq, Generic, Show)
instance Binary GhcCabalMode
instance Hashable GhcCabalMode
instance NFData GhcCabalMode
-- | GhcPkg can initialise a package database and register packages in it.
data GhcPkgMode = Init -- initialize a new database.
| Update -- update a package.
| Clone -- clone a package from one pkg database into another. @Copy@ is already taken by GhcCabalMode.
| Unregister -- unregister a package
| Dependencies -- compute package dependencies.
-- | To configure a package we need two pieces of information, which we choose
-- to record separately for convenience.
--
-- * Command line arguments to be passed to the setup script.
--
-- * Package configuration flags that enable/disable certain package features.
-- Here is an example from "Settings.Packages":
--
-- > package rts
-- > ? builder (Cabal Flags)
-- > ? any (wayUnit Profiling) rtsWays
-- > ? arg "profiling"
--
-- This instructs package configuration functions (such as 'configurePackage')
-- to enable the @profiling@ Cabal flag when processing @rts.cabal@ and
-- building RTS with profiling information.
data ConfigurationInfo = Setup | Flags deriving (Eq, Generic, Show)
instance Binary ConfigurationInfo
instance Hashable ConfigurationInfo
instance NFData ConfigurationInfo
-- TODO: Do we really need all these modes? Why do we need 'Dependencies'? We
-- can extract dependencies using the Cabal library.
-- | 'GhcPkg' can initialise a package database and register packages in it.
data GhcPkgMode = Init -- ^ Initialize a new database.
| Update -- ^ Update a package.
| Copy -- ^ Copy a package from one database to another.
| Unregister -- ^ Unregister a package.
| Dependencies -- ^ Compute package dependencies.
deriving (Eq, Generic, Show)
instance Binary GhcPkgMode
......@@ -82,21 +99,24 @@ instance Binary HaddockMode
instance Hashable HaddockMode
instance NFData HaddockMode
-- | A 'Builder' is an external command invoked in a separate process via 'cmd'.
-- @Ghc Stage0@ is the bootstrapping compiler.
-- @Ghc StageN@, N > 0, is the one built in stage (N - 1).
-- @GhcPkg Stage0@ is the bootstrapping @GhcPkg@.
-- @GhcPkg Stage1@ is the one built in Stage0.
-- | A 'Builder' is a (usually external) command invoked in a separate process
-- via 'cmd'. Here are some examples:
-- * 'Alex' is a lexical analyser generator that builds @Lexer.hs@ from @Lexer.x@.
-- * 'Ghc' 'Stage0' is the bootstrapping Haskell compiler used in 'Stage0'.
-- * 'Ghc' @StageN@ (N > 0) is the GHC built in stage (N - 1) and used in @StageN@.
--
-- The 'Cabal' builder is unusual in that it does not correspond to an external
-- program but instead relies on the Cabal library for package configuration.
data Builder = Alex
| Ar ArMode Stage
| Autoreconf FilePath
| DeriveConstants
| Cabal ConfigurationInfo Stage
| Cc CcMode Stage
| Configure FilePath
| GenApply
| GenPrimopCode
| Ghc GhcMode Stage
| GhcCabal GhcCabalMode Stage
| GhcPkg GhcPkgMode Stage
| Haddock HaddockMode
| Happy
......@@ -117,28 +137,6 @@ data Builder = Alex
| Tar TarMode
| Unlit
| Xelatex
| CabalFlags Stage
-- ^ A \"virtual\" builder (not backed by a program),
-- used a lot in Settings.Packages, that allows us to
-- toggle cabal flags of packages depending on some `Args`
-- predicates, and then collect all those when we are about to
-- configure the said packages, in Hadrian.Haskell.Cabal.Parse,
-- so that we end up passing the appropriate flags to the Cabal
-- library. For example:
--
-- > package rts
-- > ? builder CabalFlags
-- > ? any (wayUnit Profiling) rtsWays
-- > ? arg "profiling"
--
-- (from Settings.Packages) specifies that if we're
-- processing the rts package with the `CabalFlag` builder,
-- and if we're building a profiling-enabled way of the rts,
-- then we pass the @profiling@ argument to the builder. This
-- argument is then collected by the code that performs the
-- package configuration, and @rts.cabal@ is processed as if
-- we were passing @-fprofiling@ to our build tool.
deriving (Eq, Generic, Show)
instance Binary Builder
......@@ -155,7 +153,6 @@ builderProvenance = \case
GenPrimopCode -> context Stage0 genprimopcode
Ghc _ Stage0 -> Nothing
Ghc _ stage -> context (pred stage) ghc
GhcCabal _ _ -> context Stage1 ghcCabal
GhcPkg _ Stage0 -> Nothing
GhcPkg _ _ -> context Stage0 ghcPkg
Haddock _ -> context Stage1 haddock
......@@ -260,7 +257,7 @@ instance H.Builder Builder where
unit $ cmd [Cwd output] [path] buildArgs
unit $ cmd [Cwd output] [path] buildArgs
GhcPkg Clone _ -> do
GhcPkg Copy _ -> do
Stdout pkgDesc <- cmd [path]
[ "--expand-pkgroot"
, "--no-user-package-db"
......
......@@ -7,20 +7,20 @@ import Hadrian.Builder.Tar
data CcMode = CompileC | FindCDependencies
data GhcMode = CompileHs | CompileCWithGhc | FindHsDependencies | LinkHs
data GhcCabalMode = Conf | HsColour | Check | Sdist
data GhcPkgMode = Init | Update | Clone | Unregister | Dependencies
data ConfigurationInfo = Setup | Flags
data GhcPkgMode = Init | Update | Copy | Unregister | Dependencies
data HaddockMode = BuildPackage | BuildIndex
data Builder = Alex
| Ar ArMode Stage
| Autoreconf FilePath
| DeriveConstants
| Cabal ConfigurationInfo Stage
| Cc CcMode Stage
| Configure FilePath
| GenApply
| GenPrimopCode
| Ghc GhcMode Stage
| GhcCabal GhcCabalMode Stage
| GhcPkg GhcPkgMode Stage
| Haddock HaddockMode
| Happy
......@@ -41,7 +41,6 @@ data Builder = Alex
| Tar TarMode
| Unlit
| Xelatex
| CabalFlags Stage
instance Eq Builder
instance Show Builder
......@@ -7,7 +7,7 @@ import System.Environment
-- for better robustness of the build system.
setupEnvironment :: IO ()
setupEnvironment = do
-- ghc-cabal refuses to work when GHC_PACKAGE_PATH is set (e.g. by Stack)
-- Cabal refuses to work when GHC_PACKAGE_PATH is set (e.g. by Stack)
unsetEnv "GHC_PACKAGE_PATH"
-- in MinGW if PWD is set to a Windows "C:\\" style path then configure
......
......@@ -27,16 +27,16 @@ import {-# SOURCE #-} Builder
import Context hiding (stage, package, way)
import Expression.Type
import Hadrian.Expression hiding (Expr, Predicate, Args)
import Hadrian.Haskell.Cabal.PackageData (PackageData)
import Hadrian.Oracles.TextFile (readPackageDataFile)
import Hadrian.Haskell.Cabal.PackageData
import Hadrian.Oracles.TextFile
-- TODO: Get rid of partiality.
-- | Get values from a configured cabal stage.
getPackageData :: (PackageData -> a) -> Expr a
getPackageData key = do
ctx <- getContext
Just cabal <- expr (readPackageDataFile ctx)
return $ key cabal
Just packageData <- expr (readPackageData ctx)
return $ key packageData
-- | Is the build currently in the provided stage?
stage :: Stage -> Predicate
......
......@@ -3,12 +3,12 @@ module GHC (
-- * GHC packages
array, base, binary, bytestring, cabal, checkApiAnnotations, checkPpr,
compareSizes, compiler, containers, deepseq, deriveConstants, directory,
filepath, genapply, genprimopcode, ghc, ghcBoot, ghcBootTh, ghcCabal,
ghcCompact, ghcHeap, ghci, ghcPkg, ghcPrim, ghcTags, ghcSplit, haddock,
haskeline, hsc2hs, hp2ps, hpc, hpcBin, integerGmp, integerSimple, iserv,
libffi, libiserv, mtl, parsec, parallel, pretty, primitive, process, rts,
runGhc, stm, templateHaskell, terminfo, text, time, touchy, transformers,
unlit, unix, win32, xhtml, ghcPackages, isGhcPackage, defaultPackages,
filepath, genapply, genprimopcode, ghc, ghcBoot, ghcBootTh, ghcCompact,
ghcHeap, ghci, ghcPkg, ghcPrim, ghcTags, ghcSplit, haddock, haskeline,
hsc2hs, hp2ps, hpc, hpcBin, integerGmp, integerSimple, iserv, libffi,
libiserv, mtl, parsec, parallel, pretty, primitive, process, rts, runGhc,
stm, templateHaskell, terminfo, text, time, touchy, transformers, unlit,
unix, win32, xhtml, ghcPackages, isGhcPackage, defaultPackages,
testsuitePackages,
-- * Package information
......@@ -157,20 +157,17 @@ programPath context@Context {..} = do
pgm <- programName context
return $ path -/- pgm <.> exe
-- | Some contexts are special: their packages do not have @.cabal@ metadata or
-- we cannot run @ghc-cabal@ on them, e.g. because the latter hasn't been built
-- yet (this is the case with the 'ghcCabal' package in 'Stage0').
-- TODO: This is no longer true -- both @hp2ps@ and @touchy@ appear to have been
-- Cabal-ised, so we need to drop these special cases.
-- | Some contexts are special: their packages do not have @.cabal@ metadata.
nonCabalContext :: Context -> Bool
nonCabalContext Context {..} = (package `elem` [ hp2ps
, touchy
])
|| package == ghcCabal && stage == Stage0
nonCabalContext Context {..} = (package `elem` [hp2ps, touchy])
-- | Some program packages should not be linked with Haskell main function.
nonHsMainPackage :: Package -> Bool
nonHsMainPackage = (`elem` [ghc, hp2ps, iserv, touchy, unlit])
-- | Path to the autogen directory generated by @ghc-cabal@ of a given 'Context'.
-- | Path to the @autogen@ directory generated when configuring a package.
autogenPath :: Context -> Action FilePath
autogenPath context@Context {..}
| isLibrary package = autogen "build"
......
......@@ -44,7 +44,6 @@ genprimopcode = hsUtil "genprimopcode"
ghc = hsPrg "ghc-bin" `setPath` "ghc"
ghcBoot = hsLib "ghc-boot"
ghcBootTh = hsLib "ghc-boot-th"
ghcCabal = hsUtil "ghc-cabal"
ghcCompact = hsLib "ghc-compact"
ghcHeap = hsLib "ghc-heap"
ghci = hsLib "ghci"
......
......@@ -17,19 +17,19 @@ import Data.Maybe
import Development.Shake
import Context.Type
import Hadrian.Haskell.Cabal.Type
import Hadrian.Haskell.Cabal.CabalData
import Hadrian.Package
import Hadrian.Oracles.TextFile
-- | Read a Cabal file and return the package version. The Cabal file is tracked.
pkgVersion :: Context -> Action (Maybe String)
pkgVersion = fmap (fmap version) . readCabalFile
pkgVersion = fmap (fmap version) . readCabalData
-- | Read a Cabal file and return the package identifier, e.g. @base-4.10.0.0@.
-- The Cabal file is tracked.
pkgIdentifier :: Context -> Action String
pkgIdentifier ctx = do
cabal <- fromMaybe (error "Cabal file could not be read") <$> readCabalFile ctx
cabal <- fromMaybe (error "Cabal file could not be read") <$> readCabalData ctx
return $ if null (version cabal)
then name cabal
else name cabal ++ "-" ++ version cabal
......@@ -39,8 +39,8 @@ pkgIdentifier ctx = do
-- returns a crude overapproximation of actual dependencies. The Cabal file is
-- tracked.
pkgDependencies :: Context -> Action (Maybe [PackageName])
pkgDependencies = fmap (fmap (map pkgName . packageDependencies)) . readCabalFile
pkgDependencies = fmap (fmap (map pkgName . packageDependencies)) . readCabalData
-- | Read a Cabal file and return the package synopsis. The Cabal file is tracked.
pkgSynopsis :: Context -> Action (Maybe String)
pkgSynopsis = fmap (fmap synopsis) . readCabalFile
pkgSynopsis = fmap (fmap synopsis) . readCabalData
module Hadrian.Haskell.Cabal.Type where
module Hadrian.Haskell.Cabal.CabalData where
import Development.Shake.Classes
import Distribution.PackageDescription (GenericPackageDescription, PackageDescription)
import Distribution.PackageDescription
import GHC.Generics
import Hadrian.Package.Type
-- | Haskell package metadata extracted from a Cabal file.
data Cabal = Cabal
-- | Haskell package metadata extracted from a Cabal file, without performing
-- the resolution of package configuration flags and associated conditionals.
-- One consequence is that 'packageDependencies' is an overappoximation of
-- actual package dependencies; for example, both @unix@ and @win32@ packages
-- may be included even if only one of them is required on the target OS.
data CabalData = CabalData
{ name :: PackageName
, version :: String
, synopsis :: String
......@@ -15,9 +19,6 @@ data Cabal = Cabal
, packageDependencies :: [Package]
} deriving (Eq, Show, Typeable, Generic)
instance Binary Cabal
instance Hashable Cabal where
hashWithSalt salt = hashWithSalt salt . show
instance NFData Cabal
instance Binary CabalData
instance Hashable CabalData where hashWithSalt salt = hashWithSalt salt . show
instance NFData CabalData
module Hadrian.Haskell.Cabal.PackageData where
import Development.Shake.Classes
import Hadrian.Package.Type
import GHC.Generics
import Hadrian.Package.Type
-- | Most of these fields used to be provided in @package-data.mk@ files.
data PackageData = PackageData
......
......@@ -9,10 +9,10 @@
--
-- Extracting Haskell package metadata stored in Cabal files.
-----------------------------------------------------------------------------
module Hadrian.Haskell.Cabal.Parse
( PackageData (..), parseCabal, parsePackageData, parseCabalPkgId
, configurePackage, copyPackage, registerPackage
) where
module Hadrian.Haskell.Cabal.Parse (
PackageData (..), parseCabalFile, parsePackageData, parseCabalPkgId,
configurePackage, copyPackage, registerPackage
) where
import Data.List.Extra
import Development.Shake
......@@ -44,8 +44,8 @@ import Context
import Flavour
import GHC.Packages
import Hadrian.Expression
import Hadrian.Haskell.Cabal.CabalData
import Hadrian.Haskell.Cabal.PackageData
import Hadrian.Haskell.Cabal.Type
import Hadrian.Oracles.TextFile
import Hadrian.Target
import Settings
......@@ -81,8 +81,8 @@ biModules pd = go [ comp | comp@(bi,_,_) <-
-- corresponding to the 'Stage' it gets from the 'Context', and finalises the
-- package description it got from the Cabal file with additional information
-- such as platform, compiler version conditionals, and package flags.
parseCabal :: Context -> Action Cabal
parseCabal context@Context {..} = do
parseCabalFile :: Context -> Action CabalData
parseCabalFile context@Context {..} = do
let file = unsafePkgCabalFile package
-- Read the package description from the Cabal file
......@@ -93,7 +93,7 @@ parseCabal context@Context {..} = do
(compiler, Just platform, _pgdb) <- liftIO $
C.configure C.silent (Just hcPath) Nothing C.emptyProgramDb
flagList <- interpret (target context (CabalFlags stage) [] []) =<< args <$> flavour
flagList <- interpret (target context (Cabal Flags stage) [] []) =<< args <$> flavour
let flags = foldr addFlag mempty flagList
where
addFlag :: String -> C.FlagAssignment -> C.FlagAssignment
......@@ -111,19 +111,20 @@ parseCabal context@Context {..} = do
findPackageByName' p = fromMaybe (error msg) (findPackageByName p)
where
msg = "Failed to find package " ++ quote (show p)
return $ Cabal (C.unPackageName . C.pkgName . C.package $ pd)
(C.display . C.pkgVersion . C.package $ pd)
(C.synopsis pd) gpd pd depPkgs
return $ CabalData (C.unPackageName . C.pkgName . C.package $ pd)
(C.display . C.pkgVersion . C.package $ pd)
(C.synopsis pd) gpd pd depPkgs
-- | This function runs the equivalent of @cabal configure@ using the Cabal
-- library directly, collecting all the configuration options and flags to be
-- passed to Cabal before invoking it. It 'need's package database entries for
-- the dependencies of the package the 'Context' points to.
-- TODO: Track command line arguments and package configuration flags.
-- | Configure a package using the Cabal library by collecting all the command
-- line arguments (to be passed to the setup script) and package configuration
-- flags. The function 'need's package database entries for the dependencies of
-- the package the 'Context' points to.
configurePackage :: Context -> Action ()
configurePackage context@Context {..} = do
putLoud $ "| Configure package " ++ quote (pkgName package)
Cabal _ _ _ gpd _pd depPkgs <- unsafeReadCabalFile context
CabalData _ _ _ gpd _pd depPkgs <- unsafeReadCabalData context
-- Stage packages are those we have in this stage.
stagePkgs <- stagePackages stage
......@@ -152,8 +153,8 @@ configurePackage context@Context {..} = do
-- Compute the list of flags
-- Compute the Cabal configurartion arguments
flavourArgs <- args <$> flavour
flagList <- interpret (target context (CabalFlags stage) [] []) flavourArgs
argList <- interpret (target context (GhcCabal Conf stage) [] []) flavourArgs
flagList <- interpret (target context (Cabal Flags stage) [] []) flavourArgs
argList <- interpret (target context (Cabal Setup stage) [] []) flavourArgs
verbosity <- getVerbosity
let v = if verbosity >= Loud then "-v3" else "-v0"
liftIO $ C.defaultMainWithHooksNoReadArgs hooks gpd
......@@ -164,7 +165,7 @@ configurePackage context@Context {..} = do
copyPackage :: Context -> Action ()
copyPackage context@Context {..} = do
putLoud $ "| Copy package " ++ quote (pkgName package)
Cabal _ _ _ gpd _ _ <- unsafeReadCabalFile context
CabalData _ _ _ gpd _ _ <- unsafeReadCabalData context
ctxPath <- Context.contextPath context
pkgDbPath <- packageDbPath stage
verbosity <- getVerbosity
......@@ -177,7 +178,7 @@ registerPackage :: Context -> Action ()
registerPackage context@Context {..} = do
putLoud $ "| Register package " ++ quote (pkgName package)
ctxPath <- Context.contextPath context
Cabal _ _ _ gpd _ _ <- unsafeReadCabalFile context
CabalData _ _ _ gpd _ _ <- unsafeReadCabalData context
verbosity <- getVerbosity
let v = if verbosity >= Loud then "-v3" else "-v0"
liftIO $ C.defaultMainWithHooksNoReadArgs C.autoconfUserHooks gpd
......@@ -194,7 +195,7 @@ parsePackageData context@Context {..} = do
-- let (Right (pd,_)) = C.finalizePackageDescription flags (const True) platform (compilerInfo compiler) [] gpd
--
-- However when using the new-build path's this might change.
Cabal _ _ _ _gpd pd _depPkgs <- unsafeReadCabalFile context
CabalData _ _ _ _gpd pd _depPkgs <- unsafeReadCabalData context
cPath <- Context.contextPath context
need [cPath -/- "setup-config"]
......
module Hadrian.Haskell.Cabal.Parse where
import Context.Type (Context)
import Development.Shake (Action)
import Hadrian.Haskell.Cabal.PackageData (PackageData)
import Hadrian.Haskell.Cabal.Type (Cabal)
parseCabal :: Context -> Action Cabal
parsePackageData :: Context -> Action PackageData
{-# LANGUAGE TypeFamilies #-}
-----------------------------------------------------------------------------
-- |
-- Module : Hadrian.Oracles.TextFile
-- Copyright : (c) Andrey Mokhov 2014-2017
-- Copyright : (c) Andrey Mokhov 2014-2018
-- License : MIT (see the file LICENSE)
-- Maintainer : andrey.mokhov@gmail.com
-- Stability : experimental
--
-- Read and parse text files, tracking their contents. This oracle can be used
-- to read configuration or package metadata files and cache the parsing.
-- This module exports various oracle queries, whereas the corresponing Shake
-- rules can be found in "Hadrian.Oracles.TextFile.Rules".
-----------------------------------------------------------------------------
module Hadrian.Oracles.TextFile (
readTextFile, lookupValue, lookupValueOrEmpty, lookupValueOrError,
lookupValues, lookupValuesOrEmpty, lookupValuesOrError, lookupDependencies,
readCabalFile, unsafeReadCabalFile, readPackageDataFile, textFileOracle
readCabalData, unsafeReadCabalData, readPackageData
) where
import Control.Monad
import qualified Data.HashMap.Strict as Map
import Data.Maybe
import Development.Shake
import Development.Shake.Classes
import Development.Shake.Config
import GHC.Stack
import Context.Type
import Hadrian.Haskell.Cabal.CabalData
import Hadrian.Haskell.Cabal.PackageData
import Hadrian.Haskell.Cabal.Type
import {-# SOURCE #-} Hadrian.Haskell.Cabal.Parse
import Hadrian.Package
import Hadrian.Oracles.TextFile.Type
import Hadrian.Utilities
import Stage
newtype TextFile = TextFile FilePath
deriving (Binary, Eq, Hashable, NFData, Show, Typeable)
type instance RuleResult TextFile = String
newtype CabalFile = CabalFile Context
deriving (Binary, Eq, Hashable, NFData, Show, Typeable)
type instance RuleResult CabalFile = Maybe Cabal
newtype PackageDataFile = PackageDataFile Context
deriving (Binary, Eq, Hashable, NFData, Show, Typeable)
type instance RuleResult PackageDataFile = Maybe PackageData
newtype KeyValue = KeyValue (FilePath, String)
deriving (Binary, Eq, Hashable, NFData, Show, Typeable)
type instance RuleResult KeyValue = Maybe String
newtype KeyValues = KeyValues (FilePath, String)
deriving (Binary, Eq, Hashable, NFData, Show, Typeable)
type instance RuleResult KeyValues = Maybe [String]
-- | Read a text file, caching and tracking the result. To read and track
-- individual lines of a text file use 'lookupValue' and its derivatives.
......@@ -100,57 +75,17 @@ lookupDependencies depFile file = do
Just (source : files) -> return (source, files)
-- | Read and parse a @.cabal@ file, caching and tracking the result.
readCabalFile :: Context -> Action (Maybe Cabal)
readCabalFile = askOracle . CabalFile
readCabalData :: Context -> Action (Maybe CabalData)
readCabalData = askOracle . CabalFile
-- | Like 'readCabalFile' but raises an error on a non-Cabal context.
unsafeReadCabalFile :: HasCallStack => Context -> Action Cabal
unsafeReadCabalFile context = fromMaybe (error msg) <$> readCabalFile context
-- | Like 'readCabalData' but raises an error on a non-Cabal context.
unsafeReadCabalData :: HasCallStack => Context -> Action CabalData
unsafeReadCabalData context = fromMaybe (error msg) <$> readCabalData context
where
msg = "[unsafeReadCabalFile] Non-Cabal context: " ++ show context
readPackageDataFile :: Context -> Action (Maybe PackageData)
readPackageDataFile = askOracle . PackageDataFile
-- | This oracle reads and parses text files to answer 'readTextFile' and
-- 'lookupValue' queries, as well as their derivatives, tracking the results.
textFileOracle :: Rules ()
textFileOracle = do
text <- newCache $ \file -> do
need [file]
putLoud $ "| TextFile oracle: reading " ++ quote file ++ "..."
liftIO $ readFile file
void $ addOracle $ \(TextFile file) -> text file
kv <- newCache $ \file -> do
need [file]
putLoud $ "| KeyValue oracle: reading " ++ quote file ++ "..."
liftIO $ readConfigFile file
void $ addOracle $ \(KeyValue (file, key)) -> Map.lookup key <$> kv file
kvs <- newCache $ \file -> do
need [file]
putLoud $ "| KeyValues oracle: reading " ++ quote file ++ "..."
contents <- map words <$> readFileLines file
return $ Map.fromList [ (key, values) | (key:values) <- contents ]
void $ addOracle $ \(KeyValues (file, key)) -> Map.lookup key <$> kvs file
cabal <- newCache $ \(ctx@Context {..}) ->
case pkgCabalFile package of
Just file -> do
need [file]
putLoud $ "| CabalFile oracle: reading " ++ quote file
++ " (Stage: " ++ stageString stage ++ ")..."
Just <$> parseCabal ctx
Nothing -> return Nothing