-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | Build system library, like Make, but more accurate dependencies. -- -- Shake is a Haskell library for writing build systems - designed as a -- replacement for make. See Development.Shake for an -- introduction, including an example. Further examples are included in -- the Cabal tarball, under the Examples directory. -- -- To use Shake the user writes a Haskell program that imports the Shake -- library, defines some build rules, and calls shake. Thanks to -- do notation and infix operators, a simple Shake program is not too -- dissimilar from a simple Makefile. However, as build systems get more -- complex, Shake is able to take advantage of the excellent abstraction -- facilities offered by Haskell and easily support much larger projects. -- -- The Shake library provides all the standard features available in -- other build systems, including automatic parallelism and minimal -- rebuilds. Shake provides highly accurate dependency tracking, -- including seamless support for generated files, and dependencies on -- system information (i.e. compiler version). Shake can produce profile -- reports, indicating which files and take longest to build, and -- providing an analysis of the parallelism. -- -- The theory behind Shake is described in an ICFP 2012 paper, Shake -- Before Building -- Replacing Make with Haskell -- http://community.haskell.org/~ndm/downloads/paper-shake_before_building-10_sep_2012.pdf. -- The associated talk forms a short overview of Shake -- http://www.youtube.com/watch?v=xYCPpXVlqFM. @package shake @version 0.4 -- | A module for FilePath operations, to be used instead of -- System.FilePath when writing build systems. In build systems, -- when using the file name as a key for indexing rules, it is important -- that two different strings do not refer to the same on-disk file. We -- therefore follow the conventions: -- --
-- dropDirectory1 "aaa/bbb" == "bbb" -- dropDirectory1 "aaa/" == "" -- dropDirectory1 "aaa" == "" -- dropDirectory1 "" == "" --dropDirectory1 :: FilePath -> FilePath -- | Take the first component of a FilePath. Should only be used on -- relative paths. -- --
-- takeDirectory1 "aaa/bbb" == "aaa" -- takeDirectory1 "aaa/" == "aaa" -- takeDirectory1 "aaa" == "aaa" --takeDirectory1 :: FilePath -> FilePath -- | Normalise a FilePath, applying the standard FilePath -- normalisation, plus translating any path separators to / and -- removing foo/.. components where possible. normalise :: FilePath -> FilePath -- | Convert to native path separators, namely \ on Windows. toNative :: FilePath -> FilePath -- | Combine two file paths, an alias for combine. (>) :: FilePath -> FilePath -> FilePath -- | Combine two file paths. Any leading ./ or ../ -- components in the right file are eliminated. -- --
-- combine "aaa/bbb" "ccc" == "aaa/bbb/ccc" -- combine "aaa/bbb" "./ccc" == "aaa/bbb/ccc" -- combine "aaa/bbb" "../ccc" == "aaa/ccc" --combine :: FilePath -> FilePath -> FilePath -- | This module is used for defining Shake build systems. As a simple -- example of a Shake build system, let us build the file -- result.tar from the files listed by result.txt: -- --
-- import Development.Shake -- import Development.Shake.FilePath -- -- main = shake shakeOptions $ do -- want ["result.tar"] -- "*.tar" *> \out -> do -- contents <- readFileLines $ replaceExtension out "txt" -- need contents -- system' "tar" $ ["-cf",out] ++ contents ---- -- We start by importing the modules defining both Shake and routines for -- manipulating FilePath values. We define main to call -- shake with the default shakeOptions. As the second -- argument to shake, we provide a set of rules. There are two -- common forms of rules, want to specify target files, and -- *> to define a rule which builds a FilePattern. We -- use want to require that after the build completes the file -- result.tar should be ready. -- -- The *.tar rule describes how to build files with the -- extension .tar, including result.tar. We -- readFileLines on result.txt, after changing the -- .tar extension to .txt. We read each line into the -- variable contents -- being a list of the files that should go -- into result.tar. Next, we depend (need) all the files -- in contents. If any of these files change, the rule will be -- repeated. Finally we call the tar program. If either -- result.txt changes, or any of the files listed by -- result.txt change, then result.tar will be rebuilt. -- -- When writing a Shake build system, start by defining what you -- want, then write rules with *> to produce the -- results. Before calling system' you should ensure that any -- files the command requires are demanded with calls to need. We -- offer the following advice to Shake users: -- --
-- shakeOptions{shakeThreads=4, shakeReport=Just "report.html"}
--
--
-- The Data instance for this type reports the
-- shakeProgress field as having the abstract type
-- ShakeProgress, because Data cannot be defined for
-- functions.
data ShakeOptions
ShakeOptions :: FilePath -> Int -> Int -> Verbosity -> Bool -> Maybe FilePath -> Bool -> Bool -> Maybe Double -> Maybe Assume -> (IO Progress -> IO ()) -> ShakeOptions
-- | Defaults to .shake. The prefix of the filename used for
-- storing Shake metadata files. All metadata files will be named
-- shakeFiles.extension, for some
-- extension.
shakeFiles :: ShakeOptions -> FilePath
-- | Defaults to 1. Maximum number of rules to run in parallel,
-- similar to make --jobs=N. To enable parallelism you
-- may need to compile with -threaded. For many build systems, a
-- number equal to or slightly less than the number of physical
-- processors works well.
shakeThreads :: ShakeOptions -> Int
-- | Defaults to 1. The version number of your build rules.
-- Increment the version number to force a complete rebuild, such as when
-- making significant changes to the rules that require a wipe. The
-- version number should be set in the source code, and not passed on the
-- command line.
shakeVersion :: ShakeOptions -> Int
-- | Defaults to Normal. What level of messages should be printed
-- out.
shakeVerbosity :: ShakeOptions -> Verbosity
-- | Defaults to False. Operate in staunch mode, where building
-- continues even after errors, similar to make --keep-going.
shakeStaunch :: ShakeOptions -> Bool
-- | Defaults to Nothing. Write an HTML profiling report to a file,
-- showing which rules rebuilt, why, and how much time they took. Useful
-- for improving the speed of your build systems.
shakeReport :: ShakeOptions -> Maybe FilePath
-- | Defaults to False. Perform basic sanity checks after building,
-- checking files have not been modified several times during the build.
-- These sanity checks fail to catch most interesting errors.
shakeLint :: ShakeOptions -> Bool
-- | Defaults to False. Run rules in a deterministic order, as far
-- as possible. Typically used in conjunction with
-- shakeThreads=1 for reproducing a build. If this field
-- is set to False, Shake will run rules in a random order, which
-- typically decreases contention for resources and speeds up the build.
shakeDeterministic :: ShakeOptions -> Bool
-- | Defaults to Just 10. How often to flush Shake metadata
-- files in seconds, or Nothing to never flush explicitly. It is
-- possible that on abnormal termination (not Haskell exceptions) any
-- rules that completed in the last shakeFlush seconds will be
-- lost.
shakeFlush :: ShakeOptions -> Maybe Double
-- | Defaults to Nothing. Assume all build objects are clean/dirty,
-- see Assume for details. Can be used to implement make
-- --touch.
shakeAssume :: ShakeOptions -> Maybe Assume
-- | Defaults to no action. A function called when the build starts,
-- allowing progress to be reported, see Progress for details.
shakeProgress :: ShakeOptions -> IO Progress -> IO ()
-- | The default set of ShakeOptions.
shakeOptions :: ShakeOptions
-- | The current assumptions made by the build system, used by
-- shakeAssume. These options allow the end user to specify that
-- any rules run are either to be treated as clean, or as dirty,
-- regardless of what the build system thinks.
--
-- These assumptions only operate on files reached by the current
-- action commands. Any other files in the database are left
-- unchanged.
data Assume
-- | Assume that all rules reached are dirty and require rebuilding,
-- equivalent to storedValue always returning Nothing.
-- Useful to undo the results of AssumeClean, for benchmarking
-- rebuild speed and for rebuilding if untracked dependencies have
-- changed. This assumption is safe, but may cause more rebuilding than
-- necessary.
AssumeDirty :: Assume
-- | This assumption is unsafe, and may lead to incorrect build
-- results. Assume that all rules reached are clean and do not
-- require rebuilding, provided the rule has a storedValue and
-- has been built before. Useful if you have modified a file in some
-- inconsequential way, such as only the comments or whitespace, and wish
-- to avoid a rebuild.
AssumeClean :: Assume
-- | Information about the current state of the build, obtained by passing
-- a callback function to shakeProgress. Typically a program will
-- poll this value to provide progress messages. The following example
-- displays the approximate single-threaded time remaining as the console
-- title.
--
-- -- showProgress :: IO Progress -> IO () -- showProgress progress = void $ forkIO loop -- where loop = do -- current <- progress -- when (isRunning current) $ do -- let (s,c) = timeTodo current -- setTitle $ "Todo = " ++ show (ceiling s) ++ "s (+ " ++ show c ++ " unknown)" -- threadDelay $ 5 * 1000000 -- loop -- -- setTitle :: String -> IO () -- setTitle s = putStr $ "\ESC]0;" ++ s ++ "\BEL" --data Progress Progress :: !Bool -> {-# UNPACK #-} !Int -> {-# UNPACK #-} !Int -> {-# UNPACK #-} !Int -> {-# UNPACK #-} !Int -> {-# UNPACK #-} !Double -> {-# UNPACK #-} !Double -> {-# UNPACK #-} !Double -> {-# UNPACK #-} !(Double, Int) -> Progress -- | Starts out True, becomes False once the build has -- completed. isRunning :: Progress -> !Bool -- | Number of rules which were required, but were already in a valid -- state. countSkipped :: Progress -> {-# UNPACK #-} !Int -- | Number of rules which were have been built in this run. countBuilt :: Progress -> {-# UNPACK #-} !Int -- | Number of rules which have been built previously, but are not yet -- known to be required. countUnknown :: Progress -> {-# UNPACK #-} !Int -- | Number of rules which are currently required (ignoring dependencies -- that do not change), but not built. countTodo :: Progress -> {-# UNPACK #-} !Int -- | Time spent building countSkipped rules in previous runs. timeSkipped :: Progress -> {-# UNPACK #-} !Double -- | Time spent building countBuilt rules. timeBuilt :: Progress -> {-# UNPACK #-} !Double -- | Time spent building countUnknown rules in previous runs. timeUnknown :: Progress -> {-# UNPACK #-} !Double -- | Time spent building countTodo rules in previous runs, plus the -- number which have no known time (have never been built before). timeTodo :: Progress -> {-# UNPACK #-} !(Double, Int) -- | Define a pair of types that can be used by Shake rules. class (Show key, Typeable key, Eq key, Hashable key, Binary key, NFData key, Show value, Typeable value, Eq value, Hashable value, Binary value, NFData value) => Rule key value | key -> value storedValue :: Rule key value => key -> IO (Maybe value) -- | Define a set of rules. Rules can be created with calls to rule, -- defaultRule or action. Rules are combined with either -- the Monoid instance, or (more commonly) the Monad -- instance and do notation. data Rules a -- | Like rule, but lower priority, if no rule exists then -- defaultRule is checked. All default rules must be disjoint. defaultRule :: Rule key value => (key -> Maybe (Action value)) -> Rules () -- | Add a rule to build a key, returning an appropriate Action. All -- rules must be disjoint. To define lower priority rules use -- defaultRule. rule :: Rule key value => (key -> Maybe (Action value)) -> Rules () -- | Run an action, usually used for specifying top-level requirements. action :: Action a -> Rules () -- | Remove all actions specified in a set of rules, usually used for -- implementing command line specification of what to build. withoutActions :: Rules () -> Rules () -- | The Action monad, use liftIO to raise IO actions -- into it, and need to execute files. Action values are used by -- rule and action. data Action a -- | Execute a rule, returning the associated values. If possible, the -- rules will be run in parallel. This function requires that appropriate -- rules have been added with rule or defaultRule. apply :: Rule key value => [key] -> Action [value] -- | Apply a single rule, equivalent to calling apply with a -- singleton list. Where possible, use apply to allow parallelism. apply1 :: Rule key value => key -> Action value -- | Write an action to the trace list, along with the start/end time of -- running the IO action. The system' command automatically calls -- traced. The trace list is used for profile reports (see -- shakeReport). traced :: String -> IO a -> Action a -- | The verbosity data type, used by shakeVerbosity. data Verbosity -- | Don't print any messages. Silent :: Verbosity -- | Only print essential messages (typically errors). Quiet :: Verbosity -- | Print normal messages (typically errors and warnings). Normal :: Verbosity -- | Print lots of messages (typically errors, warnings and status -- updates). Loud :: Verbosity -- | Print messages for virtually everything (for debugging a build -- system). Diagnostic :: Verbosity -- | Get the current verbosity level, as set by shakeVerbosity. If -- you want to output information to the console, you are recommended to -- use putLoud / putNormal / putQuiet, which ensures -- multiple messages are not interleaved. getVerbosity :: Action Verbosity -- | Write a message to the output when the verbosity -- (shakeVerbosity) is appropriate. The output will not be -- interleaved with any other Shake messages (other than those generated -- by system commands). putLoud :: String -> Action () -- | Write a message to the output when the verbosity -- (shakeVerbosity) is appropriate. The output will not be -- interleaved with any other Shake messages (other than those generated -- by system commands). putNormal :: String -> Action () -- | Write a message to the output when the verbosity -- (shakeVerbosity) is appropriate. The output will not be -- interleaved with any other Shake messages (other than those generated -- by system commands). putQuiet :: String -> Action () -- | Lift a computation from the IO monad. liftIO :: MonadIO m => forall a. IO a -> m a -- | Execute a system command. This function will raise an error if the -- exit code is non-zero. Before running system' make sure you -- need any required files. system' :: FilePath -> [String] -> Action () -- | Execute a system command with a specified current working directory -- (first argument). This function will raise an error if the exit code -- is non-zero. Before running systemCwd make sure you need -- any required files. -- --
-- systemCwd "/usr/MyDirectory" "pwd" [] --systemCwd :: FilePath -> FilePath -> [String] -> Action () -- | Execute a system command, returning (stdout,stderr). This -- function will raise an error if the exit code is non-zero. Before -- running systemOutput make sure you need any required -- files. systemOutput :: FilePath -> [String] -> Action (String, String) -- | copyFile old new copies the existing file from old -- to new. The old file is has need called on it -- before copying the file. copyFile' :: FilePath -> FilePath -> Action () -- | Read a file, after calling need. readFile' :: FilePath -> Action String -- | Write a file, lifted to the Action monad. writeFile' :: FilePath -> String -> Action () -- | A version of readFile' which also splits the result into lines. readFileLines :: FilePath -> Action [String] -- | A version of writeFile' which writes out a list of lines. writeFileLines :: FilePath -> [String] -> Action () -- | Write a file, but only if the contents would change. writeFileChanged :: FilePath -> String -> Action () -- | Require that the following files are built before continuing. -- Particularly necessary when calling system'. As an example: -- --
-- "*.rot13" *> \out -> do -- let src = dropExtension out -- need [src] -- system' ["rot13",src,"-o",out] --need :: [FilePath] -> Action () -- | Require that the following are built by the rules, used to specify the -- target. -- --
-- main = shake shakeOptions $ do -- want ["Main.exe"] -- ... ---- -- This program will build Main.exe, given sufficient rules. want :: [FilePath] -> Rules () -- | Define a rule that matches a FilePattern. No file required by -- the system must be matched by more than one pattern. For the pattern -- rules, see ?==. -- --
-- "*.asm.o" *> \out -> do -- let src = dropExtension out -- need [src] -- system' ["as",src,"-o",out] ---- -- To define a build system for multiple compiled languages, we recommend -- using .asm.o, .cpp.o, .hs.o, to indicate -- which language produces an object file. I.e., the file -- foo.cpp produces object file foo.cpp.o. -- -- Note that matching is case-sensitive, even on Windows. (*>) :: FilePattern -> (FilePath -> Action ()) -> Rules () -- | Define a set of patterns, and if any of them match, run the associated -- rule. See *>. (**>) :: [FilePattern] -> (FilePath -> Action ()) -> Rules () -- | Define a rule to build files. If the first argument returns -- True for a given file, the second argument will be used to -- build it. Usually *> is sufficient, but ?> gives -- additional power. For any file used by the build system, only one rule -- should return True. -- --
-- (all isUpper . takeBaseName) ?> \out -> do -- let src = replaceBaseName out $ map toLower $ takeBaseName out -- writeFile' . map toUpper =<< readFile' src --(?>) :: (FilePath -> Bool) -> (FilePath -> Action ()) -> Rules () -- | Define a rule for building multiple files at the same time, a more -- powerful and more dangerous version of *>>. -- -- Given an application test ?>> ..., test should -- return Just if the rule applies, and should return the list -- of files that will be produced. This list must include the file -- passed as an argument and should obey the invariant: -- --
-- test x == Just ys ==> x `elem` ys && all ((== Just ys) . test) ys ---- -- As an example of a function satisfying the invariaint: -- --
-- test x | takeExtension x `elem` [".hi",".o"] -- = Just [dropExtension x <.> "hi", dropExtension x <.> "o"] -- test _ = Nothing ---- -- Regardless of whether Foo.hi or Foo.o is passed, the -- function always returns [Foo.hi, Foo.o]. (?>>) :: (FilePath -> Maybe [FilePath]) -> ([FilePath] -> Action ()) -> Rules () -- | Define a rule for building multiple files at the same time. As an -- example, a single invokation of GHC produces both .hi and -- .o files: -- --
-- ["*.o","*.hi"] *>> \[o,hi] -> do -- let hs = replaceExtension o "hs" -- need ... -- all files the .hs import -- system' "ghc" ["-c",hs] ---- -- However, in practice, it's usually easier to define rules with -- *> and make the .hi depend on the .o. When -- defining rules that build multiple files, all the FilePattern -- values must have the same sequence of // and * -- wildcards in the same order. (*>>) :: [FilePattern] -> ([FilePath] -> Action ()) -> Rules () -- | A type synonym for file patterns, containing // and -- *. For the syntax and semantics of FilePattern see -- ?==. type FilePattern = String -- | Match a FilePattern against a FilePath, There are only -- two special forms: -- --
-- "//*.c" ?== "foo/bar/baz.c" -- "*.c" ?== "baz.c" -- "//*.c" ?== "baz.c" -- "test.c" ?== "test.c" ---- -- Examples that don't match: -- --
-- "*.c" ?== "foo/bar.c" -- "*/*.c" ?== "foo/bar/baz.c" --(?==) :: FilePattern -> FilePath -> Bool -- | Returns True if the file exists. doesFileExist :: FilePath -> Action Bool -- | Get the contents of a directory. The result will be sorted, and will -- not contain the files . or .. (unlike the standard -- Haskell version). It is usually better to call either -- getDirectoryFiles or getDirectoryDirs. The resulting -- paths will be relative to the first argument. getDirectoryContents :: FilePath -> Action [FilePath] -- | Get the files in a directory that match a particular pattern. For the -- interpretation of the pattern see ?==. getDirectoryFiles :: FilePath -> FilePattern -> Action [FilePath] -- | Get the directories contained by a directory, does not include -- . or ... getDirectoryDirs :: FilePath -> Action [FilePath] -- | Add extra information which your build should depend on. For example: -- --
-- addOracle ["ghc"] $ return ["7.2.1"] -- addOracle ["ghc-pkg","shake"] $ return ["1.0"] ---- -- If a rule depends on the GHC version, it can then use -- askOracle ["ghc"], and if the GHC version changes, the -- rule will rebuild. It is common for the value returned by -- askOracle to be ignored. -- -- The Oracle maps questions of [String] to answers of -- [String]. This type is a compromise. Questions will often be -- the singleton list, but allowing a list of strings allows hierarchical -- schemes such as ghc-pkg shake, ghc-pkg base etc. The -- answers are often singleton lists, but sometimes are used as sets - -- for example the list of packages returned by ghc-pkg. -- -- Actions passed to addOracle will be run in every Shake -- execution they are required, their value will not be kept between -- runs. To get a similar behaviour using files, see alwaysRerun. addOracle :: [String] -> Action [String] -> Rules () -- | Add a function to generate an oracle, matching a prefix. -- --
-- addOracles ["reverse"] $ \xs -> return $ reverse xs --addOracles :: [String] -> ([String] -> Action [String]) -> Rules () -- | Get information previously added with addOracle. askOracle :: [String] -> Action [String] -- | Always rerun the associated action. Useful for defining rules that -- query the environment. For example: -- --
-- "ghcVersion.txt" *> \out -> do -- alwaysRerun -- (stdout,_) <- systemOutput "ghc" ["--version"] -- writeFileChanged out stdout --alwaysRerun :: Action () -- | The type representing a finite resource, which multiple build actions -- should respect. Created with newResource in the IO monad -- before calling shake, and used with withResource in the -- Action monad when defining rules. -- -- As an example, only one set of calls to the Excel API can occur at one -- time, therefore Excel is a finite resource of quantity 1. You can -- write: -- --
-- do excel <- newResource "Excel" 1
-- shake shakeOptions{shakeThreads=2} $ do
-- want ["a.xls","b.xls"]
-- "*.xls" *> \out ->
-- withResource excel 1 $
-- system' "excel" [out,...]
--
--
-- Now the two calls to excel will not happen in parallel. Using
-- Resource is better than MVar as it will not block any
-- other threads from executing. Be careful that the actions run within
-- withResource do not themselves require further quantities of
-- this resource, or you may get a "thread blocked indefinitely in an
-- MVar operation" exception. Typically only system commands (such as
-- system') will be run inside withResource, not commands
-- such as need.
--
-- As another example, calls to compilers are usually CPU bound but calls
-- to linkers are usually disk bound. Running 8 linkers will often cause
-- an 8 CPU system to grid to a halt. We can limit ourselves to 4 linkers
-- with:
--
--
-- do disk <- newResource "Disk" 4
-- shake shakeOptions{shakeThreads=8} $ do
-- want [show i <.> "exe" | i <- [1..100]]
-- "*.exe" *> \out ->
-- withResource disk 1 $
-- system' "ld" ["-o",out,...]
-- "*.o" *> \out ->
-- system' "cl" ["-o",out,...]
--
data Resource
-- | Create a new finite resource, given a name (for error messages) and a
-- quantity of the resource that exists. For an example see
-- Resource.
newResource :: String -> Int -> IO Resource
-- | Run an action which uses part of a finite resource. For an example see
-- Resource.
withResource :: Resource -> Int -> Action a -> Action a