Development.Shake

shake-0.19.8: Build system library, like Make, but more accurate dependencies.

Safe Haskell | None
Language | Haskell2010

Development.Shake

Contents

- Writing a build system
- GHC build flags
- Other Shake modules
- Core
- Configuration
  - Command line
  - Targets
  - Progress reporting
  - Verbosity
- Running commands
- Explicit parallelism
- Utility functions
- File rules
- Directory rules
- Environment rules
- Oracle rules
- Special rules
- Resources
- Cache
- Batching
- Deprecated

Description

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 = shakeArgs shakeOptions $ do
        want ["result.tar"]
        "*.tar" %> \out -> do
            contents <- readFileLines $ out -<.> "txt"
            need contents
            cmd "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.

To find out more:

- The user manual contains a longer example and background information on how to use Shake https://www.shakebuild.com/manual.
- The home page has links to additional information https://www.shakebuild.com/, including a mailing list.
- The theory behind Shake is described in an ICFP 2012 paper, Shake Before Building -- Replacing Make with Haskell. The associated talk forms a short overview of Shake.

Synopsis

- shake :: ShakeOptions -> Rules () -> IO ()
- shakeOptions :: ShakeOptions
- data Rules a
- action :: Partial => Action a -> Rules ()
- withoutActions :: Rules a -> Rules a
- alternatives :: Rules a -> Rules a
- priority :: Double -> Rules a -> Rules a
- versioned :: Int -> Rules a -> Rules a
- data Action a
- traced :: String -> IO a -> Action a
- liftIO :: MonadIO m => IO a -> m a
- actionOnException :: Action a -> IO b -> Action a
- actionFinally :: Action a -> IO b -> Action a
- actionBracket :: IO a -> (a -> IO b) -> (a -> Action c) -> Action c
- actionCatch :: Exception e => Action a -> (e -> Action a) -> Action a
- actionRetry :: Int -> Action a -> Action a
- runAfter :: IO () -> Action ()
- data ShakeException = ShakeException {
  - shakeExceptionTarget :: String
  - shakeExceptionStack :: [String]
  - shakeExceptionInner :: SomeException
  }
- data ShakeOptions = ShakeOptions {
  - shakeFiles :: FilePath
  - shakeThreads :: Int
  - shakeVersion :: String
  - shakeVerbosity :: Verbosity
  - shakeStaunch :: Bool
  - shakeReport :: [FilePath]
  - shakeLint :: Maybe Lint
  - shakeLintInside :: [FilePath]
  - shakeLintIgnore :: [FilePattern]
  - shakeLintWatch :: [FilePattern]
  - shakeCommandOptions :: [CmdOption]
  - shakeFlush :: Maybe Seconds
  - shakeRebuild :: [(Rebuild, FilePattern)]
  - shakeAbbreviations :: [(String, String)]
  - shakeStorageLog :: Bool
  - shakeLineBuffering :: Bool
  - shakeTimings :: Bool
  - shakeRunCommands :: Bool
  - shakeChange :: Change
  - shakeCreationCheck :: Bool
  - shakeLiveFiles :: [FilePath]
  - shakeVersionIgnore :: Bool
  - shakeColor :: Bool
  - shakeShare :: Maybe FilePath
  - shakeCloud :: [String]
  - shakeSymlink :: Bool
  - shakeNeedDirectory :: Bool
  - shakeAllowRedefineRules :: Bool
  - shakeProgress :: IO Progress -> IO ()
  - shakeOutput :: Verbosity -> String -> IO ()
  - shakeTrace :: String -> String -> Bool -> IO ()
  - shakeExtra :: HashMap TypeRep Dynamic
  }
- data Rebuild
  - = RebuildNow
  - | RebuildNormal
  - | RebuildLater
- data Lint
  - = LintBasic
  - | LintFSATrace
- data Change
  - = ChangeModtime
  - | ChangeDigest
  - | ChangeModtimeAndDigest
  - | ChangeModtimeAndDigestInput
  - | ChangeModtimeOrDigest
- getShakeOptions :: Action ShakeOptions
- getShakeOptionsRules :: Rules ShakeOptions
- getHashedShakeVersion :: [FilePath] -> IO String
- getShakeExtra :: Typeable a => Action (Maybe a)
- getShakeExtraRules :: Typeable a => Rules (Maybe a)
- addShakeExtra :: Typeable a => a -> HashMap TypeRep Dynamic -> HashMap TypeRep Dynamic
- shakeArgs :: ShakeOptions -> Rules () -> IO ()
- shakeArgsWith :: ShakeOptions -> [OptDescr (Either String a)] -> ([a] -> [String] -> IO (Maybe (Rules ()))) -> IO ()
- shakeArgsOptionsWith :: ShakeOptions -> [OptDescr (Either String a)] -> (ShakeOptions -> [a] -> [String] -> IO (Maybe (ShakeOptions, Rules ()))) -> IO ()
- shakeOptDescrs :: [OptDescr (Either String (ShakeOptions -> ShakeOptions))]
- addHelpSuffix :: String -> Rules ()
- getTargets :: ShakeOptions -> Rules () -> IO [(String, Maybe String)]
- addTarget :: String -> Rules ()
- withTargetDocs :: String -> Rules () -> Rules ()
- withoutTargets :: Rules a -> Rules a
- data Progress = Progress {
  - isFailure :: !(Maybe String)
  - countSkipped :: !Int
  - countBuilt :: !Int
  - countUnknown :: !Int
  - countTodo :: !Int
  - timeSkipped :: !Double
  - timeBuilt :: !Double
  - timeUnknown :: !Double
  - timeTodo :: !(Double, Int)
  }
- progressSimple :: IO Progress -> IO ()
- progressDisplay :: Double -> (String -> IO ()) -> IO Progress -> IO ()
- progressTitlebar :: String -> IO ()
- progressProgram :: IO (String -> IO ())
- getProgress :: Action Progress
- data Verbosity
  - = Silent
  - | Error
  - | Warn
  - | Info
  - | Verbose
  - | Diagnostic
- getVerbosity :: Action Verbosity
- putVerbose :: String -> Action ()
- putInfo :: String -> Action ()
- putWarn :: String -> Action ()
- putError :: String -> Action ()
- withVerbosity :: Verbosity -> Action a -> Action a
- quietly :: Action a -> Action a
- command :: (Partial, CmdResult r) => [CmdOption] -> String -> [String] -> Action r
- command_ :: Partial => [CmdOption] -> String -> [String] -> Action ()
- cmd :: (Partial, CmdArguments args) => args :-> Action r
- cmd_ :: (Partial, CmdArguments args, Unit args) => args :-> Action ()
- unit :: m () -> m ()
- newtype Stdout a = Stdout {
  - fromStdout :: a
  }
- newtype StdoutTrim a = StdoutTrim {
  - fromStdoutTrim :: a
  }
- newtype Stderr a = Stderr {
  - fromStderr :: a
  }
- newtype Stdouterr a = Stdouterr {
  - fromStdouterr :: a
  }
- newtype Exit = Exit {
  - fromExit :: ExitCode
  }
- newtype Process = Process {
  - fromProcess :: ProcessHandle
  }
- newtype CmdTime = CmdTime {
  - fromCmdTime :: Double
  }
- newtype CmdLine = CmdLine {
  - fromCmdLine :: String
  }
- data FSATrace a
  - = FSAWrite a
  - | FSARead a
  - | FSADelete a
  - | FSAMove a a
  - | FSAQuery a
  - | FSATouch a
- class CmdResult a
- class CmdString a
- data CmdOption
  - = Cwd FilePath
  - | Env [(String, String)]
  - | AddEnv String String
  - | RemEnv String
  - | AddPath [String] [String]
  - | Stdin String
  - | StdinBS ByteString
  - | FileStdin FilePath
  - | Shell
  - | BinaryPipes
  - | Traced String
  - | Timeout Double
  - | WithStdout Bool
  - | WithStderr Bool
  - | EchoStdout Bool
  - | EchoStderr Bool
  - | FileStdout FilePath
  - | FileStderr FilePath
  - | AutoDeps
  - | UserCommand String
  - | FSAOptions String
  - | CloseFileHandles
  - | NoProcessGroup
  - | InheritStdin
