.bat file tidy up plus shake-0.16 compatibility (#392)
[hadrian.git] / src / Hadrian / Oracles / FileCache.hs
1 {-# LANGUAGE TypeFamilies #-}
2 -----------------------------------------------------------------------------
3 -- |
4 -- Module : Hadrian.Oracles.FileCache
5 -- Copyright : (c) Andrey Mokhov 2014-2017
6 -- License : MIT (see the file LICENSE)
7 -- Maintainer : andrey.mokhov@gmail.com
8 -- Stability : experimental
9 --
10 -- Build and read text file caches. File caches can be used to cache expensive
11 -- computations whose results are not expected to change between builds. One
12 -- example is parsing package @.cabal@ files to determine all inter-package
13 -- dependencies. Use "Hadrian.Oracles.KeyValue" to read and track individual
14 -- lines in text file caches.
15 -----------------------------------------------------------------------------
16 module Hadrian.Oracles.FileCache (readFileCache, fileCacheRules) where
17
18 import Control.Monad
19 import Development.Shake
20 import Development.Shake.Classes
21
22 import Hadrian.Utilities
23
24 newtype FileCache = FileCache FilePath
25 deriving (Binary, Eq, Hashable, NFData, Show, Typeable)
26 type instance RuleResult FileCache = String
27
28 -- | Read a text file, caching and tracking the result. To read and track
29 -- individual lines of the file, see "Hadrian.Oracles.KeyValue".
30 readFileCache :: FilePath -> Action String
31 readFileCache = askOracle . FileCache
32
33 -- | This oracle builds text files using supplied generators and caches access
34 -- to them to efficiently answer 'readFileCache' queries, tracking the results.
35 -- The argument is a list of pairs @(pattern, generator)@, where @pattern@
36 -- describes the files that can be built using the corresponding @generator@
37 -- action. The latter takes a specific file path to be generated as the input.
38 fileCacheRules :: [(FilePattern, FilePath -> Action String)] -> Rules ()
39 fileCacheRules patternGenerators = do
40 -- Generate file contents
41 forM_ patternGenerators $ \(pattern, generate) ->
42 pattern %> \file -> do
43 contents <- generate file
44 writeFileChanged file contents
45 putSuccess $ "| Successfully generated " ++ file
46 -- Cache file reading
47 cache <- newCache $ \file -> do
48 need [file]
49 putLoud $ "Reading " ++ file ++ "..."
50 liftIO $ readFile file
51 void $ addOracle $ \(FileCache file) -> cache file