-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | Build system library, like Make, but more accurate dependencies. -- -- Shake is a Haskell library for writing build systems - designed as a -- replacement for make. See Development.Shake for an -- introduction, including an example. Further examples are included in -- the Cabal tarball, under the Examples directory. The homepage -- contains links to a user manual, an academic paper and further -- information: https://github.com/ndmitchell/shake -- -- To use Shake the user writes a Haskell program that imports -- Development.Shake, defines some build rules, and calls the -- Development.Shake.shakeArgs function. Thanks to do notation and -- infix operators, a simple Shake build system is not too dissimilar -- from a simple Makefile. However, as build systems get more complex, -- Shake is able to take advantage of the excellent abstraction -- facilities offered by Haskell and easily support much larger projects. -- The Shake library provides all the standard features available in -- other build systems, including automatic parallelism and minimal -- rebuilds. Shake also provides more accurate dependency tracking, -- including seamless support for generated files, and dependencies on -- system information (e.g. compiler version). @package shake @version 0.13 -- | This module reexports the six necessary type classes that every -- Rule type must support. You can use this module to define new -- rules without depending on the binary, deepseq and -- hashable packages. module Development.Shake.Classes -- | Conversion of values to readable Strings. -- -- Minimal complete definition: showsPrec or show. -- -- Derived instances of Show have the following properties, which -- are compatible with derived instances of Read: -- --
-- infixr 5 :^: -- data Tree a = Leaf a | Tree a :^: Tree a ---- -- the derived instance of Show is equivalent to -- --
-- instance (Show a) => Show (Tree a) where -- -- showsPrec d (Leaf m) = showParen (d > app_prec) $ -- showString "Leaf " . showsPrec (app_prec+1) m -- where app_prec = 10 -- -- showsPrec d (u :^: v) = showParen (d > up_prec) $ -- showsPrec (up_prec+1) u . -- showString " :^: " . -- showsPrec (up_prec+1) v -- where up_prec = 5 ---- -- Note that right-associativity of :^: is ignored. For example, -- --
-- decode . encode == id ---- -- That is, the get and put methods should be the inverse -- of each other. A range of instances are provided for basic Haskell -- types. class Binary t put :: Binary t => t -> Put get :: Binary t => Get t -- | A class of types that can be fully evaluated. class NFData a rnf :: NFData a => a -> () -- | A module for FilePath operations, to be used instead of -- System.FilePath when writing build systems. In build systems, -- when using the file name as a key for indexing rules, it is important -- that two different strings do not refer to the same on-disk file. We -- therefore follow the conventions: -- --
-- dropDirectory1 "aaa/bbb" == "bbb" -- dropDirectory1 "aaa/" == "" -- dropDirectory1 "aaa" == "" -- dropDirectory1 "" == "" --dropDirectory1 :: FilePath -> FilePath -- | Take the first component of a FilePath. Should only be used on -- relative paths. -- --
-- takeDirectory1 "aaa/bbb" == "aaa" -- takeDirectory1 "aaa/" == "aaa" -- takeDirectory1 "aaa" == "aaa" --takeDirectory1 :: FilePath -> FilePath -- | Normalise a FilePath, trying to do: -- --
-- combine "aaa/bbb" "ccc" == "aaa/bbb/ccc" -- combine "aaa/bbb" "./ccc" == "aaa/bbb/ccc" -- combine "aaa/bbb" "../ccc" == "aaa/ccc" --combine :: FilePath -> FilePath -> FilePath -- | The extension of executables, "exe" on Windows and -- "" otherwise. exe :: String -- | This module provides functions for calling command line programs, -- primarily command and cmd. As a simple example: -- --
-- command [] "gcc" ["-c",myfile] ---- -- The functions from this module are now available directly from -- Development.Shake. You should only need to import this module -- if you are using the cmd function in the IO monad. module Development.Shake.Command -- | 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_. command :: CmdResult r => [CmdOption] -> String -> [String] -> Action r -- | A version of command where you do not require any results, used -- to avoid errors about being unable to deduce CmdResult. command_ :: [CmdOption] -> String -> [String] -> Action () -- | Execute a system command. Before running cmd make sure you -- need any files that are used by the command. -- --
-- () <- 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 ---- -- When passing file arguments we use [myfile] so that if the -- myfile variable contains spaces they are properly escaped. -- -- 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, bind the result to (), -- or include a type signature. -- -- The cmd command can also be run in the IO monad, but -- then Traced is ignored and command lines are not echoed. cmd :: CmdArguments args => args :-> Action r -- | Collect the stdout of the process. If you are collecting the -- stdout, it will not be echoed to the terminal, unless you -- include EchoStdout. newtype Stdout Stdout :: String -> Stdout fromStdout :: Stdout -> String -- | Collect the stderr of the process. If you are collecting the -- stderr, it will not be echoed to the terminal, unless you -- include EchoStderr. newtype Stderr Stderr :: String -> Stderr fromStderr :: Stderr -> String -- | Collect the ExitCode of the process. If you do not collect the -- exit code, any ExitFailure will cause an exception. newtype Exit Exit :: ExitCode -> Exit fromExit :: Exit -> ExitCode -- | A class for specifying what results you want to collect from a -- process. Values are formed of Stdout, Stderr, -- Exit and tuples of those. class CmdResult a -- | Options passed to command or cmd to control how -- processes are executed. data CmdOption -- | Change the current directory in the spawned process. By default uses -- this processes current directory. Cwd :: FilePath -> CmdOption -- | Change the environment variables in the spawned process. By default -- uses this processes environment. Use addPath to modify the -- $PATH variable, or addEnv to modify other variables. Env :: [(String, String)] -> CmdOption -- | Given as the stdin of the spawned process. By default no -- stdin is given. Stdin :: String -> CmdOption -- | Pass the command to the shell without escaping - any arguments will be -- joined with spaces. By default arguments are escaped properly. Shell :: CmdOption -- | Treat the stdin/stdout/stderr messages as -- binary. By default streams use text encoding. BinaryPipes :: CmdOption -- | Name to use with traced, or "" for no tracing. By -- default traces using the name of the executable. Traced :: String -> CmdOption -- | Should I include the stderr in the exception if the command -- fails? Defaults to True. WithStderr :: Bool -> CmdOption -- | Should I echo the stdout? Defaults to True unless a -- Stdout result is required. EchoStdout :: Bool -> CmdOption -- | Should I echo the stderr? Defaults to True unless a -- Stderr result is required. EchoStderr :: Bool -> CmdOption -- | Produce a CmdOption of value Env that is the current -- environment, plus 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. addPath :: MonadIO m => [String] -> [String] -> m CmdOption -- | Produce a CmdOption of value Env that is the current -- environment, plus the argument environment variables. 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.
addEnv :: MonadIO m => [(String, String)] -> m CmdOption
instance Eq CmdOption
instance Ord CmdOption
instance Show CmdOption
instance Eq Result
instance Arg [CmdOption]
instance Arg CmdOption
instance Arg [String]
instance Arg String
instance CmdResult r => CmdArguments (IO r)
instance CmdResult r => CmdArguments (Action r)
instance (Arg a, CmdArguments r) => CmdArguments (a -> r)
instance (CmdResult x1, CmdResult x2, CmdResult x3) => CmdResult (x1, x2, x3)
instance (CmdResult x1, CmdResult x2) => CmdResult (x1, x2)
instance CmdResult ()
instance CmdResult Stderr
instance CmdResult Stdout
instance CmdResult ExitCode
instance CmdResult Exit
-- | This module is used for defining new types of rules for Shake build
-- systems. Most users will find the built-in set of rules sufficient.
module Development.Shake.Rule
-- | Define an alias for the six type classes required for things involved
-- in Shake Rules. This alias is only available in GHC 7.4 and
-- above, and 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) --type ShakeValue a = (Show a, Typeable a, Eq a, Hashable a, Binary a, NFData a) -- | Define a pair of types that can be used by Shake rules. To import all -- the type classes required see Development.Shake.Classes. class (ShakeValue key, ShakeValue value) => Rule key value where equalValue _ _ v1 v2 = if v1 == v2 then EqualCheap else NotEqual storedValue :: Rule key value => ShakeOptions -> key -> IO (Maybe value) equalValue :: Rule key value => ShakeOptions -> key -> value -> value -> EqualCost -- | An equality check and a cost. data EqualCost -- | The equality check was cheap. EqualCheap :: EqualCost -- | The equality check was expensive, as the results are not trivially -- equal. EqualExpensive :: EqualCost -- | The values are not equal. NotEqual :: EqualCost -- | Add a rule to build a key, returning an appropriate Action. All -- rules at a given priority must be disjoint. Rules have priority 1 by -- default, but can be modified with priority. rule :: Rule key value => (key -> Maybe (Action value)) -> Rules () -- | Execute a rule, returning the associated values. If possible, the -- rules will be run in parallel. This function requires that appropriate -- rules have been added with rule. All key values passed -- to apply become dependencies of the Action. apply :: Rule key value => [key] -> Action [value] -- | Apply a single rule, equivalent to calling apply with a -- singleton list. Where possible, use apply to allow parallelism. apply1 :: Rule key value => key -> Action value -- | Track that a key has been used by the action preceeding it. trackUse :: ShakeValue key => key -> Action () -- | Track that a key has been changed by the action preceeding it. trackChange :: ShakeValue key => key -> Action () -- | Allow any matching key to violate the tracking rules. trackAllow :: ShakeValue key => (key -> Bool) -> Action () -- | A deprecated way of defining a low priority rule. Defined as: -- --
-- defaultRule = priority 0 . rule ---- | Deprecated: Use rule with priority 0 defaultRule :: Rule key value => (key -> Maybe (Action value)) -> Rules () -- | 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: -- --
-- ghc --make MyBuildSystem -rtsopts -with-rtsopts=-I0 ---- --
-- 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. All arguments to action may be -- run in parallel, in any order. -- -- For the standard requirement of only needing a fixed list of -- files in the action, see want. action :: Action a -> Rules () -- | Remove all actions specified in a set of rules, usually used for -- implementing command line specification of what to build. withoutActions :: Rules () -> Rules () -- | 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. alternatives :: Rules () -> Rules () -- | Change the priority of a given set of rules, where higher priorities -- 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. priority :: Double -> Rules () -> Rules () -- | The Action monad, use liftIO to raise IO actions -- into it, and need to execute files. Action values are used by -- rule and action. The Action monad tracks the -- dependencies of a Rule. data 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. The trace list is used for profile -- reports (see shakeReport). traced :: String -> IO a -> Action a -- | Lift a computation from the IO monad. liftIO :: MonadIO m => forall a. IO a -> m a -- | If an exception is raised by the Action, perform some -- IO. actionOnException :: Action a -> IO b -> Action a -- | After an Action, perform some IO, even if there is an -- exception. actionFinally :: Action a -> IO b -> Action a -- | Error representing all expected exceptions thrown by Shake. Problems -- when executing rules will be raising using this exception type. data ShakeException ShakeException :: String -> [String] -> SomeException -> ShakeException -- | The target that was being built when the exception occured. shakeExceptionTarget :: ShakeException -> String -- | The stack of targets, where the shakeExceptionTarget is last. shakeExceptionStack :: ShakeException -> [String] -- | The underlying exception that was raised. shakeExceptionInner :: ShakeException -> SomeException -- | 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 Function, because Data cannot be defined
-- for functions.
data ShakeOptions
ShakeOptions :: FilePath -> Int -> String -> Verbosity -> Bool -> [FilePath] -> Maybe Lint -> Maybe Double -> Maybe Assume -> [(String, String)] -> Bool -> Bool -> Bool -> Bool -> Change -> (IO Progress -> IO ()) -> (Verbosity -> String -> IO ()) -> ShakeOptions
-- | Defaults to .shake. The prefix of the filename used for
-- storing Shake metadata files. All metadata files will be named
-- shakeFiles.extension, for some
-- extension. If the shakeFiles directory does not
-- exist it will be created.
shakeFiles :: ShakeOptions -> FilePath
-- | 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.
shakeThreads :: ShakeOptions -> Int
-- | 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.
shakeVersion :: ShakeOptions -> String
-- | Defaults to Normal. What level of messages should be printed
-- out.
shakeVerbosity :: ShakeOptions -> Verbosity
-- | Defaults to False. Operate in staunch mode, where building
-- continues even after errors, similar to make --keep-going.
shakeStaunch :: ShakeOptions -> Bool
-- | Defaults to '[]'. 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, otherwise it will write HTML.
shakeReport :: ShakeOptions -> [FilePath]
-- | Defaults to Nothing. Perform sanity checks during building, see
-- Lint for details.
shakeLint :: ShakeOptions -> Maybe Lint
-- | Defaults to Just 10. How often to flush Shake metadata
-- files in seconds, or Nothing to never flush explicitly. It is
-- possible that on abnormal termination (not Haskell exceptions) any
-- rules that completed in the last shakeFlush seconds will be
-- lost.
shakeFlush :: ShakeOptions -> Maybe Double
-- | Defaults to Nothing. Assume all build objects are clean/dirty,
-- see Assume for details. Can be used to implement make
-- --touch.
shakeAssume :: ShakeOptions -> Maybe Assume
-- | Defaults to []. 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).
shakeAbbreviations :: ShakeOptions -> [(String, String)]
-- | Defaults to False. Write a message to
-- shakeFiles.storage whenever a storage event happens
-- which may impact on the current stored progress. Examples include
-- database version number changes, database compaction or corrupt files.
shakeStorageLog :: ShakeOptions -> Bool
-- | Defaults to True. Change stdout and stderr to
-- line buffering while running Shake.
shakeLineBuffering :: ShakeOptions -> Bool
-- | Defaults to False. Print timing information for each stage at
-- the end.
shakeTimings :: ShakeOptions -> 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.
shakeRunCommands :: ShakeOptions -> Bool
-- | Default to ChangeModtime. How to check if a file has changed,
-- see Change for details.
shakeChange :: ShakeOptions -> Change
-- | 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.
shakeProgress :: ShakeOptions -> IO Progress -> 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.
shakeOutput :: ShakeOptions -> Verbosity -> String -> IO ()
-- | The current assumptions made by the build system, used by
-- shakeAssume. These options allow the end user to specify that
-- any rules run are either to be treated as clean, or as dirty,
-- regardless of what the build system thinks.
--
-- These assumptions only operate on files reached by the current
-- action commands. Any other files in the database are left
-- unchanged.
data Assume
-- | Assume that all rules reached are dirty and require rebuilding,
-- equivalent to storedValue always returning Nothing.
-- Useful to undo the results of AssumeClean, for benchmarking
-- rebuild speed and for rebuilding if untracked dependencies have
-- changed. This assumption is safe, but may cause more rebuilding than
-- necessary.
AssumeDirty :: Assume
-- | This assumption is unsafe, and may lead to incorrect build results
-- in this run, and in future runs. Assume and record that all rules
-- reached are clean and do not require rebuilding, provided the rule has
-- a storedValue and has been built before. Useful if you have
-- modified a file in some inconsequential way, such as only the comments
-- or whitespace, and wish to avoid a rebuild.
AssumeClean :: Assume
-- | This assumption is unsafe, and may lead to incorrect build results
-- in this run. Assume that all rules reached are clean in this run.
-- Only useful for benchmarking, to remove any overhead from running
-- storedValue operations.
AssumeSkip :: Assume
-- | Which lint checks to perform, used by shakeLint.
data Lint
-- | 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.
LintBasic :: Lint
-- | Track which files are accessed by command line programs run by
-- command or cmd, using tracker.exe as
-- supplied with the Microsoft .NET 4.5 SDK (Windows only). Also performs
-- all checks from LintBasic. Note that some programs are not
-- tracked properly, particularly cygwin programs (it seems).
LintTracker :: Lint
-- | How should you determine if a file has changed, used by
-- shakeChange. The most common values are ChangeModtime
-- (very fast, touch causes files to rebuild) and
-- ChangeModtimeAndDigestInput (a bit slower, touch does
-- not cause input files to rebuild).
data Change
-- | 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.
ChangeModtime :: Change
-- | 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.
ChangeDigest :: Change
-- | 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.
ChangeModtimeAndDigest :: Change
-- | Use ChangeModtimeAndDigest for input/source files and
-- ChangeModtime for output files.
ChangeModtimeAndDigestInput :: Change
-- | 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.
ChangeModtimeOrDigest :: Change
-- | Get the initial ShakeOptions, these will not change during the
-- build process.
getShakeOptions :: Action ShakeOptions
-- | 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 wanted (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:
--
-- -- shakeArgsWith opts flags (\flagValues argValues -> result) ---- --
-- import System.Console.GetOpt -- -- data Flags = DistCC deriving Eq -- flags = [Option "" ["distcc"] (NoArg $ Right DistCC) "Run distributed."] -- -- main = shakeArgsWith shakeOptions flags $ \flags targets -> return $ Just $ do -- if null targets then want ["result.exe"] else want targets -- let compiler = if DistCC `elem` flags then "distcc" else "gcc" -- "*.o" *> \out -> do -- need ... -- cmd compiler ... -- ... ---- -- Now you can pass --distcc to use the distcc -- compiler. shakeArgsWith :: ShakeOptions -> [OptDescr (Either String a)] -> ([a] -> [String] -> IO (Maybe (Rules ()))) -> IO () -- | 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. shakeOptDescrs :: [OptDescr (Either String (ShakeOptions -> ShakeOptions))] -- | Information about the current state of the build, obtained by passing -- a callback function to shakeProgress. Typically a program will -- use progressDisplay to poll this value and produce status -- messages, which is implemented using this data type. data Progress Progress :: !(Maybe String) -> {-# UNPACK #-} !Int -> {-# UNPACK #-} !Int -> {-# UNPACK #-} !Int -> {-# UNPACK #-} !Int -> {-# UNPACK #-} !Double -> {-# UNPACK #-} !Double -> {-# UNPACK #-} !Double -> {-# UNPACK #-} !(Double, Int) -> Progress -- | Starts out Nothing, becomes Just a target name if a rule -- fails. isFailure :: Progress -> !(Maybe String) -- | Number of rules which were required, but were already in a valid -- state. countSkipped :: Progress -> {-# UNPACK #-} !Int -- | Number of rules which were have been built in this run. countBuilt :: Progress -> {-# UNPACK #-} !Int -- | Number of rules which have been built previously, but are not yet -- known to be required. countUnknown :: Progress -> {-# UNPACK #-} !Int -- | Number of rules which are currently required (ignoring dependencies -- that do not change), but not built. countTodo :: Progress -> {-# UNPACK #-} !Int -- | Time spent building countSkipped rules in previous runs. timeSkipped :: Progress -> {-# UNPACK #-} !Double -- | Time spent building countBuilt rules. timeBuilt :: Progress -> {-# UNPACK #-} !Double -- | Time spent building countUnknown rules in previous runs. timeUnknown :: Progress -> {-# UNPACK #-} !Double -- | Time spent building countTodo rules in previous runs, plus the -- number which have no known time (have never been built before). timeTodo :: Progress -> {-# UNPACK #-} !(Double, Int) -- | 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. progressSimple :: 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. progressDisplay :: Double -> (String -> IO ()) -> IO Progress -> 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. progressTitlebar :: String -> IO () -- | Call the program shake-progress if it is on the -- $PATH. The program is called with the following arguments: -- --
-- 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_. command :: CmdResult r => [CmdOption] -> String -> [String] -> Action r -- | A version of command where you do not require any results, used -- to avoid errors about being unable to deduce CmdResult. command_ :: [CmdOption] -> String -> [String] -> Action () -- | Execute a system command. Before running cmd make sure you -- need any files that are used by the command. -- --
-- () <- 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 ---- -- When passing file arguments we use [myfile] so that if the -- myfile variable contains spaces they are properly escaped. -- -- 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, bind the result to (), -- or include a type signature. -- -- The cmd command can also be run in the IO monad, but -- then Traced is ignored and command lines are not echoed. cmd :: CmdArguments args => args :-> Action r -- | Collect the stdout of the process. If you are collecting the -- stdout, it will not be echoed to the terminal, unless you -- include EchoStdout. newtype Stdout Stdout :: String -> Stdout fromStdout :: Stdout -> String -- | Collect the stderr of the process. If you are collecting the -- stderr, it will not be echoed to the terminal, unless you -- include EchoStderr. newtype Stderr Stderr :: String -> Stderr fromStderr :: Stderr -> String -- | Collect the ExitCode of the process. If you do not collect the -- exit code, any ExitFailure will cause an exception. newtype Exit Exit :: ExitCode -> Exit fromExit :: Exit -> ExitCode -- | A class for specifying what results you want to collect from a -- process. Values are formed of Stdout, Stderr, -- Exit and tuples of those. class CmdResult a -- | Options passed to command or cmd to control how -- processes are executed. data CmdOption -- | Change the current directory in the spawned process. By default uses -- this processes current directory. Cwd :: FilePath -> CmdOption -- | Change the environment variables in the spawned process. By default -- uses this processes environment. Use addPath to modify the -- $PATH variable, or addEnv to modify other variables. Env :: [(String, String)] -> CmdOption -- | Given as the stdin of the spawned process. By default no -- stdin is given. Stdin :: String -> CmdOption -- | Pass the command to the shell without escaping - any arguments will be -- joined with spaces. By default arguments are escaped properly. Shell :: CmdOption -- | Treat the stdin/stdout/stderr messages as -- binary. By default streams use text encoding. BinaryPipes :: CmdOption -- | Name to use with traced, or "" for no tracing. By -- default traces using the name of the executable. Traced :: String -> CmdOption -- | Should I include the stderr in the exception if the command -- fails? Defaults to True. WithStderr :: Bool -> CmdOption -- | Should I echo the stdout? Defaults to True unless a -- Stdout result is required. EchoStdout :: Bool -> CmdOption -- | Should I echo the stderr? Defaults to True unless a -- Stderr result is required. EchoStderr :: Bool -> CmdOption -- | Produce a CmdOption of value Env that is the current -- environment, plus 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. addPath :: MonadIO m => [String] -> [String] -> m CmdOption -- | Produce a CmdOption of value Env that is the current -- environment, plus the argument environment variables. 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.
addEnv :: MonadIO m => [(String, String)] -> m CmdOption
-- | copyFile' old new copies the existing file from old
-- to new. The old file will be tracked as a
-- dependency.
copyFile' :: FilePath -> FilePath -> Action ()
-- | Read a file, after calling need. The argument file will be
-- tracked as a dependency.
readFile' :: FilePath -> Action String
-- | A version of readFile' which also splits the result into lines.
-- The argument file will be tracked as a dependency.
readFileLines :: FilePath -> Action [String]
-- | Write a file, lifted to the Action monad.
writeFile' :: FilePath -> String -> Action ()
-- | A version of writeFile' which writes out a list of lines.
writeFileLines :: FilePath -> [String] -> Action ()
-- | Write a file, but only if the contents would change.
writeFileChanged :: FilePath -> String -> Action ()
-- | Remove all files and directories that match any of the patterns within
-- a directory. Some examples:
--
-- -- removeFiles "output" ["//*"] -- removeFiles "." ["//*.hi","//*.o"] ---- -- Any directories that become empty after deleting items from within -- them will themselves be deleted, up to (and including) the containing -- directory. This function is often useful when writing a clean -- action for your build system, often as a phony rule. removeFiles :: FilePath -> [FilePattern] -> IO () -- | Remove files, like removeFiles, but executed after the build -- completes successfully. Useful for implementing clean actions -- that delete files Shake may have open for building. removeFilesAfter :: FilePath -> [FilePattern] -> 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. need :: [FilePath] -> Action () -- | 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. want :: [FilePath] -> Rules () -- | 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. (*>) :: FilePattern -> (FilePath -> Action ()) -> Rules () -- | 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 *>. (|*>) :: [FilePattern] -> (FilePath -> Action ()) -> Rules () -- | Define a rule to build files. If the first argument returns -- True for a given file, the second argument will be used to -- build it. Usually *> is sufficient, but ?> gives -- additional power. For any file used by the build system, only one rule -- should return True. 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 --(?>) :: (FilePath -> Bool) -> (FilePath -> Action ()) -> Rules () -- | Declare a phony action -- an action that does not produce a file, and -- will be rerun in every execution that requires it. You can demand -- phony rules using want / need. Phony actions are -- never executed more than once in a single build run. -- -- Phony actions are intended to define command-line abbreviations. 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. phony :: String -> Action () -> Rules () -- | Infix operator alias for phony, for sake of consistency with -- normal rules. (~>) :: String -> Action () -> Rules () -- | 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. Think of it as the OR (||) -- equivalent of *>. (&*>) :: [FilePattern] -> ([FilePath] -> Action ()) -> Rules () -- | 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 ---- -- As an example of a function satisfying the invariaint: -- --
-- test x | takeExtension x `elem` [".hi",".o"] -- = Just [dropExtension x <.> "hi", dropExtension x <.> "o"] -- test _ = Nothing ---- -- Regardless of whether Foo.hi or Foo.o is passed, the -- function always returns [Foo.hi, Foo.o]. (&?>) :: (FilePath -> Maybe [FilePath]) -> ([FilePath] -> Action ()) -> Rules () -- | Define 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, -- and you will have lost some opportunity for parallelism. orderOnly :: [FilePath] -> Action () -- | A type synonym for file patterns, containing // and -- *. For the syntax and semantics of FilePattern see -- ?==. type FilePattern = String -- | Match a FilePattern against a FilePath, There are only -- two special forms: -- --
-- "//*.c" ?== "foo/bar/baz.c" -- "*.c" ?== "baz.c" -- "//*.c" ?== "baz.c" -- "test.c" ?== "test.c" ---- -- Examples that don't match: -- --
-- "*.c" ?== "foo/bar.c" -- "*/*.c" ?== "foo/bar/baz.c" ---- -- An example that only matches on Windows: -- --
-- "foo/bar" ?== "foo\\bar" ---- -- Patterns with constructs such as foo/../bar will never match -- normalised FilePath values, so are unlikely to be correct. (?==) :: FilePattern -> FilePath -> Bool -- | 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. needed :: [FilePath] -> Action () -- | Track that a file was read by the action preceeding it. If -- shakeLint is activated then these files must be dependencies of -- this rule. Calls to trackRead are automatically inserted in -- LintTracker mode. trackRead :: [FilePath] -> Action () -- | Track that a file was written by the action preceeding 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 LintTracker -- mode. trackWrite :: [FilePath] -> Action () -- | Allow accessing a file in this rule, ignoring any -- 'trackRead'\/'trackWrite' calls matching the pattern. trackAllow :: [FilePattern] -> Action () -- | 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. -- -- You should not call doesFileExist on files which can be created -- by the build system. doesFileExist :: 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. doesDirectoryExist :: FilePath -> Action Bool -- | 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 is tracked as a dependency, and if it changes the -- rule will rerun in subsequent builds. -- -- It is usually simpler to call either getDirectoryFiles or -- getDirectoryDirs. getDirectoryContents :: FilePath -> 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 FilePath argument. The result -- is tracked as a dependency, and if it changes the rule will rerun in -- subsequent builds. 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 FilePath argument, for example the following two -- expressions are equivalent: -- --
-- fmap (map ("Config" </>)) (getDirectoryFiles "Config" ["//*.xml"])
-- getDirectoryFiles "" ["Config//*.xml"]
--
getDirectoryFiles :: FilePath -> [FilePattern] -> Action [FilePath]
-- | Get the directories in a directory, not including . or
-- ... All directories are relative to the argument directory.
-- The result is tracked as a dependency, and if it changes the rule will
-- rerun in subsequent builds.
--
-- -- getDirectoryDirs "/Users" -- -- Return all directories in the /Users directory -- -- e.g. ["Emily","Henry","Neil"] --getDirectoryDirs :: FilePath -> Action [FilePath] -- | 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. getEnv :: String -> Action (Maybe String) -- | Return the value of the environment variable, or the default value if -- it not set. Similar to getEnv. getEnvWithDefault :: String -> String -> Action String -- | 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) -- rules = do -- addOracle $ \(GhcVersion _) -> fmap fromStdout $ cmd "ghc --numeric-version" -- ... rules ... ---- -- If a rule calls askOracle (GhcVersion ()), that rule -- will be rerun whenever the GHC version changes. Some notes: -- --
-- newtype GhcPkgList = GhcPkgList () deriving (Show,Typeable,Eq,Hashable,Binary,NFData)
-- newtype GhcPkgVersion = GhcPkgVersion String deriving (Show,Typeable,Eq,Hashable,Binary,NFData)
--
-- rules = do
-- getPkgList <- addOracle $ \GhcPkgList{} -> do
-- Stdout out <- cmd "ghc-pkg list --simple-output"
-- return [(reverse b, reverse a) | x <- words out, let (a,_:b) = break (== '-') $ reverse x]
-- --
-- getPkgVersion <- addOracle $ \(GhcPkgVersion pkg) -> do
-- pkgs <- getPkgList $ GhcPkgList ()
-- return $ 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.
addOracle :: (ShakeValue q, ShakeValue a) => (q -> Action a) -> Rules (q -> Action a)
-- | Get information previously added with addOracle. The
-- question/answer types must match those provided to addOracle.
askOracle :: (ShakeValue q, ShakeValue a) => q -> Action a
-- | Get information previously added with addOracle. The second
-- argument is not used, but can be useful to fix the answer type,
-- avoiding ambiguous type error messages.
askOracleWith :: (ShakeValue q, ShakeValue a) => q -> a -> Action a
-- | 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 --alwaysRerun :: Action () -- | A type representing an external resource which the build system should -- respect. There are two ways to create Resources in Shake: -- --
-- 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] ... --newResource :: String -> Int -> Rules Resource -- | A version of newResource that runs in IO, and can be called -- before calling shake. Most people should use newResource -- instead. newResourceIO :: String -> Int -> IO Resource -- | 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. withResource :: 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. withResources :: [(Resource, Int)] -> Action a -> Action a -- | 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" ["http://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 $ return () -- cmd "wget" ["http://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. newThrottle :: String -> Int -> Double -> Rules Resource -- | A version of newThrottle that runs in IO, and can be called -- before calling shake. Most people should use newResource -- instead. newThrottleIO :: String -> Int -> Double -> IO Resource -- | 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. unsafeExtraThread :: Action a -> Action a -- | Given an action on a key, produce a cached version that will execute -- the action at most once per key. Using the cached result will still -- result include any dependencies that the action requires. Each call to -- newCache creates a separate cache that is independent of all -- other calls to newCache. -- -- 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 -- return $ 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. newCache :: (Eq k, Hashable k) => (k -> Action v) -> Rules (k -> Action v) -- | A version of newCache that runs in IO, and can be called before -- calling shake. Most people should use newCache instead. newCacheIO :: (Eq k, Hashable k) => (k -> Action v) -> IO (k -> Action v) -- | Deprecated: Alias for |*>. (**>) :: [FilePattern] -> (FilePath -> Action ()) -> Rules () -- | Deprecated: Alias for &*>. (*>>) :: [FilePattern] -> ([FilePath] -> Action ()) -> Rules () -- | Deprecated: Alias for &?>. (?>>) :: (FilePath -> Maybe [FilePath]) -> ([FilePath] -> Action ()) -> Rules () -- | Deprecated: Please use command or cmd -- instead. This function will be removed in a future version. -- -- Execute a system command. This function will raise an error if the -- exit code is non-zero. Before running system' make sure you -- need any required files. -- | Deprecated: Use command or cmd system' :: FilePath -> [String] -> Action () -- | Deprecated: Please use command or cmd -- instead, with Cwd. This function will be removed in a future -- version. -- -- Execute a system command with a specified current working directory -- (first argument). This function will raise an error if the exit code -- is non-zero. Before running systemCwd make sure you need -- any required files. -- --
-- systemCwd "/usr/MyDirectory" "pwd" [] ---- | Deprecated: Use command or cmd with Cwd -- systemCwd :: FilePath -> FilePath -> [String] -> Action () -- | Deprecated: Please use command or cmd -- instead, with Stdout or Stderr. This function will -- be removed in a future version. -- -- Execute a system command, returning (stdout,stderr). This -- function will raise an error if the exit code is non-zero. Before -- running systemOutput make sure you need any required -- files. -- | Deprecated: Use command or cmd with -- Stdout or Stderr systemOutput :: FilePath -> [String] -> Action (String, String) -- | A module for parsing and using config files in a Shake build system. -- Config files consist of variable bindings, for example: -- --
-- # This is my Config file
-- HEADERS_DIR = /path/to/dir
-- CFLAGS = -g -I${HEADERS_DIR}
-- CFLAGS = $CFLAGS -O2
-- include extra/file.cfg
--
--
-- This defines the variable HEADERS_DIR (equal to
-- /path/to/dir), and CFLAGS (equal to -g
-- -I/path/to/dir -O2), and also includes the configuration
-- statements in the file extra/file.cfg. The full lexical
-- syntax for configuration files is defined here:
-- http://martine.github.io/ninja/manual.html#_lexical_syntax.
--
-- To use the configuration file either use readConfigFile to
-- parse the configuration file and use the values directly, or
-- usingConfigFile and getConfig to track the configuration
-- values, so they become build dependencies.
module Development.Shake.Config
-- | Read a config file, returning a list of the variables and their
-- bindings. Config files use the Ninja lexical syntax:
-- http://martine.github.io/ninja/manual.html#_lexical_syntax
readConfigFile :: FilePath -> IO (HashMap String String)
-- | Specify the file to use with getConfig.
usingConfigFile :: FilePath -> Rules ()
-- | Specify the values to use with getConfig, generally prefer
-- usingConfigFile unless you also need access to the values of
-- variables outside Action.
usingConfig :: HashMap String String -> Rules ()
-- | Obtain the value of a configuration variable, returns Nothing
-- to indicate the variable has no binding. Any build system using
-- getConfig must call either usingConfigFile or
-- usingConfig. The getConfig function will introduce a
-- dependency on the configuration variable (but not the whole
-- configuration file), and if the configuration variable changes, the
-- rule will be rerun. As an example:
--
-- -- usingConfigFile "myconfiguration.cfg" -- "*.o" *> \out -> do -- cflags <- getConfig "CFLAGS" -- cmd "gcc" [out -<.> "c"] (fromMaybe "" cflags) --getConfig :: String -> Action (Maybe String) instance Typeable Config instance Show Config instance Eq Config instance Hashable Config instance Binary Config instance NFData Config -- | A module for useful utility functions for Shake build systems. module Development.Shake.Util -- | Given the text of a Makefile, extract the list of targets and -- dependencies. Assumes a small subset of Makefile syntax, mostly that -- generated by gcc -MM. -- --
-- parseMakefile "a: b c\nd : e" == [("a",["b","c"]),("d",["e"])]
--
parseMakefile :: String -> [(FilePath, [FilePath])]
-- | Depend on the dependencies listed in a Makefile. Does not depend on
-- the Makefile itself.
--
-- -- needMakefileDependencies file = need . concatMap snd . parseMakefile =<< liftIO (readFile file) --needMakefileDependencies :: FilePath -> Action () -- | Depend on the dependencies listed in a Makefile. Does not depend on -- the Makefile itself. Use this function to indicate that you have -- already used the files in question. -- --
-- neededMakefileDependencies file = needed . concatMap snd . parseMakefile =<< liftIO (readFile file) --neededMakefileDependencies :: FilePath -> Action () -- | Like shakeArgsWith, but instead of accumulating a list of -- flags, apply functions to a default value. Usually used to populate a -- record structure. As an example of a build system that can use either -- gcc or distcc for compiling: -- --
-- import System.Console.GetOpt
--
-- data Flags = Flags {distCC :: Bool} deriving Eq
-- flags = [Option "" ["distcc"] (NoArg $ Right $ \x -> x{distCC=True}) "Run distributed."]
--
-- main = shakeArgsAccumulate shakeOptions flags (Flags False) $ \flags targets -> return $ Just $ do
-- if null targets then want ["result.exe"] else want targets
-- let compiler = if distCC flags then "distcc" else "gcc"
-- "*.o" *> \out -> do
-- need ...
-- cmd compiler ...
-- ...
--
--
-- Now you can pass --distcc to use the distcc
-- compiler.
shakeArgsAccumulate :: ShakeOptions -> [OptDescr (Either String (a -> a))] -> a -> (a -> [String] -> IO (Maybe (Rules ()))) -> IO ()