- addPath :: MonadIO m => [String] -> [String] -> m CmdOption
- addEnv :: MonadIO m => [(String, String)] -> m CmdOption
- parallel :: [Action a] -> Action [a]
- forP :: [a] -> (a -> Action b) -> Action [b]
- par :: Action a -> Action b -> Action (a, b)
- copyFile' :: Partial => FilePath -> FilePath -> Action ()
- copyFileChanged :: Partial => FilePath -> FilePath -> Action ()
- readFile' :: Partial => FilePath -> Action String
- readFileLines :: Partial => FilePath -> Action [String]
- writeFile' :: (MonadIO m, Partial) => FilePath -> String -> m ()
- writeFileLines :: (MonadIO m, Partial) => FilePath -> [String] -> m ()
- writeFileChanged :: (MonadIO m, Partial) => FilePath -> String -> m ()
- removeFiles :: FilePath -> [FilePattern] -> IO ()
- removeFilesAfter :: FilePath -> [FilePattern] -> Action ()
- withTempFile :: (FilePath -> Action a) -> Action a
- withTempDir :: (FilePath -> Action a) -> Action a
- withTempFileWithin :: FilePath -> (FilePath -> Action a) -> Action a
- withTempDirWithin :: FilePath -> (FilePath -> Action a) -> Action a
- need :: Partial => [FilePath] -> Action ()
- want :: Partial => [FilePath] -> Rules ()
- (%>) :: Located => FilePattern -> (FilePath -> Action ()) -> Rules ()
- (|%>) :: Located => [FilePattern] -> (FilePath -> Action ()) -> Rules ()
- (?>) :: Located => (FilePath -> Bool) -> (FilePath -> Action ()) -> Rules ()
- phony :: Located => String -> Action () -> Rules ()
- (~>) :: Located => String -> Action () -> Rules ()
- phonys :: Located => (String -> Maybe (Action ())) -> Rules ()
- (&%>) :: Located => [FilePattern] -> ([FilePath] -> Action ()) -> Rules ()
- (&?>) :: Located => (FilePath -> Maybe [FilePath]) -> ([FilePath] -> Action ()) -> Rules ()
- orderOnly :: [FilePath] -> Action ()
- orderOnlyAction :: Action a -> Action a
- type FilePattern = String
- (?==) :: FilePattern -> FilePath -> Bool
- (<//>) :: FilePattern -> FilePattern -> FilePattern
- filePattern :: FilePattern -> FilePath -> Maybe [String]
- needed :: Partial => [FilePath] -> Action ()
- trackRead :: [FilePath] -> Action ()
- trackWrite :: [FilePath] -> Action ()
- trackAllow :: [FilePattern] -> Action ()
- doesFileExist :: FilePath -> Action Bool
- doesDirectoryExist :: FilePath -> Action Bool
- getDirectoryContents :: FilePath -> Action [FilePath]
- getDirectoryFiles :: FilePath -> [FilePattern] -> Action [FilePath]
- getDirectoryDirs :: FilePath -> Action [FilePath]
- getDirectoryFilesIO :: FilePath -> [FilePattern] -> IO [FilePath]
- getEnv :: String -> Action (Maybe String)
- getEnvWithDefault :: String -> String -> Action String
- getEnvError :: Partial => String -> Action String
- type ShakeValue a = (Show a, Typeable a, Eq a, Hashable a, Binary a, NFData a)
- type family RuleResult key
- addOracle :: (RuleResult q ~ a, ShakeValue q, ShakeValue a, Partial) => (q -> Action a) -> Rules (q -> Action a)
- addOracleCache :: (RuleResult q ~ a, ShakeValue q, ShakeValue a, Partial) => (q -> Action a) -> Rules (q -> Action a)
- addOracleHash :: (RuleResult q ~ a, ShakeValue q, ShakeValue a, Partial) => (q -> Action a) -> Rules (q -> Action a)
- askOracle :: (RuleResult q ~ a, ShakeValue q, ShakeValue a) => q -> Action a
- askOracles :: (RuleResult q ~ a, ShakeValue q, ShakeValue a) => [q] -> Action [a]
- alwaysRerun :: Action ()
- data Resource
- newResource :: String -> Int -> Rules Resource
- newResourceIO :: String -> Int -> IO Resource
- withResource :: Resource -> Int -> Action a -> Action a
- withResources :: [(Resource, Int)] -> Action a -> Action a
- newThrottle :: String -> Int -> Double -> Rules Resource
- newThrottleIO :: String -> Int -> Double -> IO Resource
- unsafeExtraThread :: Action a -> Action a
- newCache :: (Eq k, Hashable k) => (k -> Action v) -> Rules (k -> Action v)
- newCacheIO :: (Eq k, Hashable k) => (k -> Action v) -> IO (k -> Action v)
- historyDisable :: Action ()
- produces :: [FilePath] -> Action ()
- needHasChanged :: Partial => [FilePath] -> Action [FilePath]
- resultHasChanged :: FilePath -> Action Bool
- batch :: Int -> ((a -> Action ()) -> Rules ()) -> (a -> Action b) -> ([b] -> Action ()) -> Rules ()
- reschedule :: Double -> Action ()
- askOracleWith :: (RuleResult q ~ a, ShakeValue q, ShakeValue a) => q -> a -> Action a
- deprioritize :: Double -> Action ()
- pattern Quiet :: Verbosity
- pattern Normal :: Verbosity
- pattern Loud :: Verbosity
- pattern Chatty :: Verbosity
- putLoud :: String -> Action ()
- putNormal :: String -> Action ()
- putQuiet :: String -> Action ()

# Writing a build system

When writing a Shake build system, start by defining what you `want`, then write rules with `%>` to produce the results. Before calling `cmd` you should ensure that any files the command requires are demanded with calls to `need`. We offer the following advice to Shake users:

- If `ghc --make` or `cabal` is capable of building your project, use that instead. Custom build systems are necessary for many complex projects, but many projects are not complex.
- The `shakeArgs` function automatically handles command line arguments. To define non-file targets use `phony`.
- Put all result files in a distinguished directory, for example `_make`. You can implement a `clean` command by removing that directory, using ``removeFilesAfter` "_make" ["//*"]`.
- To obtain parallel builds set `shakeThreads` to a number greater than 1.
- Lots of compilers produce `.o` files. To avoid overlapping rules, use `.c.o` for C compilers, `.hs.o` for Haskell compilers etc.
- Do not be afraid to mix Shake rules, system commands and other Haskell libraries -- use each for what it does best.
- The more accurate the dependencies are, the better. Use additional rules like `doesFileExist` and `getDirectoryFiles` to track information other than just the contents of files. For information in the environment that you suspect will change regularly (perhaps `ghc` version number), either write the information to a file with `alwaysRerun` and `writeFileChanged`, or use `addOracle`.

# GHC build flags

For large build systems the choice of GHC flags can have a significant impact. We recommend:

    ghc --make MyBuildSystem -threaded -rtsopts "-with-rtsopts=-I0 -qg"

- `-rtsopts`: Allow the setting of further GHC options at runtime.
- `-I0`: Disable idle garbage collection, to avoid frequent unnecessary garbage collection, see a full explanation.
- You may add `-threaded`, and pass the options `-qg` to `-with-rtsopts` to disable parallel garbage collection. Parallel garbage collection in Shake programs typically goes slower than sequential garbage collection, while occupying many cores that could be used for running system commands.

# Other Shake modules

The main Shake module is this one, Development.Shake, which should be sufficient for most people writing build systems using Shake. However, Shake provides some additional modules,

- Development.Shake.Classes provides convenience exports of the classes Shake relies on, in particular `Binary`, `Hashable` and `NFData`. Useful for deriving these types using `GeneralizedNewtypeDeriving` without adding dependencies on the associated packages.
- Development.Shake.Command provides the command line wrappers. These are reexported by Development.Shake, but if you want to reuse just the command-line running functionality in a non-Shake program you can import just that.
- Development.Shake.Config provides a way to write configuration files that are tracked. The configuration files are in the Ninja format. Useful for users of bigger systems who want to track the build rules not in Haskell.
- Development.Shake.Database provides lower level primitives to drive Shake, particularly useful if you want to run multiple Shake runs in a row without reloading from the database.
- Development.Shake.FilePath is an extension of System.FilePath with a few additional methods and safer extension manipulation code.
- Development.Shake.Forward is an alternative take on build systems, where you write the rules as a script where steps are skipped, rather than as a set of dependencies. Only really works if you use `fsatrace`.
- Development.Shake.Rule provides tools for writing your own types of Shake rules. Useful if you need something new, like a rule that queries a database or similar.
- Development.Shake.Util has general utilities that are useful for build systems, e.g. reading `Makefile` syntax and alternative forms of argument parsing.

# Core

shake :: ShakeOptions -> Rules () -> IO () #

Main entry point for running Shake build systems. For an example see the top of the module Development.Shake. Use `ShakeOptions` to specify how the system runs, and `Rules` to specify what to build. The function will throw an exception if the build fails.

To use command line flags to modify `ShakeOptions` see `shakeArgs`.

shakeOptions :: ShakeOptions #

The default set of `ShakeOptions`.

data Rules a #

Define a set of rules. Rules can be created with calls to functions such as `%>` or `action`. Rules are combined with either the `Monoid` instance, or (more commonly) the `Monad` instance and `do` notation. To define your own custom types of rule, see Development.Shake.Rule.

#### Instances

Instances details

MonadIO Rules # |
Instance details Defined in Development.Shake.Internal.Core.Rules Methods liftIO :: IO a -> Rules a #
Applicative Rules # |
Instance details Defined in Development.Shake.Internal.Core.Rules Methods pure :: a -> Rules a # (<*>) :: Rules (a -> b) -> Rules a -> Rules b # liftA2 :: (a -> b -> c) -> Rules a -> Rules b -> Rules c # (*>) :: Rules a -> Rules b -> Rules b # (<*) :: Rules a -> Rules b -> Rules a #
Functor Rules # |
Instance details Defined in Development.Shake.Internal.Core.Rules Methods fmap :: (a -> b) -> Rules a -> Rules b # (<$) :: a -> Rules b -> Rules a #
Monad Rules # |
Instance details Defined in Development.Shake.Internal.Core.Rules Methods (>>=) :: Rules a -> (a -> Rules b) -> Rules b # (>>) :: Rules a -> Rules b -> Rules b # return :: a -> Rules a #
MonadFail Rules # |
Instance details Defined in Development.Shake.Internal.Core.Rules Methods fail :: String -> Rules a #
MonadFix Rules # |
Instance details Defined in Development.Shake.Internal.Core.Rules Methods mfix :: (a -> Rules a) -> Rules a #
(Semigroup a, Monoid a) => Monoid (Rules a) # |
Instance details Defined in Development.Shake.Internal.Core.Rules Methods mempty :: Rules a # mappend :: Rules a -> Rules a -> Rules a # mconcat :: [Rules a] -> Rules a #
Semigroup a => Semigroup (Rules a) # |
Instance details Defined in Development.Shake.Internal.Core.Rules Methods (<>) :: Rules a -> Rules a -> Rules a # sconcat :: NonEmpty (Rules a) -> Rules a # stimes :: Integral b => b -> Rules a -> Rules a #

action :: Partial => Action a -> Rules () #

Run an action, usually used for specifying top-level requirements.

    main = shake shakeOptions $ do
       action $ do
           b <- doesFileExist "file.src"
           when b $ need ["file.out"]

This `action` builds `file.out`, but only if `file.src` exists. The `action` will be run in every build execution (unless `withoutActions` is used), so only cheap operations should be performed. On the flip side, consulting system information (e.g. environment variables) can be done directly as the information will not be cached. All calls to `action` may be run in parallel, in any order.

For the standard requirement of only `need`ing a fixed list of files in the `action`, see `want`.

withoutActions :: Rules a -> Rules a #

Remove all actions specified in a set of rules, usually used for implementing command line specification of what to build.

alternatives :: Rules a -> Rules a #

Change the matching behaviour of rules so rules do not have to be disjoint, but are instead matched in order. Only recommended for small blocks containing a handful of rules.

    alternatives $ do
        "hello.*" %> \out -> writeFile' out "hello.*"
        "*.txt" %> \out -> writeFile' out "*.txt"

In this example `hello.txt` will match the first rule, instead of raising an error about ambiguity. Inside `alternatives` the `priority` of each rule is not used to determine which rule matches, but the resulting match uses that priority compared to the rules outside the `alternatives` block.

priority :: Double -> Rules a -> Rules a #

Change the priority of a given set of rules, where higher values take precedence. All matching rules at a given priority must be disjoint, or an error is raised. All builtin Shake rules have priority between 0 and 1. Excessive use of `priority` is discouraged. As an example:

    priority 4 $ "hello.*" %> \out -> writeFile' out "hello.*"
    priority 8 $ "*.txt" %> \out -> writeFile' out "*.txt"

In this example `hello.txt` will match the second rule, instead of raising an error about ambiguity.

The `priority` function obeys the invariants:

    priority p1 (priority p2 r1) === priority p1 r1
    priority p1 (r1 >> r2) === priority p1 r1 >> priority p1 r2

versioned :: Int -> Rules a -> Rules a #

Indicate that the nested rules have a given version. If you change the semantics of the rule then updating (or adding) a version will cause the rule to rebuild in some circumstances.

    versioned 1 $ "hello.*" %> \out ->
        writeFile' out "Writes v1 now" -- previously wrote out v0

You should only use `versioned` to track changes in the build source, for standard runtime dependencies you should use other mechanisms, e.g. `addOracle`.

data Action a #

The `Action` monad, use `liftIO` to raise `IO` actions into it, and `need` to execute files. Action values are used by `addUserRule` and `action`. The `Action` monad tracks the dependencies of a rule. To raise an exception call `error`, `fail` or ``liftIO` . `throwIO``.

The `Action` type is both a `Monad` and `Applicative`. Anything that is depended upon applicatively will have its dependencies run in parallel. For example ``need` ["a"] *> 'need ["b"]` is equivalent to ``need` ["a", "b"]`.

#### Instances

Instances details

MonadIO Action # |
Instance details Defined in Development.Shake.Internal.Core.Types Methods liftIO :: IO a -> Action a #
Applicative Action # |
Instance details Defined in Development.Shake.Internal.Core.Types Methods pure :: a -> Action a # (<*>) :: Action (a -> b) -> Action a -> Action b # liftA2 :: (a -> b -> c) -> Action a -> Action b -> Action c # (*>) :: Action a -> Action b -> Action b # (<*) :: Action a -> Action b -> Action a #
Functor Action # |
Instance details Defined in Development.Shake.Internal.Core.Types Methods fmap :: (a -> b) -> Action a -> Action b # (<$) :: a -> Action b -> Action a #
Monad Action # |
Instance details Defined in Development.Shake.Internal.Core.Types Methods (>>=) :: Action a -> (a -> Action b) -> Action b # (>>) :: Action a -> Action b -> Action b # return :: a -> Action a #
MonadFail Action # |
Instance details Defined in Development.Shake.Internal.Core.Types Methods fail :: String -> Action a #
Monoid a => Monoid (Action a) # |
Instance details Defined in Development.Shake.Internal.Core.Types Methods mempty :: Action a # mappend :: Action a -> Action a -> Action a # mconcat :: [Action a] -> Action a #
Semigroup a => Semigroup (Action a) # |
Instance details Defined in Development.Shake.Internal.Core.Types Methods (<>) :: Action a -> Action a -> Action a # sconcat :: NonEmpty (Action a) -> Action a # stimes :: Integral b => b -> Action a -> Action a #
CmdResult r => CmdArguments (Action r) # |
Instance details Defined in Development.Shake.Command Methods cmdArguments :: CmdArgument -> Action r #

traced :: String -> IO a -> Action a #

Write an action to the trace list, along with the start/end time of running the IO action. The `cmd` and `command` functions automatically call `traced` with the name of the executable. The trace list is used for profile reports (see `shakeReport`).

By default `traced` prints some useful extra context about what Shake is building, e.g.:

    # traced message (for myobject.o)

To suppress the output of `traced` (for example you want more control over the message using `putInfo`), use the `quietly` combinator.

It is recommended that the string passed to `traced` is short and that only a small number of unique strings are used (makes profiling work better). The string does not need to make sense on its own, only in conjunction with the target it is building.

liftIO :: MonadIO m => IO a -> m a #

Lift a computation from the `IO` monad. This allows us to run IO computations in any monadic stack, so long as it supports these kinds of operations (i.e. `IO` is the base monad for the stack).

### Example

Expand

    import Control.Monad.Trans.State -- from the "transformers" library

    printState :: Show s => StateT s IO ()
    printState = do
      state <- get
      liftIO $ print state

Had we omitted ``liftIO``, we would have ended up with this error:

    • Couldn't match type ‘IO’ with ‘StateT s IO’
     Expected type: StateT s IO ()
       Actual type: IO ()

The important part here is the mismatch between `StateT s IO ()` and ``IO` ()`.

Luckily, we know of a function that takes an ``IO` a` and returns an `(m a)`: ``liftIO``, enabling us to run the program and see the expected results:

    > evalStateT printState "hello"
    "hello"

    > evalStateT printState 3
    3

actionOnException :: Action a -> IO b -> Action a #

If an exception is raised by the `Action`, perform some `IO` then reraise the exception. This function is implemented using `actionBracket`.

actionFinally :: Action a -> IO b -> Action a #

After an `Action`, perform some `IO`, even if there is an exception. This function is implemented using `actionBracket`.

actionBracket :: IO a -> (a -> IO b) -> (a -> Action c) -> Action c #

Like `bracket`, but where the inner operation is of type `Action`. Usually used as ``actionBracket` alloc free use`.

The `free` action will be run masked. The cost of `actionBracket` is _O(n log n)_ in the number of simultaneous `actionBracket` calls active in the program.

actionCatch :: Exception e => Action a -> (e -> Action a) -> Action a #

If a syncronous exception is raised by the `Action`, perform some handler. Note that there is no guarantee that the handler will run on shutdown (use `actionFinally` for that), and that `actionCatch` cannot catch exceptions thrown by dependencies, e.g. raised by `need` (to do so would allow untracked dependencies on failure conditions).

actionRetry :: Int -> Action a -> Action a #

Retry an `Action` if it throws an exception, at most n times (where n must be positive). If you need to call this function, you should probably try and fix the underlying cause (but you also probably know that).

runAfter :: IO () -> Action () #

Specify an action to be run after the database has been closed, if building completes successfully.

data ShakeException #

Error representing all expected exceptions thrown by Shake. Problems when executing rules will be raising using this exception type.

Constructors

ShakeException |
Fields shakeExceptionTarget :: String The target that was being built when the exception occurred. shakeExceptionStack :: [String] A description of the call stack, one entry per line. shakeExceptionInner :: SomeException The underlying exception that was raised.

#### Instances

Instances details

Exception ShakeException # |
Instance details Defined in Development.Shake.Internal.Errors Methods toException :: ShakeException -> SomeException # fromException :: SomeException -> Maybe ShakeException # displayException :: ShakeException -> String # backtraceDesired :: ShakeException -> Bool #
Show ShakeException # |
Instance details Defined in Development.Shake.Internal.Errors Methods showsPrec :: Int -> ShakeException -> ShowS # show :: ShakeException -> String # showList :: [ShakeException] -> ShowS #

# Configuration

data ShakeOptions #

Options to control the execution of Shake, usually specified by overriding fields in `shakeOptions`:

     shakeOptions{shakeThreads=4, shakeReport=["report.html"]}

The `Data` instance for this type reports the `shakeProgress` and `shakeOutput` fields as having the abstract type `Hidden`, because `Data` cannot be defined for functions or `TypeRep`s.

Constructors

ShakeOptions |
Fields shakeFiles :: FilePath Defaults to `.shake`. The directory used for storing Shake metadata files. All metadata files will be named ``shakeFiles`/.shake.file-name`, for some `file-name`. If the `shakeFiles` directory does not exist it will be created. If set to `"/dev/null"` then no shakeFiles are read or written (even on Windows). shakeThreads :: Int Defaults to `1`. Maximum number of rules to run in parallel, similar to `make --jobs=N`. For many build systems, a number equal to or slightly less than the number of physical processors works well. Use `0` to match the detected number of processors (when `0`, `getShakeOptions` will return the number of threads used). shakeVersion :: String Defaults to `"1"`. The version number of your build rules. Change 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. shakeVerbosity :: Verbosity Defaults to `Info`. What level of messages should be printed out. shakeStaunch :: Bool Defaults to `False`. Operate in staunch mode, where building continues even after errors, similar to `make --keep-going`. shakeReport :: [FilePath] Defaults to `[]`. Write a 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. If the file extension is `.json` it will write JSON data; if `.js` it will write Javascript; if `.trace` it will write trace events (load into `about://tracing` in Chrome); otherwise it will write HTML. shakeLint :: Maybe Lint Defaults to `Nothing`. Perform sanity checks during building, see `Lint` for details. shakeLintInside :: [FilePath] Directories in which the files will be tracked by the linter. shakeLintIgnore :: [FilePattern] File patterns which are ignored from linter tracking, a bit like calling `trackAllow` in every rule. shakeLintWatch :: [FilePattern] File patterns whose modification causes an error. Raises an error even if `shakeLint` is `Nothing`. shakeCommandOptions :: [CmdOption] Defaults to `[]`. Additional options to be passed to all command invocations. shakeFlush :: Maybe Seconds 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. shakeRebuild :: [(Rebuild, FilePattern)] What to rebuild shakeAbbreviations :: [(String, String)] Defaults to `[]`. A list of substrings that should be abbreviated in status messages, and their corresponding abbreviation. Commonly used to replace the long paths (e.g. `.make/i586-linux-gcc/output`) with an abbreviation (e.g. `$OUT`). shakeStorageLog :: Bool Defaults to `False`. Write a message to ``shakeFiles`/.shake.storage.log` whenever a storage event happens which may impact on the current stored progress. Examples include database version number changes, database compaction or corrupt files. shakeLineBuffering :: Bool Defaults to `True`. Change `stdout` and `stderr` to line buffering while running Shake. shakeTimings :: Bool Defaults to `False`. Print timing information for each stage at the end. shakeRunCommands :: Bool Default to `True`. Should you run command line actions, set to `False` to skip actions whose output streams and exit code are not used. Useful for profiling the non-command portion of the build system. shakeChange :: Change Default to `ChangeModtime`. How to check if a file has changed, see `Change` for details. shakeCreationCheck :: Bool Default to `True`. After running a rule to create a file, is it an error if the file does not exist. Provided for compatibility with `make` and `ninja` (which have ugly file creation semantics). shakeLiveFiles :: [FilePath] Default to `[]`. After the build system completes, write a list of all files which were live in that run, i.e. those which Shake checked were valid or rebuilt. Produces best answers if nothing rebuilds. shakeVersionIgnore :: Bool Defaults to `False`. Ignore any differences in `shakeVersion`. shakeColor :: Bool Defaults to `False`. Whether to colorize the output. shakeShare :: Maybe FilePath Defaults to `Nothing`. Whether to use and store outputs in a shared directory. shakeCloud :: [String] Defaults to `[]`. Cloud servers to talk to forming a shared cache. shakeSymlink :: Bool Defaults to `False`. Use symlinks for `shakeShare` if they are available. If this setting is `True` (even if symlinks are not available) then files will be made read-only to avoid inadvertantly poisoning the shared cache. Note the links are actually hard links, not symlinks. shakeNeedDirectory :: Bool Defaults to `False`. Is depending on a directory an error (default), or it is permitted with undefined results. Provided for compatibility with `ninja`. shakeAllowRedefineRules :: Bool Whether to allow calling addBuiltinRule for the same key more than once shakeProgress :: IO Progress -> IO () Defaults to no action. A function called when the build starts, allowing progress to be reported. The function is called on a separate thread, and that thread is killed when the build completes. For applications that want to display progress messages, `progressSimple` is often sufficient, but more advanced users should look at the `Progress` data type. shakeOutput :: Verbosity -> String -> IO () Defaults to writing using `putStrLn`. A function called to output messages from Shake, along with the `Verbosity` at which that message should be printed. This function will be called atomically from all other `shakeOutput` functions. The `Verbosity` will always be greater than or higher than `shakeVerbosity`. shakeTrace :: String -> String -> Bool -> IO () Defaults to doing nothing. Called for each call of `traced`, with the key, the command and `True` for starting, `False` for stopping. shakeExtra :: HashMap TypeRep Dynamic This a map which can be used to store arbitrary extra information that a user may need when writing rules. The key of each entry must be the `dynTypeRep` of the value. Insert values using `addShakeExtra` and retrieve them using `getShakeExtra`. The correct way to use this field is to define a hidden newtype for the key, so that conflicts cannot occur.

#### Instances

Instances details

Data ShakeOptions # |
Instance details Defined in Development.Shake.Internal.Options Methods gfoldl :: (forall d b. Data d => c (d -> b) -> d -> c b) -> (forall g. g -> c g) -> ShakeOptions -> c ShakeOptions # gunfold :: (forall b r. Data b => c (b -> r) -> c r) -> (forall r. r -> c r) -> Constr -> c ShakeOptions # toConstr :: ShakeOptions -> Constr # dataTypeOf :: ShakeOptions -> DataType # dataCast1 :: Typeable t => (forall d. Data d => c (t d)) -> Maybe (c ShakeOptions) # dataCast2 :: Typeable t => (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c ShakeOptions) # gmapT :: (forall b. Data b => b -> b) -> ShakeOptions -> ShakeOptions # gmapQl :: (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> ShakeOptions -> r # gmapQr :: forall r r'. (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> ShakeOptions -> r # gmapQ :: (forall d. Data d => d -> u) -> ShakeOptions -> [u] # gmapQi :: Int -> (forall d. Data d => d -> u) -> ShakeOptions -> u # gmapM :: Monad m => (forall d. Data d => d -> m d) -> ShakeOptions -> m ShakeOptions # gmapMp :: MonadPlus m => (forall d. Data d => d -> m d) -> ShakeOptions -> m ShakeOptions # gmapMo :: MonadPlus m => (forall d. Data d => d -> m d) -> ShakeOptions -> m ShakeOptions #
Show ShakeOptions # |
Instance details Defined in Development.Shake.Internal.Options Methods showsPrec :: Int -> ShakeOptions -> ShowS # show :: ShakeOptions -> String # showList :: [ShakeOptions] -> ShowS #

data Rebuild #

The current assumptions made by the build system, used by `shakeRebuild`. 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.

Constructors

RebuildNow | Assume these files are dirty and require rebuilding. for benchmarking rebuild speed and for rebuilding if untracked dependencies have changed. This flag is safe, but may cause more rebuilding than necessary.
RebuildNormal | Useful to reset the rebuild status to how it was before, equivalent to passing no `Rebuild` flags.
RebuildLater | This assumption is unsafe, and may lead to incorrect build results in this run. Assume these files are clean in this run, but test them normally in future runs.

#### Instances

Instances details

Data Rebuild # |
Instance details Defined in Development.Shake.Internal.Options Methods gfoldl :: (forall d b. Data d => c (d -> b) -> d -> c b) -> (forall g. g -> c g) -> Rebuild -> c Rebuild # gunfold :: (forall b r. Data b => c (b -> r) -> c r) -> (forall r. r -> c r) -> Constr -> c Rebuild # toConstr :: Rebuild -> Constr # dataTypeOf :: Rebuild -> DataType # dataCast1 :: Typeable t => (forall d. Data d => c (t d)) -> Maybe (c Rebuild) # dataCast2 :: Typeable t => (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c Rebuild) # gmapT :: (forall b. Data b => b -> b) -> Rebuild -> Rebuild # gmapQl :: (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> Rebuild -> r # gmapQr :: forall r r'. (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> Rebuild -> r # gmapQ :: (forall d. Data d => d -> u) -> Rebuild -> [u] # gmapQi :: Int -> (forall d. Data d => d -> u) -> Rebuild -> u # gmapM :: Monad m => (forall d. Data d => d -> m d) -> Rebuild -> m Rebuild # gmapMp :: MonadPlus m => (forall d. Data d => d -> m d) -> Rebuild -> m Rebuild # gmapMo :: MonadPlus m => (forall d. Data d => d -> m d) -> Rebuild -> m Rebuild #
Bounded Rebuild # |
Instance details Defined in Development.Shake.Internal.Options Methods minBound :: Rebuild # maxBound :: Rebuild #
Enum Rebuild # |
Instance details Defined in Development.Shake.Internal.Options Methods succ :: Rebuild -> Rebuild # pred :: Rebuild -> Rebuild # toEnum :: Int -> Rebuild # fromEnum :: Rebuild -> Int # enumFrom :: Rebuild -> [Rebuild] # enumFromThen :: Rebuild -> Rebuild -> [Rebuild] # enumFromTo :: Rebuild -> Rebuild -> [Rebuild] # enumFromThenTo :: Rebuild -> Rebuild -> Rebuild -> [Rebuild] #
Read Rebuild # |
Instance details Defined in Development.Shake.Internal.Options Methods readsPrec :: Int -> ReadS Rebuild # readList :: ReadS [Rebuild] # readPrec :: ReadPrec Rebuild # readListPrec :: ReadPrec [Rebuild] #
Show Rebuild # |
Instance details Defined in Development.Shake.Internal.Options Methods showsPrec :: Int -> Rebuild -> ShowS # show :: Rebuild -> String # showList :: [Rebuild] -> ShowS #
Eq Rebuild # |
Instance details Defined in Development.Shake.Internal.Options Methods (==) :: Rebuild -> Rebuild -> Bool # (/=) :: Rebuild -> Rebuild -> Bool #
Ord Rebuild # |
Instance details Defined in Development.Shake.Internal.Options Methods compare :: Rebuild -> Rebuild -> Ordering # (<) :: Rebuild -> Rebuild -> Bool # (<=) :: Rebuild -> Rebuild -> Bool # (>) :: Rebuild -> Rebuild -> Bool # (>=) :: Rebuild -> Rebuild -> Bool # max :: Rebuild -> Rebuild -> Rebuild # min :: Rebuild -> Rebuild -> Rebuild #

data Lint #

Which lint checks to perform, used by `shakeLint`.

Constructors

LintBasic | The most basic form of linting. Checks that the current directory does not change and that results do not change after they are first written. Any calls to `needed` will assert that they do not cause a rule to be rebuilt.
LintFSATrace | Track which files are accessed by command line programs using fsatrace.

#### Instances

Instances details

Data Lint # |
Instance details Defined in Development.Shake.Internal.Options Methods gfoldl :: (forall d b. Data d => c (d -> b) -> d -> c b) -> (forall g. g -> c g) -> Lint -> c Lint # gunfold :: (forall b r. Data b => c (b -> r) -> c r) -> (forall r. r -> c r) -> Constr -> c Lint # toConstr :: Lint -> Constr # dataTypeOf :: Lint -> DataType # dataCast1 :: Typeable t => (forall d. Data d => c (t d)) -> Maybe (c Lint) # dataCast2 :: Typeable t => (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c Lint) # gmapT :: (forall b. Data b => b -> b) -> Lint -> Lint # gmapQl :: (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> Lint -> r # gmapQr :: forall r r'. (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> Lint -> r # gmapQ :: (forall d. Data d => d -> u) -> Lint -> [u] # gmapQi :: Int -> (forall d. Data d => d -> u) -> Lint -> u # gmapM :: Monad m => (forall d. Data d => d -> m d) -> Lint -> m Lint # gmapMp :: MonadPlus m => (forall d. Data d => d -> m d) -> Lint -> m Lint # gmapMo :: MonadPlus m => (forall d. Data d => d -> m d) -> Lint -> m Lint #
Bounded Lint # |
Instance details Defined in Development.Shake.Internal.Options Methods minBound :: Lint # maxBound :: Lint #
Enum Lint # |
Instance details Defined in Development.Shake.Internal.Options Methods succ :: Lint -> Lint # pred :: Lint -> Lint # toEnum :: Int -> Lint # fromEnum :: Lint -> Int # enumFrom :: Lint -> [Lint] # enumFromThen :: Lint -> Lint -> [Lint] # enumFromTo :: Lint -> Lint -> [Lint] # enumFromThenTo :: Lint -> Lint -> Lint -> [Lint] #
Read Lint # |
Instance details Defined in Development.Shake.Internal.Options Methods readsPrec :: Int -> ReadS Lint # readList :: ReadS [Lint] # readPrec :: ReadPrec Lint # readListPrec :: ReadPrec [Lint] #
Show Lint # |
Instance details Defined in Development.Shake.Internal.Options Methods showsPrec :: Int -> Lint -> ShowS # show :: Lint -> String # showList :: [Lint] -> ShowS #
Eq Lint # |
Instance details Defined in Development.Shake.Internal.Options Methods (==) :: Lint -> Lint -> Bool # (/=) :: Lint -> Lint -> Bool #
Ord Lint # |
Instance details Defined in Development.Shake.Internal.Options Methods compare :: Lint -> Lint -> Ordering # (<) :: Lint -> Lint -> Bool # (<=) :: Lint -> Lint -> Bool # (>) :: Lint -> Lint -> Bool # (>=) :: Lint -> Lint -> Bool # max :: Lint -> Lint -> Lint # min :: Lint -> Lint -> Lint #

data Change #

How should you determine if a file has changed, used by `shakeChange`. The most common values are `ChangeModtime` (the default, very fast, `touch` causes files to rebuild) and `ChangeModtimeAndDigestInput` (slightly slower, `touch` and switching `git` branches does not cause input files to rebuild).

Constructors

ChangeModtime | Compare equality of modification timestamps, a file has changed if its last modified time changes. A `touch` will force a rebuild. This mode is fast and usually sufficiently accurate, so is the default.
ChangeDigest | Compare equality of file contents digests, a file has changed if its digest changes. A `touch` will not force a rebuild. Use this mode if modification times on your file system are unreliable.
ChangeModtimeAndDigest | A file is rebuilt if both its modification time and digest have changed. For efficiency reasons, the modification time is checked first, and if that has changed, the digest is checked.
ChangeModtimeAndDigestInput | Use `ChangeModtimeAndDigest` for input/source files and `ChangeModtime` for output files. An input file is one which is a dependency but is not built by Shake as it has no matching rule and already exists on the file system.
ChangeModtimeOrDigest | A file is rebuilt if either its modification time or its digest has changed. A `touch` will force a rebuild, but even if a files modification time is reset afterwards, changes will also cause a rebuild.

#### Instances

Instances details

Data Change # |
Instance details Defined in Development.Shake.Internal.Options Methods gfoldl :: (forall d b. Data d => c (d -> b) -> d -> c b) -> (forall g. g -> c g) -> Change -> c Change # gunfold :: (forall b r. Data b => c (b -> r) -> c r) -> (forall r. r -> c r) -> Constr -> c Change # toConstr :: Change -> Constr # dataTypeOf :: Change -> DataType # dataCast1 :: Typeable t => (forall d. Data d => c (t d)) -> Maybe (c Change) # dataCast2 :: Typeable t => (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c Change) # gmapT :: (forall b. Data b => b -> b) -> Change -> Change # gmapQl :: (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> Change -> r # gmapQr :: forall r r'. (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> Change -> r # gmapQ :: (forall d. Data d => d -> u) -> Change -> [u] # gmapQi :: Int -> (forall d. Data d => d -> u) -> Change -> u # gmapM :: Monad m => (forall d. Data d => d -> m d) -> Change -> m Change # gmapMp :: MonadPlus m => (forall d. Data d => d -> m d) -> Change -> m Change # gmapMo :: MonadPlus m => (forall d. Data d => d -> m d) -> Change -> m Change #
Bounded Change # |
Instance details Defined in Development.Shake.Internal.Options Methods minBound :: Change # maxBound :: Change #
Enum Change # |
Instance details Defined in Development.Shake.Internal.Options Methods succ :: Change -> Change # pred :: Change -> Change # toEnum :: Int -> Change # fromEnum :: Change -> Int # enumFrom :: Change -> [Change] # enumFromThen :: Change -> Change -> [Change] # enumFromTo :: Change -> Change -> [Change] # enumFromThenTo :: Change -> Change -> Change -> [Change] #
Read Change # |
Instance details Defined in Development.Shake.Internal.Options Methods readsPrec :: Int -> ReadS Change # readList :: ReadS [Change] # readPrec :: ReadPrec Change # readListPrec :: ReadPrec [Change] #
Show Change # |
Instance details Defined in Development.Shake.Internal.Options Methods showsPrec :: Int -> Change -> ShowS # show :: Change -> String # showList :: [Change] -> ShowS #
Eq Change # |
Instance details Defined in Development.Shake.Internal.Options Methods (==) :: Change -> Change -> Bool # (/=) :: Change -> Change -> Bool #
Ord Change # |
Instance details Defined in Development.Shake.Internal.Options Methods compare :: Change -> Change -> Ordering # (<) :: Change -> Change -> Bool # (<=) :: Change -> Change -> Bool # (>) :: Change -> Change -> Bool # (>=) :: Change -> Change -> Bool # max :: Change -> Change -> Change # min :: Change -> Change -> Change #

getShakeOptions :: Action ShakeOptions #

Get the initial `ShakeOptions`, these will not change during the build process.

getShakeOptionsRules :: Rules ShakeOptions #

Get the `ShakeOptions` that were used.

getHashedShakeVersion :: [FilePath] -> IO String #

Get a checksum of a list of files, suitable for using as `shakeVersion`. This will trigger a rebuild when the Shake rules defined in any of the files are changed. For example:

    main = do
        ver <- getHashedShakeVersion ["Shakefile.hs"]
        shakeArgs shakeOptions{shakeVersion = ver} ...

To automatically detect the name of the current file, turn on the `TemplateHaskell` extension and write `$(LitE . StringL . loc_filename <$> location)`.

This feature can be turned off during development by passing the flag `--no-rule-version` or setting `shakeVersionIgnore` to `True`.

getShakeExtra :: Typeable a => Action (Maybe a) #

Get an item from `shakeExtra`, using the requested type as the key. Fails if the value found at this key does not match the requested type.

getShakeExtraRules :: Typeable a => Rules (Maybe a) #

A version of `getShakeExtra` in `Rules`.

addShakeExtra :: Typeable a => a -> HashMap TypeRep Dynamic -> HashMap TypeRep Dynamic #

Add a properly structued value to `shakeExtra` which can be retrieved with `getShakeExtra`.

## Command line

shakeArgs :: ShakeOptions -> Rules () -> IO () #

Run a build system using command line arguments for configuration. The available flags are those from `shakeOptDescrs`, along with a few additional `make` compatible flags that are not represented in `ShakeOptions`, such as `--print-directory`. If there are no file arguments then the `Rules` are used directly, otherwise the file arguments are `want`ed (after calling `withoutActions`). As an example:

    main = shakeArgs shakeOptions{shakeFiles = "_make", shakeProgress = progressSimple} $ do
        phony "clean" $ removeFilesAfter "_make" ["//*"]
        want ["_make/neil.txt","_make/emily.txt"]
        "_make/*.txt" %> \out ->
            ... build action here ...

This build system will default to building `neil.txt` and `emily.txt`, while showing progress messages, and putting the Shake files in locations such as `_make/.database`. Some example command line flags:

- `main --no-progress` will turn off progress messages.
- `main -j6` will build on 6 threads.
- `main --help` will display a list of supported flags.
- `main clean` will not build anything, but will remove the `_make` directory, including the any `shakeFiles`.
- `main _make/henry.txt` will not build `neil.txt` or `emily.txt`, but will instead build `henry.txt`.

shakeArgsWith :: ShakeOptions -> [OptDescr (Either String a)] -> ([a] -> [String] -> IO (Maybe (Rules ()))) -> IO () #

A version of `shakeArgs` with more flexible handling of command line arguments. The caller of `shakeArgsWith` can add additional flags (the second argument) and chose how to convert the flags/arguments into rules (the third argument). Given:

    shakeArgsWith opts flags (\flagValues argValues -> result)

- `opts` is the initial `ShakeOptions` value, which may have some fields overridden by command line flags. This argument is usually `shakeOptions`, perhaps with a few fields overridden.
- `flags` is a list of flag descriptions, which either produce a `String` containing an error message (typically for flags with invalid arguments, .e.g. ``Left` "could not parse as int"`), or a value that is passed as `flagValues`. If you have no custom flags, pass `[]`.
- `flagValues` is a list of custom flags that the user supplied. If `flags == []` then this list will be `[]`.
- `argValues` is a list of non-flag arguments, which are often treated as files and passed to `want`. If arguments are specified then typically the `want` calls from the rules are discarded using `withoutActions`.
- `result` should produce a `Nothing` to indicate that no building needs to take place, or a `Just` providing the rules that should be used.

As an example of a build system that can use either `gcc` or `distcc` for compiling:

    import System.Console.GetOpt

    data Flags = DistCC deriving Eq
    flags = [Option "" ["distcc"] (NoArg $ Right DistCC) "Run distributed."]

    main = shakeArgsWith shakeOptions flags $ \flags targets -> pure $ Just $ do
        let compiler = if DistCC `elem` flags then "distcc" else "gcc"
        let rules = do
            "*.o" %> \out -> do
                need ...
                cmd compiler ...
            want ["target.exe"]
            ...
        if null targets then rules else want targets >> withoutActions rules

Now you can pass `--distcc` to use the `distcc` compiler.

shakeArgsOptionsWith :: ShakeOptions -> [OptDescr (Either String a)] -> (ShakeOptions -> [a] -> [String] -> IO (Maybe (ShakeOptions, Rules ()))) -> IO () #

Like `shakeArgsWith`, but also lets you manipulate the `ShakeOptions`.

shakeOptDescrs :: [OptDescr (Either String (ShakeOptions -> ShakeOptions))] #

A list of command line options that can be used to modify `ShakeOptions`. Each option returns either an error message (invalid argument to the flag) or a function that changes some fields in `ShakeOptions`. The command line flags are `make` compatible where possbile, but additional flags have been added for the extra options Shake supports.

addHelpSuffix :: String -> Rules () #

Adds some extra information at the end of `--help`.

## Targets

getTargets :: ShakeOptions -> Rules () -> IO [(String, Maybe String)] #

Get all targets registered in the given rules. The names in `phony` and `~>` as well as the file patterns in `%>`, `|%>` and `&%>` are registered as targets, plus any explicit calls to `addTarget`. Returns the command, paired with the documentation (if any).

addTarget :: String -> Rules () #

Register a target, as available when passing `--help` or through `getTargets`. Called automatically by rules such as `phony` and `%>` - to avoid that use `withoutTargets`. To add documentation to a target use `withTargetDocs`.

withTargetDocs :: String -> Rules () -> Rules () #

For all `addTarget` targets within the `Rules` provide the specified documentation, if they don't already have documentation.

withoutTargets :: Rules a -> Rules a #

Remove all targets specified in a set of rules, typically because they are internal details. Overrides `addTarget`.

## Progress reporting

data Progress #

Information about the current state of the build, obtained by either passing a callback function to `shakeProgress` (asynchronous output) or `getProgress` (synchronous output). Typically a build system will pass `progressDisplay` to `shakeProgress`, which will poll this value and produce status messages.

Constructors

Progress |
Fields isFailure :: !(Maybe String) Starts out `Nothing`, becomes `Just` a target name if a rule fails. countSkipped :: !Int Number of rules which were required, but were already in a valid state. countBuilt :: !Int Number of rules which were have been built in this run. countUnknown :: !Int Number of rules which have been built previously, but are not yet known to be required. countTodo :: !Int Number of rules which are currently required (ignoring dependencies that do not change), but not built. timeSkipped :: !Double Time spent building `countSkipped` rules in previous runs. timeBuilt :: !Double Time spent building `countBuilt` rules. timeUnknown :: !Double Time spent building `countUnknown` rules in previous runs. timeTodo :: !(Double, Int) Time spent building `countTodo` rules in previous runs, plus the number which have no known time (have never been built before).

#### Instances

Instances details

Monoid Progress # |
Instance details Defined in Development.Shake.Internal.Options Methods mempty :: Progress # mappend :: Progress -> Progress -> Progress # mconcat :: [Progress] -> Progress #
Semigroup Progress # |
Instance details Defined in Development.Shake.Internal.Options Methods (<>) :: Progress -> Progress -> Progress # sconcat :: NonEmpty Progress -> Progress # stimes :: Integral b => b -> Progress -> Progress #
Data Progress # |
Instance details Defined in Development.Shake.Internal.Options Methods gfoldl :: (forall d b. Data d => c (d -> b) -> d -> c b) -> (forall g. g -> c g) -> Progress -> c Progress # gunfold :: (forall b r. Data b => c (b -> r) -> c r) -> (forall r. r -> c r) -> Constr -> c Progress # toConstr :: Progress -> Constr # dataTypeOf :: Progress -> DataType # dataCast1 :: Typeable t => (forall d. Data d => c (t d)) -> Maybe (c Progress) # dataCast2 :: Typeable t => (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c Progress) # gmapT :: (forall b. Data b => b -> b) -> Progress -> Progress # gmapQl :: (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> Progress -> r # gmapQr :: forall r r'. (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> Progress -> r # gmapQ :: (forall d. Data d => d -> u) -> Progress -> [u] # gmapQi :: Int -> (forall d. Data d => d -> u) -> Progress -> u # gmapM :: Monad m => (forall d. Data d => d -> m d) -> Progress -> m Progress # gmapMp :: MonadPlus m => (forall d. Data d => d -> m d) -> Progress -> m Progress # gmapMo :: MonadPlus m => (forall d. Data d => d -> m d) -> Progress -> m Progress #
Read Progress # |
Instance details Defined in Development.Shake.Internal.Options Methods readsPrec :: Int -> ReadS Progress # readList :: ReadS [Progress] # readPrec :: ReadPrec Progress # readListPrec :: ReadPrec [Progress] #
Show Progress # |
Instance details Defined in Development.Shake.Internal.Options Methods showsPrec :: Int -> Progress -> ShowS # show :: Progress -> String # showList :: [Progress] -> ShowS #
Eq Progress # |
Instance details Defined in Development.Shake.Internal.Options Methods (==) :: Progress -> Progress -> Bool # (/=) :: Progress -> Progress -> Bool #
Ord Progress # |
Instance details Defined in Development.Shake.Internal.Options Methods compare :: Progress -> Progress -> Ordering # (<) :: Progress -> Progress -> Bool # (<=) :: Progress -> Progress -> Bool # (>) :: Progress -> Progress -> Bool # (>=) :: Progress -> Progress -> Bool # max :: Progress -> Progress -> Progress # min :: Progress -> Progress -> Progress #

progressSimple :: IO Progress -> IO () #

A simple method for displaying progress messages, suitable for using as `shakeProgress`. This function writes the current progress to the titlebar every five seconds using `progressTitlebar`, and calls any `shake-progress` program on the `$PATH` using `progressProgram`.

progressDisplay :: Double -> (String -> IO ()) -> IO Progress -> IO () #

Given a sampling interval (in seconds) and a way to display the status message, produce a function suitable for using as `shakeProgress`. This function polls the progress information every n seconds, produces a status message and displays it using the display function.

Typical status messages will take the form of `1m25s (15%)`, indicating that the build is predicted to complete in 1 minute 25 seconds (85 seconds total), and 15% of the necessary build time has elapsed. This function uses past observations to predict future behaviour, and as such, is only guessing. The time is likely to go up as well as down, and will be less accurate from a clean build (as the system has fewer past observations).

The current implementation is to predict the time remaining (based on `timeTodo`) and the work already done (`timeBuilt`). The percentage is then calculated as `remaining / (done + remaining)`, while time left is calculated by scaling `remaining` by the observed work rate in this build, roughly `done / time_elapsed`.

progressTitlebar :: String -> IO () #

Set the title of the current console window to the given text. If the environment variable `$TERM` is set to `xterm` this uses xterm escape sequences. On Windows, if not detected as an xterm, this function uses the `SetConsoleTitle` API.

progressProgram :: IO (String -> IO ()) #

Call the program `shake-progress` if it is on the `$PATH`. The program is called with the following arguments:

- `--title=string` - the string passed to `progressProgram`.
- `--state=Normal`, or one of `NoProgress`, `Normal`, or `Error` to indicate what state the progress bar should be in.
- `--value=25` - the percent of the build that has completed, if not in `NoProgress` state.

The program will not be called consecutively with the same `--state` and `--value` options.

Windows 7 or higher users can get taskbar progress notifications by placing the following program in their `$PATH`: https://github.com/ndmitchell/shake/releases.

getProgress :: Action Progress #

Get the current `Progress` structure, as would be returned by `shakeProgress`.

## Verbosity

data Verbosity #

The verbosity data type, used by `shakeVerbosity`.

Constructors

Silent | Don't print any messages.
Error | Only print error messages.
Warn | Print errors and warnings.
Info | Print errors, warnings and `# command-name (for file-name)` when running a `traced` command.
Verbose | Print errors, warnings, full command lines when running a `command` or `cmd` command and status messages when starting a rule.
Diagnostic | Print messages for virtually everything (mostly for debugging).

#### Instances

Instances details

Data Verbosity # |
Instance details Defined in Development.Shake.Internal.Options Methods gfoldl :: (forall d b. Data d => c (d -> b) -> d -> c b) -> (forall g. g -> c g) -> Verbosity -> c Verbosity # gunfold :: (forall b r. Data b => c (b -> r) -> c r) -> (forall r. r -> c r) -> Constr -> c Verbosity # toConstr :: Verbosity -> Constr # dataTypeOf :: Verbosity -> DataType # dataCast1 :: Typeable t => (forall d. Data d => c (t d)) -> Maybe (c Verbosity) # dataCast2 :: Typeable t => (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c Verbosity) # gmapT :: (forall b. Data b => b -> b) -> Verbosity -> Verbosity # gmapQl :: (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> Verbosity -> r # gmapQr :: forall r r'. (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> Verbosity -> r # gmapQ :: (forall d. Data d => d -> u) -> Verbosity -> [u] # gmapQi :: Int -> (forall d. Data d => d -> u) -> Verbosity -> u # gmapM :: Monad m => (forall d. Data d => d -> m d) -> Verbosity -> m Verbosity # gmapMp :: MonadPlus m => (forall d. Data d => d -> m d) -> Verbosity -> m Verbosity # gmapMo :: MonadPlus m => (forall d. Data d => d -> m d) -> Verbosity -> m Verbosity #
Bounded Verbosity # |
Instance details Defined in Development.Shake.Internal.Options Methods minBound :: Verbosity # maxBound :: Verbosity #
Enum Verbosity # |
Instance details Defined in Development.Shake.Internal.Options Methods succ :: Verbosity -> Verbosity # pred :: Verbosity -> Verbosity # toEnum :: Int -> Verbosity # fromEnum :: Verbosity -> Int # enumFrom :: Verbosity -> [Verbosity] # enumFromThen :: Verbosity -> Verbosity -> [Verbosity] # enumFromTo :: Verbosity -> Verbosity -> [Verbosity] # enumFromThenTo :: Verbosity -> Verbosity -> Verbosity -> [Verbosity] #
Read Verbosity # |
Instance details Defined in Development.Shake.Internal.Options Methods readsPrec :: Int -> ReadS Verbosity # readList :: ReadS [Verbosity] # readPrec :: ReadPrec Verbosity # readListPrec :: ReadPrec [Verbosity] #
Show Verbosity # |
Instance details Defined in Development.Shake.Internal.Options Methods showsPrec :: Int -> Verbosity -> ShowS # show :: Verbosity -> String # showList :: [Verbosity] -> ShowS #
Eq Verbosity # |
Instance details Defined in Development.Shake.Internal.Options Methods (==) :: Verbosity -> Verbosity -> Bool # (/=) :: Verbosity -> Verbosity -> Bool #
Ord Verbosity # |
Instance details Defined in Development.Shake.Internal.Options Methods compare :: Verbosity -> Verbosity -> Ordering # (<) :: Verbosity -> Verbosity -> Bool # (<=) :: Verbosity -> Verbosity -> Bool # (>) :: Verbosity -> Verbosity -> Bool # (>=) :: Verbosity -> Verbosity -> Bool # max :: Verbosity -> Verbosity -> Verbosity # min :: Verbosity -> Verbosity -> Verbosity #

getVerbosity :: Action Verbosity #

Get the current verbosity level, originally set by `shakeVerbosity`. If you want to output information to the console, you are recommended to use `putVerbose` / `putInfo` / `putError`, which ensures multiple messages are not interleaved. The verbosity can be modified locally by `withVerbosity`.

putVerbose :: String -> Action () #

Write an unimportant message to the output, only shown when `shakeVerbosity` is higher than normal (`Verbose` or above). The output will not be interleaved with any other Shake messages (other than those generated by system commands).

putInfo :: String -> Action () #

Write a normal priority message to the output, only suppressed when `shakeVerbosity` is `Error`, `Warn` or `Silent`. The output will not be interleaved with any other Shake messages (other than those generated by system commands).

putWarn :: String -> Action () #

Write a semi important message to the output, only suppressed when `shakeVerbosity` is `Error` or `Silent`. The output will not be interleaved with any other Shake messages (other than those generated by system commands).

putError :: String -> Action () #

Write an important message to the output, only suppressed when `shakeVerbosity` is `Silent`. The output will not be interleaved with any other Shake messages (other than those generated by system commands).

withVerbosity :: Verbosity -> Action a -> Action a #

Run an action with a particular verbosity level. Will not update the `shakeVerbosity` returned by `getShakeOptions` and will not have any impact on `Diagnostic` tracing.

quietly :: Action a -> Action a #

Run an action with `Error` verbosity, in particular messages produced by `traced` (including from `cmd` or `command`) will not be printed to the screen. Will not update the `shakeVerbosity` returned by `getShakeOptions` and will not turn off any `Diagnostic` tracing.

# Running commands

command :: (Partial, CmdResult r) => [CmdOption] -> String -> [String] -> Action r #

Execute a system command. Before running `command` make sure you `need` any files that are used by the command.

This function takes a list of options (often just `[]`, see `CmdOption` for the available options), the name of the executable (either a full name, or a program on the `$PATH`) and a list of arguments. The result is often `()`, but can be a tuple containg any of `Stdout`, `Stderr` and `Exit`. Some examples:

    command_ [] "gcc" ["-c","myfile.c"]                          -- compile a file, throwing an exception on failure
    Exit c <- command [] "gcc" ["-c",myfile]                     -- run a command, recording the exit code
    (Exit c, Stderr err) <- command [] "gcc" ["-c","myfile.c"]   -- run a command, recording the exit code and error output
    Stdout out <- command [] "gcc" ["-MM","myfile.c"]            -- run a command, recording the output
    command_ [Cwd "generated"] "gcc" ["-c",myfile]               -- run a command in a directory

Unless you retrieve the `ExitCode` using `Exit`, any `ExitFailure` will throw an error, including the `Stderr` in the exception message. If you capture the `Stdout` or `Stderr`, that stream will not be echoed to the console, unless you use the option `EchoStdout` or `EchoStderr`.

If you use `command` inside a `do` block and do not use the result, you may get a compile-time error about being unable to deduce `CmdResult`. To avoid this error, use `command_`.

By default the `stderr` stream will be captured for use in error messages, and also echoed. To only echo pass ``WithStderr` `False``, which causes no streams to be captured by Shake, and certain programs (e.g. `gcc`) to detect they are running in a terminal.

command_ :: Partial => [CmdOption] -> String -> [String] -> Action () #

A version of `command` where you do not require any results, used to avoid errors about being unable to deduce `CmdResult`.

cmd :: (Partial, CmdArguments args) => args :-> Action r #

Build or execute a system command. Before using `cmd` to run a command, make sure you `need` any files that are used by the command.

- `String` arguments are treated as a list of whitespace separated arguments.
- `[String]` arguments are treated as a list of literal arguments.
- `CmdOption` arguments are used as options.
- `CmdArgument` arguments, which can be built by `cmd` itself, are spliced into the containing command.

Typically only string literals should be passed as `String` arguments. When using variables prefer `[myvar]` so that if `myvar` contains spaces they are properly escaped.

As some examples, here are some calls, and the resulting command string:

    cmd_ "git log --pretty=" "oneline"           -- git log --pretty= oneline
    cmd_ "git log --pretty=" ["oneline"]         -- git log --pretty= oneline
    cmd_ "git log" ("--pretty=" ++ "oneline")    -- git log --pretty=oneline
    cmd_ "git log" ("--pretty=" ++ "one line")   -- git log --pretty=one line
    cmd_ "git log" ["--pretty=" ++ "one line"]   -- git log "--pretty=one line"

More examples, including return values, see this translation of the examples given for the `command` function:

    cmd_ "gcc -c myfile.c"                                       -- compile a file, throwing an exception on failure
    Exit c <- cmd "gcc -c" [myfile]                              -- run a command, recording the exit code
    (Exit c, Stderr err) <- cmd "gcc -c myfile.c"                -- run a command, recording the exit code and error output
    Stdout out <- cmd "gcc -MM myfile.c"                         -- run a command, recording the output
    cmd (Cwd "generated") "gcc -c" [myfile] :: Action ()         -- run a command in a directory

    let gccCommand = cmd "gcc -c" :: CmdArgument                 -- build a sub-command. cmd can return CmdArgument values as well as execute commands
    cmd (Cwd "generated") gccCommand [myfile]                 -- splice that command into a greater command

If you use `cmd` inside a `do` block and do not use the result, you may get a compile-time error about being unable to deduce `CmdResult`. To avoid this error, use `cmd_`. If you enable `OverloadedStrings` or `OverloadedLists` you may have to give type signatures to the arguments, or use the more constrained `command` instead.

The `cmd` function can also be run in the `IO` monad, but then `Traced` is ignored and command lines are not echoed. As an example:

    cmd (Cwd "generated") Shell "gcc -c myfile.c" :: IO ()

cmd_ :: (Partial, CmdArguments args, Unit args) => args :-> Action () #

See `cmd`. Same as `cmd` except with a unit result. `cmd` is to `cmd_` as `command` is to `command_`.

unit :: m () -> m () #

The identity function which requires the inner argument to be `()`. Useful for functions with overloaded return types.

    \(x :: Maybe ()) -> unit x == x

newtype Stdout a #

Collect the `stdout` of the process. If used, the `stdout` will not be echoed to the terminal, unless you include `EchoStdout`. The value type may be either `String`, or either lazy or strict `ByteString`.

Note that most programs end their output with a trailing newline, so calling `ghc --numeric-version` will result in `Stdout` of `"6.8.3\n"`. If you want to automatically trim the resulting string, see `StdoutTrim`.

Constructors

Stdout |
Fields fromStdout :: a

#### Instances

Instances details

CmdString a => CmdResult (Stdout a) # |
Instance details Defined in Development.Shake.Command Methods cmdResult :: ([Result], [Result] -> Stdout a)

newtype StdoutTrim a #

Like `Stdout` but remove all leading and trailing whitespaces.

Constructors

StdoutTrim |
Fields fromStdoutTrim :: a

#### Instances

Instances details

CmdString a => CmdResult (StdoutTrim a) # |
Instance details Defined in Development.Shake.Command Methods cmdResult :: ([Result], [Result] -> StdoutTrim a)

newtype Stderr a #

Collect the `stderr` of the process. If used, the `stderr` will not be echoed to the terminal, unless you include `EchoStderr`. The value type may be either `String`, or either lazy or strict `ByteString`.

Constructors

Stderr |
Fields fromStderr :: a

#### Instances

Instances details

CmdString a => CmdResult (Stderr a) # |
Instance details Defined in Development.Shake.Command Methods cmdResult :: ([Result], [Result] -> Stderr a)

newtype Stdouterr a #

Collect the `stdout` and `stderr` of the process. If used, the `stderr` and `stdout` will not be echoed to the terminal, unless you include `EchoStdout` and `EchoStderr`. The value type may be either `String`, or either lazy or strict `ByteString`.

Constructors

Stdouterr |
Fields fromStdouterr :: a

#### Instances

Instances details

CmdString a => CmdResult (Stdouterr a) # |
Instance details Defined in Development.Shake.Command Methods cmdResult :: ([Result], [Result] -> Stdouterr a)

newtype Exit #

Collect the `ExitCode` of the process. If you do not collect the exit code, any `ExitFailure` will cause an exception.

Constructors

Exit |
Fields fromExit :: ExitCode

#### Instances

Instances details

CmdResult Exit # |
Instance details Defined in Development.Shake.Command Methods cmdResult :: ([Result], [Result] -> Exit)

newtype Process #

Collect the `ProcessHandle` of the process. If you do collect the process handle, the command will run asyncronously and the call to `cmd` / `command` will return as soon as the process is spawned. Any `Stdout` / `Stderr` captures will return empty strings.

Constructors

Process |
Fields fromProcess :: ProcessHandle

#### Instances

Instances details

CmdResult Process # |
Instance details Defined in Development.Shake.Command Methods cmdResult :: ([Result], [Result] -> Process)

newtype CmdTime #

Collect the time taken to execute the process. Can be used in conjunction with `CmdLine` to write helper functions that print out the time of a result.

    timer :: (CmdResult r, MonadIO m) => (forall r . CmdResult r => m r) -> m r
    timer act = do
        (CmdTime t, CmdLine x, r) <- act
        liftIO $ putStrLn $ "Command " ++ x ++ " took " ++ show t ++ " seconds"
        pure r

    run :: IO ()
    run = timer $ cmd "ghc --version"

Constructors

CmdTime |
Fields fromCmdTime :: Double

#### Instances

Instances details

CmdResult CmdTime # |
Instance details Defined in Development.Shake.Command Methods cmdResult :: ([Result], [Result] -> CmdTime)

newtype CmdLine #

Collect the command line used for the process. This command line will be approximate - suitable for user diagnostics, but not for direct execution.

Constructors

CmdLine |
Fields fromCmdLine :: String

#### Instances

Instances details

CmdResult CmdLine # |
Instance details Defined in Development.Shake.Command Methods cmdResult :: ([Result], [Result] -> CmdLine)

data FSATrace a #

The results produced by `fsatrace`. All files will be absolute paths. You can get the results for a `cmd` by requesting a value of type `[`FSATrace`]`.

Constructors

FSAWrite a | Writing to a file
FSARead a | Reading from a file
FSADelete a | Deleting a file
FSAMove a a | Moving, arguments destination, then source
FSAQuery a | Querying/stat on a file
FSATouch a | Touching a file

#### Instances

Instances details

Functor FSATrace # |
Instance details Defined in Development.Shake.Command Methods fmap :: (a -> b) -> FSATrace a -> FSATrace b # (<$) :: a -> FSATrace b -> FSATrace a #
Data a => Data (FSATrace a) # |
Instance details Defined in Development.Shake.Command Methods gfoldl :: (forall d b. Data d => c (d -> b) -> d -> c b) -> (forall g. g -> c g) -> FSATrace a -> c (FSATrace a) # gunfold :: (forall b r. Data b => c (b -> r) -> c r) -> (forall r. r -> c r) -> Constr -> c (FSATrace a) # toConstr :: FSATrace a -> Constr # dataTypeOf :: FSATrace a -> DataType # dataCast1 :: Typeable t => (forall d. Data d => c (t d)) -> Maybe (c (FSATrace a)) # dataCast2 :: Typeable t => (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c (FSATrace a)) # gmapT :: (forall b. Data b => b -> b) -> FSATrace a -> FSATrace a # gmapQl :: (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> FSATrace a -> r # gmapQr :: forall r r'. (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> FSATrace a -> r # gmapQ :: (forall d. Data d => d -> u) -> FSATrace a -> [u] # gmapQi :: Int -> (forall d. Data d => d -> u) -> FSATrace a -> u # gmapM :: Monad m => (forall d. Data d => d -> m d) -> FSATrace a -> m (FSATrace a) # gmapMp :: MonadPlus m => (forall d. Data d => d -> m d) -> FSATrace a -> m (FSATrace a) # gmapMo :: MonadPlus m => (forall d. Data d => d -> m d) -> FSATrace a -> m (FSATrace a) #
Show a => Show (FSATrace a) # |
Instance details Defined in Development.Shake.Command Methods showsPrec :: Int -> FSATrace a -> ShowS # show :: FSATrace a -> String # showList :: [FSATrace a] -> ShowS #
Eq a => Eq (FSATrace a) # |
Instance details Defined in Development.Shake.Command Methods (==) :: FSATrace a -> FSATrace a -> Bool # (/=) :: FSATrace a -> FSATrace a -> Bool #
Ord a => Ord (FSATrace a) # |
Instance details Defined in Development.Shake.Command Methods compare :: FSATrace a -> FSATrace a -> Ordering # (<) :: FSATrace a -> FSATrace a -> Bool # (<=) :: FSATrace a -> FSATrace a -> Bool # (>) :: FSATrace a -> FSATrace a -> Bool # (>=) :: FSATrace a -> FSATrace a -> Bool # max :: FSATrace a -> FSATrace a -> FSATrace a # min :: FSATrace a -> FSATrace a -> FSATrace a #
CmdResult [FSATrace ByteString] # |
Instance details Defined in Development.Shake.Command Methods cmdResult :: ([Result], [Result] -> [FSATrace ByteString])
CmdResult [FSATrace FilePath] # |
Instance details Defined in Development.Shake.Command Methods cmdResult :: ([Result], [Result] -> [FSATrace FilePath])

class CmdResult a #

A class for specifying what results you want to collect from a process. Values are formed of `Stdout`, `Stderr`, `Exit` and tuples of those.

Minimal complete definition

cmdResult

#### Instances

Instances details

CmdResult ExitCode # |
Instance details Defined in Development.Shake.Command Methods cmdResult :: ([Result], [Result] -> ExitCode)
CmdResult ProcessHandle # |
Instance details Defined in Development.Shake.Command Methods cmdResult :: ([Result], [Result] -> ProcessHandle)
CmdResult CmdLine # |
Instance details Defined in Development.Shake.Command Methods cmdResult :: ([Result], [Result] -> CmdLine)
CmdResult CmdTime # |
Instance details Defined in Development.Shake.Command Methods cmdResult :: ([Result], [Result] -> CmdTime)
CmdResult Exit # |
Instance details Defined in Development.Shake.Command Methods cmdResult :: ([Result], [Result] -> Exit)
CmdResult Process # |
Instance details Defined in Development.Shake.Command Methods cmdResult :: ([Result], [Result] -> Process)
CmdResult () # |
Instance details Defined in Development.Shake.Command Methods cmdResult :: ([Result], [Result] -> ())
CmdString a => CmdResult (Stderr a) # |
Instance details Defined in Development.Shake.Command Methods cmdResult :: ([Result], [Result] -> Stderr a)
CmdString a => CmdResult (Stdout a) # |
Instance details Defined in Development.Shake.Command Methods cmdResult :: ([Result], [Result] -> Stdout a)
CmdString a => CmdResult (StdoutTrim a) # |
Instance details Defined in Development.Shake.Command Methods cmdResult :: ([Result], [Result] -> StdoutTrim a)
CmdString a => CmdResult (Stdouterr a) # |
Instance details Defined in Development.Shake.Command Methods cmdResult :: ([Result], [Result] -> Stdouterr a)
CmdResult [FSATrace ByteString] # |
Instance details Defined in Development.Shake.Command Methods cmdResult :: ([Result], [Result] -> [FSATrace ByteString])
CmdResult [FSATrace FilePath] # |
Instance details Defined in Development.Shake.Command Methods cmdResult :: ([Result], [Result] -> [FSATrace FilePath])
(CmdResult x1, CmdResult x2) => CmdResult (x1, x2) # |
Instance details Defined in Development.Shake.Command Methods cmdResult :: ([Result], [Result] -> (x1, x2))
(CmdResult x1, CmdResult x2, CmdResult x3) => CmdResult (x1, x2, x3) # |
Instance details Defined in Development.Shake.Command Methods cmdResult :: ([Result], [Result] -> (x1, x2, x3))
(CmdResult x1, CmdResult x2, CmdResult x3, CmdResult x4) => CmdResult (x1, x2, x3, x4) # |
Instance details Defined in Development.Shake.Command Methods cmdResult :: ([Result], [Result] -> (x1, x2, x3, x4))
(CmdResult x1, CmdResult x2, CmdResult x3, CmdResult x4, CmdResult x5) => CmdResult (x1, x2, x3, x4, x5) # |
Instance details Defined in Development.Shake.Command Methods cmdResult :: ([Result], [Result] -> (x1, x2, x3, x4, x5))

class CmdString a #

The allowable `String`-like values that can be captured.

Minimal complete definition

cmdString

#### Instances

Instances details

CmdString ByteString # |
Instance details Defined in Development.Shake.Command Methods cmdString :: (Str, Str -> ByteString)
CmdString ByteString # |
Instance details Defined in Development.Shake.Command Methods cmdString :: (Str, Str -> ByteString)
CmdString String # |
Instance details Defined in Development.Shake.Command Methods cmdString :: (Str, Str -> String)
CmdString () # |
Instance details Defined in Development.Shake.Command Methods cmdString :: (Str, Str -> ())

data CmdOption #

Options passed to `command` or `cmd` to control how processes are executed.

Constructors

Cwd FilePath | Change the current directory in the spawned process. By default uses this processes current directory. Successive `Cwd` options are joined together, to change into nested directories.
Env [(String, String)] | Change the environment variables in the spawned process. By default uses this processes environment.
AddEnv String String | Add an environment variable in the child process.
RemEnv String | Remove an environment variable from the child process.
AddPath [String] [String] | Add some items to the prefix and suffix of the `$PATH` variable.
Stdin String | Given as the `stdin` of the spawned process.
StdinBS ByteString | Given as the `stdin` of the spawned process.
FileStdin FilePath | Take the `stdin` from a file.
Shell | Pass the command to the shell without escaping - any arguments will be joined with spaces. By default arguments are escaped properly.
BinaryPipes | Treat the `stdin`/`stdout`/`stderr` messages as binary. By default `String` results use text encoding and `ByteString` results use binary encoding.
Traced String | Name to use with `traced`, or `""` for no tracing. By default traces using the name of the executable.
Timeout Double | Abort the computation after N seconds, will raise a failure exit code. Calls `interruptProcessGroupOf` and `terminateProcess`, but may sometimes fail to abort the process and not timeout.
WithStdout Bool | Should I include the `stdout` in the exception if the command fails? Defaults to `False`.
WithStderr Bool | Should I include the `stderr` in the exception if the command fails? Defaults to `True`.
EchoStdout Bool | Should I echo the `stdout`? Defaults to `True` unless a `Stdout` result is required or you use `FileStdout`.
EchoStderr Bool | Should I echo the `stderr`? Defaults to `True` unless a `Stderr` result is required or you use `FileStderr`.
FileStdout FilePath | Should I put the `stdout` to a file.
FileStderr FilePath | Should I put the `stderr` to a file.
AutoDeps | Compute dependencies automatically. Only works if `shakeLintInside` has been set to the files where autodeps might live.
UserCommand String | The command the user thinks about, before any munging. Defaults to the actual command.
FSAOptions String | Options to `fsatrace`, a list of strings with characters such as `"r"` (reads) `"w"` (writes). Defaults to `"rwmdqt"` if the output of `fsatrace` is required.
CloseFileHandles | Before starting the command in the child process, close all file handles except stdin, stdout, stderr in the child process. Uses `close_fds` from package process and comes with the same caveats, i.e. runtime is linear with the maximum number of open file handles (`RLIMIT_NOFILE`, see `man 2 getrlimit` on Linux).
NoProcessGroup | Don't run the process in its own group. Required when running `docker`. Will mean that process timeouts and asyncronous exceptions may not properly clean up child processes.
InheritStdin | Cause the stdin from the parent to be inherited. Might also require NoProcessGroup on Linux. Ignored if you explicitly pass a stdin.

#### Instances

Instances details

Data CmdOption # |
Instance details Defined in Development.Shake.Internal.CmdOption Methods gfoldl :: (forall d b. Data d => c (d -> b) -> d -> c b) -> (forall g. g -> c g) -> CmdOption -> c CmdOption # gunfold :: (forall b r. Data b => c (b -> r) -> c r) -> (forall r. r -> c r) -> Constr -> c CmdOption # toConstr :: CmdOption -> Constr # dataTypeOf :: CmdOption -> DataType # dataCast1 :: Typeable t => (forall d. Data d => c (t d)) -> Maybe (c CmdOption) # dataCast2 :: Typeable t => (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c CmdOption) # gmapT :: (forall b. Data b => b -> b) -> CmdOption -> CmdOption # gmapQl :: (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> CmdOption -> r # gmapQr :: forall r r'. (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> CmdOption -> r # gmapQ :: (forall d. Data d => d -> u) -> CmdOption -> [u] # gmapQi :: Int -> (forall d. Data d => d -> u) -> CmdOption -> u # gmapM :: Monad m => (forall d. Data d => d -> m d) -> CmdOption -> m CmdOption # gmapMp :: MonadPlus m => (forall d. Data d => d -> m d) -> CmdOption -> m CmdOption # gmapMo :: MonadPlus m => (forall d. Data d => d -> m d) -> CmdOption -> m CmdOption #
Show CmdOption # |
Instance details Defined in Development.Shake.Internal.CmdOption Methods showsPrec :: Int -> CmdOption -> ShowS # show :: CmdOption -> String # showList :: [CmdOption] -> ShowS #
Eq CmdOption # |
Instance details Defined in Development.Shake.Internal.CmdOption Methods (==) :: CmdOption -> CmdOption -> Bool # (/=) :: CmdOption -> CmdOption -> Bool #
Ord CmdOption # |
Instance details Defined in Development.Shake.Internal.CmdOption Methods compare :: CmdOption -> CmdOption -> Ordering # (<) :: CmdOption -> CmdOption -> Bool # (<=) :: CmdOption -> CmdOption -> Bool # (>) :: CmdOption -> CmdOption -> Bool # (>=) :: CmdOption -> CmdOption -> Bool # max :: CmdOption -> CmdOption -> CmdOption # min :: CmdOption -> CmdOption -> CmdOption #
IsCmdArgument CmdOption # |
Instance details Defined in Development.Shake.Command Methods toCmdArgument :: CmdOption -> CmdArgument #
IsCmdArgument [CmdOption] # |
Instance details Defined in Development.Shake.Command Methods toCmdArgument :: [CmdOption] -> CmdArgument #

addPath :: MonadIO m => [String] -> [String] -> m CmdOption #

Deprecated: Use `AddPath`. This function will be removed in a future version.

Add a prefix and suffix to the `$PATH` environment variable. For example:

    opt <- addPath ["/usr/special"] []
    cmd opt "userbinary --version"

Would prepend `/usr/special` to the current `$PATH`, and the command would pick `/usr/special/userbinary`, if it exists. To add other variables see `addEnv`.

addEnv :: MonadIO m => [(String, String)] -> m CmdOption #

Deprecated: Use `AddEnv`. This function will be removed in a future version.

Add a single variable to the environment. For example:

    opt <- addEnv [("CFLAGS","-O2")]
    cmd opt "gcc -c main.c"

Would add the environment variable `$CFLAGS` with value `-O2`. If the variable `$CFLAGS` was already defined it would be overwritten. If you wish to modify `$PATH` see `addPath`.

# Explicit parallelism

parallel :: [Action a] -> Action [a] #

Execute a list of actions in parallel. In most cases `need` will be more appropriate to benefit from parallelism. If the two types of `Action` are different dependencies which ultimately boil down to `apply`, using `Applicative` operations will still ensure the dependencies occur in parallel. The main use of this function is to run work that happens in an `Action` in parallel.

forP :: [a] -> (a -> Action b) -> Action [b] #

A `parallel` version of `forM`.

par :: Action a -> Action b -> Action (a, b) #

Execute two operations in parallel, based on `parallel`.

# Utility functions

copyFile' :: Partial => FilePath -> FilePath -> Action () #

`copyFile' old new` copies the existing file from `old` to `new`. The `old` file will be tracked as a dependency. Also creates the new directory if necessary.

copyFileChanged :: Partial => FilePath -> FilePath -> Action () #

`copyFileChanged old new` copies the existing file from `old` to `new`, if the contents have changed. The `old` file will be tracked as a dependency. Also creates the new directory if necessary.

readFile' :: Partial => FilePath -> Action String #

Read a file, after calling `need`. The argument file will be tracked as a dependency.

readFileLines :: Partial => FilePath -> Action [String] #

A version of `readFile'` which also splits the result into lines. The argument file will be tracked as a dependency.

writeFile' :: (MonadIO m, Partial) => FilePath -> String -> m () #

Write a file, lifted to the `Action` monad.

writeFileLines :: (MonadIO m, Partial) => FilePath -> [String] -> m () #

A version of `writeFile'` which writes out a list of lines.

writeFileChanged :: (MonadIO m, Partial) => FilePath -> String -> m () #

Write a file, but only if the contents would change.

removeFiles :: FilePath -> [FilePattern] -> IO () #

Remove all files and directories that match any of the patterns within a directory. Some examples:

    removeFiles "output" ["//*"]        -- delete everything inside 'output'
    removeFiles "output" ["//"]         -- delete 'output' itself
    removeFiles "." ["//*.hi","//*.o"] -- delete all '.hi' and '.o' files

If the argument directory is missing no error is raised. This function will follow symlinks, so should be used with care.

This function is often useful when writing a `clean` action for your build system, often as a `phony` rule.

removeFilesAfter :: FilePath -> [FilePattern] -> Action () #

Remove files, like `removeFiles`, but executed after the build completes successfully using `runAfter`. Useful for implementing `clean` actions that delete files Shake may have open for building, e.g. `shakeFiles`. Where possible, delete the files as a normal part of the build, e.g. using ``liftIO` $ `removeFiles` dir pats`.

withTempFile :: (FilePath -> Action a) -> Action a #

Create a temporary file in the temporary directory. The file will be deleted after the action completes (provided the file is not still open). The `FilePath` will not have any file extension, will exist, and will be zero bytes long. If you require a file with a specific name, use `withTempDir`.

withTempDir :: (FilePath -> Action a) -> Action a #

Create a temporary directory inside the system temporary directory. The directory will be deleted after the action completes. As an example:

    withTempDir $ \mydir -> do
       putInfo $ "Temp directory is " ++ mydir
       writeFile' (mydir </> "test.txt") "writing out a temp file"

withTempFileWithin :: FilePath -> (FilePath -> Action a) -> Action a #

Like `withTempFile` but using a custom temporary directory.

withTempDirWithin :: FilePath -> (FilePath -> Action a) -> Action a #

Like `withTempDir` but using a custom temporary directory.

# File rules

need :: Partial => [FilePath] -> Action () #

Add a dependency on the file arguments, ensuring they are built before continuing. The file arguments may be built in parallel, in any order. This function is particularly necessary when calling `cmd` or `command`. As an example:

    "//*.rot13" %> \out -> do
        let src = dropExtension out
        need [src]
        cmd "rot13" [src] "-o" [out]

Usually `need [foo,bar]` is preferable to `need [foo] >> need [bar]` as the former allows greater parallelism, while the latter requires `foo` to finish building before starting to build `bar`.

This function should not be called with wildcards (e.g. `*.txt` - use `getDirectoryFiles` to expand them), environment variables (e.g. `$HOME` - use `getEnv` to expand them) or directories (directories cannot be tracked directly - track files within the directory instead).

want :: Partial => [FilePath] -> Rules () #

Require that the argument files 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. All arguments to all `want` calls may be built in parallel, in any order.

This function is defined in terms of `action` and `need`, use `action` if you need more complex targets than `want` allows.

(%>) :: Located => FilePattern -> (FilePath -> Action ()) -> Rules () infix 1 #

Define a rule that matches a `FilePattern`, see `?==` for the pattern rules. Patterns with no wildcards have higher priority than those with wildcards, and no file required by the system may be matched by more than one pattern at the same priority (see `priority` and `alternatives` to modify this behaviour). This function will create the directory for the result file, if necessary.

    "*.asm.o" %> \out -> do
        let src = dropExtension out
        need [src]
        cmd "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.

If the `Action` completes successfully the file is considered up-to-date, even if the file has not changed.

(|%>) :: Located => [FilePattern] -> (FilePath -> Action ()) -> Rules () infix 1 #

Define a set of patterns, and if any of them match, run the associated rule. Defined in terms of `%>`. Think of it as the OR (`||`) equivalent of `%>`.

(?>) :: Located => (FilePath -> Bool) -> (FilePath -> Action ()) -> Rules () infix 1 #

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`. This function will create the directory for the result file, if necessary.

    (all isUpper . takeBaseName) ?> \out -> do
        let src = replaceBaseName out $ map toLower $ takeBaseName out
        writeFile' out . map toUpper =<< readFile' src

If the `Action` completes successfully the file is considered up-to-date, even if the file has not changed.

phony :: Located => String -> Action () -> Rules () #

Declare a Make-style phony action. A phony target does not name a file (despite living in the same namespace as file rules); rather, it names some action to be executed when explicitly requested. You can demand `phony` rules using `want`. (And `need`, although that's not recommended.)

Phony actions are intended to define recipes that can be executed by the user. If you `need` a phony action in a rule then every execution where that rule is required will rerun both the rule and the phony action. However, note that phony actions are never executed more than once in a single build run.

In make, the `.PHONY` attribute on non-file-producing rules has a similar effect. However, while in make it is acceptable to omit the `.PHONY` attribute as long as you don't create the file in question, a Shake rule which behaves this way will fail lint. For file-producing rules which should be rerun every execution of Shake, see `alwaysRerun`.

(~>) :: Located => String -> Action () -> Rules () infix 1 #

Infix operator alias for `phony`, for sake of consistency with normal rules.

phonys :: Located => (String -> Maybe (Action ())) -> Rules () #

A predicate version of `phony`, return `Just` with the `Action` for the matching rules.

(&%>) :: Located => [FilePattern] -> ([FilePath] -> Action ()) -> Rules () infix 1 #

Define a rule for building multiple files at the same time. Think of it as the AND (`&&`) equivalent of `%>`. As an example, a single invocation of GHC produces both `.hi` and `.o` files:

    ["*.o","*.hi"] &%> \[o,hi] -> do
        let hs = o -<.> "hs"
        need ... -- all files the .hs import
        cmd "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. This function will create directories for the result files, if necessary.

(&?>) :: Located => (FilePath -> Maybe [FilePath]) -> ([FilePath] -> Action ()) -> Rules () infix 1 #

Define a rule for building multiple files at the same time, a more powerful and more dangerous version of `&%>`. Think of it as the AND (`&&`) equivalent 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:

    forAll $ \x ys -> test x == Just ys ==> x `elem` ys && all ((== Just ys) . test) ys

Intuitively, the function defines a set partitioning, mapping each element to the partition that contains it. As an example of a function satisfying the invariant:

    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]`.

orderOnly :: [FilePath] -> Action () #

Define order-only dependencies, these are dependencies that will always be built before continuing, but which aren't dependencies of this action. Mostly useful for defining generated dependencies you think might be real dependencies. If they turn out to be real dependencies, you should add an explicit dependency afterwards.

    "source.o" %> \out -> do
        orderOnly ["header.h"]
        cmd_ "gcc -c source.c -o source.o -MMD -MF source.m"
        neededMakefileDependencies "source.m"

If `header.h` is included by `source.c` then the call to `needMakefileDependencies` will cause it to be added as a real dependency. If it isn't, then the rule won't rebuild if it changes.

orderOnlyAction :: Action a -> Action a #

Run an action but do not depend on anything the action uses. A more general version of `orderOnly`.

type FilePattern = String #

A type synonym for file patterns, containing `//` and `*`. For the syntax and semantics of `FilePattern` see `?==`.

Most `normaliseEx`d `FilePath` values are suitable as `FilePattern` values which match only that specific file. On Windows `\` is treated as equivalent to `/`.

You can write `FilePattern` values as a literal string, or build them up using the operators `<.>`, `</>` and `<//>`. However, beware that:

- On Windows, use `<.>` from Development.Shake.FilePath instead of from System.FilePath - otherwise `"//*" <.> exe` results in `"//*\\.exe"`.
- If the second argument of `</>` has a leading path separator (namely `/`) then the second argument will be returned.

(?==) :: FilePattern -> FilePath -> Bool #

Match a `FilePattern` against a `FilePath`, There are three special forms:

- `*` matches an entire path component, excluding any separators.
- `//` matches an arbitrary number of path components, including absolute path prefixes.
- `**` as a path component matches an arbitrary number of path components, but not absolute path prefixes. Currently considered experimental.

Some examples:

- `test.c` matches `test.c` and nothing else.
- `*.c` matches all `.c` files in the current directory, so `file.c` matches, but `file.h` and `dir/file.c` don't.
- `//*.c` matches all `.c` files anywhere on the filesystem, so `file.c`, `dir/file.c`, `dir1/dir2/file.c` and `/path/to/file.c` all match, but `file.h` and `dir/file.h` don't.
- `dir/*/*` matches all files one level below `dir`, so `dir/one/file.c` and `dir/two/file.h` match, but `file.c`, `one/dir/file.c`, `dir/file.h` and `dir/one/two/file.c` don't.

Patterns with constructs such as `foo/../bar` will never match normalised `FilePath` values, so are unlikely to be correct.

(<//>) :: FilePattern -> FilePattern -> FilePattern infixr 5 #

Join two `FilePattern` values by inserting two `/` characters between them. Will first remove any trailing path separators on the first argument, and any leading separators on the second.

    "dir" <//> "*" == "dir//*"

filePattern :: FilePattern -> FilePath -> Maybe [String] #

Like `?==`, but returns `Nothing` on if there is no match, otherwise `Just` with the list of fragments matching each wildcard. For example:

    filePattern "**/*.c" "test.txt" == Nothing
    filePattern "**/*.c" "foo.c" == Just ["","foo"]
    filePattern "**/*.c" "bar/baz/foo.c" == Just ["bar/baz/","foo"]

Note that the `**` will often contain a trailing `/`, and even on Windows any `\` separators will be replaced by `/`.

needed :: Partial => [FilePath] -> Action () #

Like `need`, but if `shakeLint` is set, check that the file does not rebuild. Used for adding dependencies on files that have already been used in this rule.

trackRead :: [FilePath] -> Action () #

Track that a file was read by the action preceding it. If `shakeLint` is activated then these files must be dependencies of this rule. Calls to `trackRead` are automatically inserted in `LintFSATrace` mode.

trackWrite :: [FilePath] -> Action () #

Track that a file was written by the action preceding it. If `shakeLint` is activated then these files must either be the target of this rule, or never referred to by the build system. Calls to `trackWrite` are automatically inserted in `LintFSATrace` mode.

trackAllow :: [FilePattern] -> Action () #

Allow accessing a file in this rule, ignoring any subsequent `trackRead` / `trackWrite` calls matching the pattern.

# Directory rules

doesFileExist :: FilePath -> Action Bool #

Returns `True` if the file exists. The existence of the file is tracked as a dependency, and if the file is created or deleted the rule will rerun in subsequent builds. Usually used to implement include paths. For example, given a include path of `foo` and `bar`, and a file `hello.txt`, you might write:

    b <- doesFileExist "foo/hello.txt"
    let file = if b then "foo/hello.txt" else "bar/hello.txt"

Now if the user had a file `bar/hello.txt`, and then creates a file `foo/hello.txt`, the rule would correctly rerun, as while the `hello.txt` that was used didn't change, which file should be used has changed.

You should not call `doesFileExist` on files which can be created by the build system. The reason is that Shake operations such as this one are both cached for the duration of the build, and may be run preemptively during a recheck. That means you can't control the time at which `doesFileExist` is called. For that to be consistent, `doesFileExist` must return the same result at the start and end of the build, a property that is partially checked by the `--lint` flag. Given a file created by the build system, a build from clean will return `False` at the beginning and `True` at the end, leading to a change, and thus rebuilds in subsequent runs.

If you do want to know whether a file exists separate to the build system, e.g. you can perfectly predict the files contents and can save some meaningful work if the file already exists, you should use the untracked System.Directory version. Such calls are not tracked by the file system, and you should take care not to result in unpredictable results.

doesDirectoryExist :: FilePath -> Action Bool #

Returns `True` if the directory exists. The existence of the directory is tracked as a dependency, and if the directory is created or delete the rule will rerun in subsequent builds.

You should not call `doesDirectoryExist` on directories which can be created by the build system, for reasons explained in `doesFileExist`.

getDirectoryContents :: FilePath -> Action [FilePath] #

Get the contents of a directory. The result will be sorted, and will not contain the entries `.` or `..` (unlike the standard Haskell version). The resulting paths will be relative to the first argument. The result itself is tracked as a dependency, but the files in the result are not. If the list of files changes in subsequent builds any rule calling it will rerun.

It is usually simpler to call either `getDirectoryFiles` or `getDirectoryDirs`.

getDirectoryFiles :: FilePath -> [FilePattern] -> Action [FilePath] #

Get the files anywhere under a directory that match any of a set of patterns. For the interpretation of the patterns see `?==`. All results will be relative to the directory argument. The result itself is tracked as a dependency, but the files in the result are not. If the list of files changes in subsequent builds any rule calling it will rerun. Some examples:

    getDirectoryFiles "Config" ["//*.xml"]
        -- All .xml files anywhere under the Config directory
        -- If Config/foo/bar.xml exists it will return ["foo/bar.xml"]
    getDirectoryFiles "Modules" ["*.hs","*.lhs"]
        -- All .hs or .lhs in the Modules directory
        -- If Modules/foo.hs and Modules/foo.lhs exist, it will return ["foo.hs","foo.lhs"]

If you require a qualified file name it is often easier to use `""` as the `FilePath` argument, for example the following two expressions are equivalent:

    fmap (map ("Config" </>)) (getDirectoryFiles "Config" ["//*.xml"])
    getDirectoryFiles "" ["Config//*.xml"]

If the first argument directory does not exist it will raise an error. If `foo` does not exist, then the first of these error, but the second will not.

    getDirectoryFiles "foo" ["//*"] -- error
    getDirectoryFiles "" ["foo//*"] -- returns []

This function is tracked and serves as a dependency. If a rule calls `getDirectoryFiles "" ["*.c"]` and someone adds `foo.c` to the directory, that rule will rebuild. If someone changes one of the `.c` files, but the list of `.c` files doesn't change, then it will not rebuild. As a consequence of being tracked, if the contents change during the build (e.g. you are generating `.c` files in this directory) then the build not reach a stable point, which is an error - detected by running with `--lint`. You should normally only call this function returning source files.

For an untracked variant see `getDirectoryFilesIO`.

getDirectoryDirs :: FilePath -> Action [FilePath] #

Get the directories in a directory, not including `.` or `..`. All directories are relative to the argument directory. The result itself is tracked as a dependency, but the directories in the result are not. If the list of directories changes in subsequent builds any rule calling it will rerun.

getDirectoryFilesIO :: FilePath -> [FilePattern] -> IO [FilePath] #

A version of `getDirectoryFiles` that is in IO, and thus untracked.

# Environment rules

getEnv :: String -> Action (Maybe String) #

Return `Just` the value of the environment variable, or `Nothing` if the variable is not set. The environment variable is tracked as a dependency, and if it changes the rule will rerun in subsequent builds. This function is a tracked version of `getEnv` / `lookupEnv` from the base library.

    flags <- getEnv "CFLAGS"
    cmd "gcc -c" [out] (maybe [] words flags)

getEnvWithDefault :: String -> String -> Action String #

``getEnvWithDefault` def var` returns the value of the environment variable `var`, or the default value `def` if it is not set. Similar to `getEnv`.

    flags <- getEnvWithDefault "-Wall" "CFLAGS"
    cmd "gcc -c" [out] flags

getEnvError :: Partial => String -> Action String #

A partial variant of `getEnv` that returns the environment variable variable or fails.

# Oracle rules

type ShakeValue a = (Show a, Typeable a, Eq a, Hashable a, Binary a, NFData a) #

Define an alias for the six type classes required for things involved in Shake rules. Using this alias requires the `ConstraintKinds` extension.

To define your own values meeting the necessary constraints it is convenient to use the extensions `GeneralizedNewtypeDeriving` and `DeriveDataTypeable` to write:

    newtype MyType = MyType (String, Bool) deriving (Show, Typeable, Eq, Hashable, Binary, NFData)

Shake needs these instances on keys and values. They are used for:

- `Show` is used to print out keys in errors, profiling, progress messages and diagnostics.
- `Typeable` is used because Shake indexes its database by the type of the key and value involved in the rule (overlap is not allowed for type classes and not allowed in Shake either).
- `Eq` and `Hashable` are used on keys in order to build hash maps from keys to values. `Eq` is used on values to test if the value has changed or not (this is used to support unchanging rebuilds, where Shake can avoid rerunning rules if it runs a dependency, but it turns out that no changes occurred.) The `Hashable` instances are only use at runtime (never serialised to disk), so they do not have to be stable across runs. Hashable on values is not used, and only required for a consistent interface.
- `Binary` is used to serialize keys and values into Shake's build database; this lets Shake cache values across runs and implement unchanging rebuilds.
- `NFData` is used to avoid space and thunk leaks, especially when Shake is parallelized.

type family RuleResult key #

The type mapping between the `key` or a rule and the resulting `value`. See `addBuiltinRule` and `apply`.

addOracle :: (RuleResult q ~ a, ShakeValue q, ShakeValue a, Partial) => (q -> Action a) -> Rules (q -> Action a) #

Add extra information which rules can depend on. An oracle is a function from a question type `q`, to an answer type `a`. As an example, we can define an oracle allowing you to depend on the current version of GHC:

    newtype GhcVersion = GhcVersion () deriving (Show,Typeable,Eq,Hashable,Binary,NFData)
    type instance RuleResult GhcVersion = String
    rules = do
        addOracle $ \(GhcVersion _) -> fromStdout <$> cmd "ghc --numeric-version" :: Action String
        ... rules ...

If a rule calls ``askOracle` (GhcVersion ())`, that rule will be rerun whenever the GHC version changes. Some notes:

- We define `GhcVersion` with a `newtype` around `()`, allowing the use of `GeneralizedNewtypeDeriving`. All the necessary type classes are exported from Development.Shake.Classes.
- The `type instance` requires the extension `TypeFamilies`.
- Each call to `addOracle` must use a different type of question.
- Actions passed to `addOracle` will be run in every build they are required, even if nothing else changes, so be careful of slow actions. If the result of an oracle does not change it will not invalidate any rules depending on it. To always rerun files rules see `alwaysRerun`.

As a more complex example, consider tracking Haskell package versions:

    newtype GhcPkgList = GhcPkgList () deriving (Show,Typeable,Eq,Hashable,Binary,NFData)
    type instance RuleResult GhcPkgList = [(String, String)]
    newtype GhcPkgVersion = GhcPkgVersion String deriving (Show,Typeable,Eq,Hashable,Binary,NFData)
    type instance RuleResult GhcPkgVersion = Maybe String

    rules = do
        getPkgList <- addOracle $ \GhcPkgList{} -> do
            Stdout out <- cmd "ghc-pkg list --simple-output"
            pure [(reverse b, reverse a) | x <- words out, let (a,_:b) = break (== '-') $ reverse x]

        getPkgVersion <- addOracle $ \(GhcPkgVersion pkg) -> do
            pkgs <- getPkgList $ GhcPkgList ()
            pure $ lookup pkg pkgs

        "myrule" %> \_ -> do
            getPkgVersion $ GhcPkgVersion "shake"
            ... rule using the shake version ...

Using these definitions, any rule depending on the version of `shake` should call `getPkgVersion $ GhcPkgVersion "shake"` to rebuild when `shake` is upgraded.

If you apply `versioned` to an oracle it will cause that oracle result to be discarded, and not do early-termination.

addOracleCache :: (RuleResult q ~ a, ShakeValue q, ShakeValue a, Partial) => (q -> Action a) -> Rules (q -> Action a) #

A combination of `addOracle` and `newCache` - an action that only runs when its dependencies change, whose result is stored in the database.

- Does the information need recomputing every time? e.g. looking up stuff in the environment? If so, use `addOracle` instead.
- Is the action mostly deserisalising some file? If so, use `newCache`.
- Is the operation expensive computation from other results? If so, use `addOracleCache`.

An alternative to using `addOracleCache` is introducing an intermediate file containing the result, which requires less storage in the Shake database and can be inspected by existing file-system viewing tools.

addOracleHash :: (RuleResult q ~ a, ShakeValue q, ShakeValue a, Partial) => (q -> Action a) -> Rules (q -> Action a) #

An alternative to to `addOracle` that relies on the `hash` function providing a perfect equality, doesn't support `--skip`, but requires less storage.

askOracle :: (RuleResult q ~ a, ShakeValue q, ShakeValue a) => q -> Action a #

Get information previously added with `addOracle` or `addOracleCache`. The question/answer types must match those provided previously.

askOracles :: (RuleResult q ~ a, ShakeValue q, ShakeValue a) => [q] -> Action [a] #

A parallel version of `askOracle`.

# Special rules

alwaysRerun :: Action () #

Always rerun the associated action. Useful for defining rules that query the environment. For example:

    "ghcVersion.txt" %> \out -> do
        alwaysRerun
        Stdout stdout <- cmd "ghc --numeric-version"
        writeFileChanged out stdout

In `make`, the `.PHONY` attribute on file-producing rules has a similar effect.

Note that `alwaysRerun` is applied when a rule is executed. Modifying an existing rule to insert `alwaysRerun` will not cause that rule to rerun next time.

# Resources

data Resource #

A type representing an external resource which the build system should respect. There are two ways to create `Resource`s in Shake:

- `newResource` creates a finite resource, stopping too many actions running simultaneously.
- `newThrottle` creates a throttled resource, stopping too many actions running over a short time period.

These resources are used with `withResource` when defining rules. Typically only system commands (such as `cmd`) should be run inside `withResource`, not commands such as `need`.

Be careful that the actions run within `withResource` do not themselves require further resources, or you may get a "thread blocked indefinitely in an MVar operation" exception. If an action requires multiple resources, use `withResources` to avoid deadlock.

#### Instances

Instances details

Show Resource # |
Instance details Defined in Development.Shake.Internal.Resource Methods showsPrec :: Int -> Resource -> ShowS # show :: Resource -> String # showList :: [Resource] -> ShowS #
Eq Resource # |
Instance details Defined in Development.Shake.Internal.Resource Methods (==) :: Resource -> Resource -> Bool # (/=) :: Resource -> Resource -> Bool #
Ord Resource # |
Instance details Defined in Development.Shake.Internal.Resource Methods compare :: Resource -> Resource -> Ordering # (<) :: Resource -> Resource -> Bool # (<=) :: Resource -> Resource -> Bool # (>) :: Resource -> Resource -> Bool # (>=) :: Resource -> Resource -> Bool # max :: Resource -> Resource -> Resource # min :: Resource -> Resource -> Resource #

newResource :: String -> Int -> Rules Resource #

Create a finite resource, given a name (for error messages) and a quantity of the resource that exists. Shake will ensure that actions using the same finite resource do not execute in parallel. 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:

    shake shakeOptions{shakeThreads=2} $ do
       want ["a.xls","b.xls"]
       excel <- newResource "Excel" 1
       "*.xls" %> \out ->
           withResource excel 1 $
               cmd "excel" out ...

Now the two calls to `excel` will not happen in parallel.

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:

    disk <- newResource "Disk" 4
    want [show i <.> "exe" | i <- [1..100]]
    "*.exe" %> \out ->
        withResource disk 1 $
            cmd "ld -o" [out] ...
    "*.o" %> \out ->
        cmd "cl -o" [out] ...

newResourceIO :: String -> Int -> IO Resource #

A version of `newResource` that runs in IO, and can be called before calling `shake`. Most people should use `newResource` instead.

withResource :: Resource -> Int -> Action a -> Action a #

Run an action which uses part of a finite resource. For more details see `Resource`. You cannot depend on a rule (e.g. `need`) while a resource is held.

withResources :: [(Resource, Int)] -> Action a -> Action a #

Run an action which uses part of several finite resources. Acquires the resources in a stable order, to prevent deadlock. If all rules requiring more than one resource acquire those resources with a single call to `withResources`, resources will not deadlock.

newThrottle :: String -> Int -> Double -> Rules Resource #

Create a throttled resource, given a name (for error messages) and a number of resources (the `Int`) that can be used per time period (the `Double` in seconds). Shake will ensure that actions using the same throttled resource do not exceed the limits. As an example, let us assume that making more than 1 request every 5 seconds to Google results in our client being blacklisted, we can write:

    google <- newThrottle "Google" 1 5
    "*.url" %> \out -> do
        withResource google 1 $
            cmd "wget" ["https://google.com?q=" ++ takeBaseName out] "-O" [out]

Now we will wait at least 5 seconds after querying Google before performing another query. If Google change the rules to allow 12 requests per minute we can instead use ``newThrottle` "Google" 12 60`, which would allow greater parallelisation, and avoid throttling entirely if only a small number of requests are necessary.

In the original example we never make a fresh request until 5 seconds after the previous request has completed. If we instead want to throttle requests since the previous request started we can write:

    google <- newThrottle "Google" 1 5
    "*.url" %> \out -> do
        withResource google 1 $ pure ()
        cmd "wget" ["https://google.com?q=" ++ takeBaseName out] "-O" [out]

However, the rule may not continue running immediately after `withResource` completes, so while we will never exceed an average of 1 request every 5 seconds, we may end up running an unbounded number of requests simultaneously. If this limitation causes a problem in practice it can be fixed.

newThrottleIO :: String -> Int -> Double -> IO Resource #

A version of `newThrottle` that runs in IO, and can be called before calling `shake`. Most people should use `newThrottle` instead.

unsafeExtraThread :: Action a -> Action a #

Run an action without counting to the thread limit, typically used for actions that execute on remote machines using barely any local CPU resources. Unsafe as it allows the `shakeThreads` limit to be exceeded. You cannot depend on a rule (e.g. `need`) while the extra thread is executing. If the rule blocks (e.g. calls `withResource`) then the extra thread may be used by some other action. Only really suitable for calling `cmd` / `command`.

# Cache

newCache :: (Eq k, Hashable k) => (k -> Action v) -> Rules (k -> Action v) #

Given an action on a key, produce a cached version that will execute the action at most once per key per run. Using the cached result will still result include any dependencies that the action requires - e.g. if the action does `need` then those dependencies will be added to every rule that uses that cache. Each call to `newCache` creates a separate cache that is independent of all other calls to `newCache`.

The operations will not be cached between runs and nothing will be persisted to the Shake database. For an alternative that does persist the cache, see `addOracleCache`.

This function is useful when creating files that store intermediate values, to avoid the overhead of repeatedly reading from disk, particularly if the file requires expensive parsing. As an example:

    digits <- newCache $ \file -> do
        src <- readFile' file
        pure $ length $ filter isDigit src
    "*.digits" %> \x -> do
        v1 <- digits (dropExtension x)
        v2 <- digits (dropExtension x)
        writeFile' x $ show (v1,v2)

To create the result `MyFile.txt.digits` the file `MyFile.txt` will be read and counted, but only at most once per execution.

newCacheIO :: (Eq k, Hashable k) => (k -> Action v) -> IO (k -> Action v) #

A version of `newCache` that runs in IO, and can be called before calling `shake`. Most people should use `newCache` instead.

historyDisable :: Action () #

This rule should not be saved to shared/cloud storage via `shakeShare`. There are usually two reasons to call this function:

1. It makes use of untracked dependencies that are specific to this machine, e.g. files in a system directory or items on the `$PATH`.
2. The rule is trivial to compute locally, so there is no point sharing it.

If you want the rule to not be cached at all, use `alwaysRerun`.

produces :: [FilePath] -> Action () #

This rule builds the following files, in addition to any defined by its target. At the end of the rule these files must have been written. These files must not be tracked as part of the build system - two rules cannot produce the same file and you cannot `need` the files it produces.

# Batching

needHasChanged :: Partial => [FilePath] -> Action [FilePath] #

Like `need` but returns a list of rebuilt dependencies since the calling rule last built successfully.

The following example writes a list of changed dependencies to a file as its action.

    "target" %> \out -> do
          let sourceList = ["source1", "source2"]
          rebuildList <- needHasChanged sourceList
          writeFileLines out rebuildList

This function can be used to alter the action depending on which dependency needed to be rebuild.

Note that a rule can be run even if no dependency has changed, for example because of `shakeRebuild` or because the target has changed or been deleted. To detect the latter case you may wish to use `resultHasChanged`.

resultHasChanged :: FilePath -> Action Bool #

Has a file changed. This function will only give the correct answer if called in the rule producing the file, before the rule has modified the file in question. Best avoided, but sometimes necessary in conjunction with `needHasChanged` to cause rebuilds to happen if the result is deleted or modified.

batch #

Arguments

:: Int | Maximum number to run in a single batch, e.g. `3`, must be positive.
-> ((a -> Action ()) -> Rules ()) | Way to match an entry, e.g. `"*.ext" `%>``.
-> (a -> Action b) | Preparation to run individually on each, e.g. using `need`.
-> ([b] -> Action ()) | Combination action to run on all, e.g. using `cmd`.
-> Rules () |

Batch different outputs into a single `Action`, typically useful when a command has a high startup cost - e.g. `apt-get install foo bar baz` is a lot cheaper than three separate calls to `apt-get install`. As an example, if we have a standard build rule:

    "*.out" %> \out -> do
        need [out -<.> "in"]
        cmd "build-multiple" [out -<.> "in"]

Assuming that `build-multiple` can compile multiple files in a single run, and that the cost of doing so is a lot less than running each individually, we can write:

    batch 3 ("*.out" %>)
        (\out -> do need [out -<.> "in"]; pure out)
        (\outs -> cmd "build-multiple" [out -<.> "in" | out <- outs])

In constrast to the normal call, we have specified a maximum batch size of 3, an action to run on each output individually (typically all the `need` dependencies), and an action that runs on multiple files at once. If we were to require lots of `*.out` files, they would typically be built in batches of 3.

If Shake ever has nothing else to do it will run batches before they are at the maximum, so you may see much smaller batches, especially at high parallelism settings.

reschedule :: Double -> Action () #

Given a running task, reschedule so it only continues after all other pending tasks, and all rescheduled tasks with a higher pool priority. Note that due to parallelism there is no guarantee that all actions of a higher pool priority will have completed before the action resumes. Only useful if the results are being interactively reported or consumed.

# Deprecated

askOracleWith :: (RuleResult q ~ a, ShakeValue q, ShakeValue a) => q -> a -> Action a #

Deprecated: Use 'askOracle q' instead of 'askOracleWith q a', the result value is now unnecessary

Deprecated: Replace ``askOracleWith` q a` by ``askOracle` q` since the `RuleResult` type family now fixes the result type.

deprioritize :: Double -> Action () #

Deprecated: Use `reschedule` instead

Deprecated: Alias for `reschedule`.

pattern Quiet :: Verbosity #

Deprecated: A bidirectional pattern synonym for `Error`.

pattern Normal :: Verbosity #

Deprecated: A bidirectional pattern synonym for `Info`.

pattern Loud :: Verbosity #

Deprecated: A bidirectional pattern synonym for `Verbose`.

pattern Chatty :: Verbosity #

Deprecated: A bidirectional pattern synonym for `Verbose`.

putLoud :: String -> Action () #

Deprecated: Alias for `putVerbose`.

putNormal :: String -> Action () #

Deprecated: Alias for `putInfo`.

putQuiet :: String -> Action () #

Deprecated: Alias for `putError`.