module Development.Shake.Util(
parseMakefile, needMakefileDependencies, neededMakefileDependencies,
shakeArgsAccumulate, shakeArgsPrune, shakeArgsPruneWith,
) where
import Development.Shake
import Development.Shake.Internal.Rules.File
import qualified Data.ByteString.Char8 as BS
import qualified General.Makefile as BS
import Data.Tuple.Extra
import Control.Applicative
import Data.List
import General.GetOpt
import Data.IORef
import Data.Maybe
import Control.Monad.Extra
import Prelude
import System.IO.Extra as IO
parseMakefile :: String -> [(FilePath, [FilePath])]
parseMakefile :: String -> [(String, [String])]
parseMakefile = ((ByteString, [ByteString]) -> (String, [String]))
-> [(ByteString, [ByteString])] -> [(String, [String])]
forall a b. (a -> b) -> [a] -> [b]
map (ByteString -> String
BS.unpack (ByteString -> String)
-> ([ByteString] -> [String])
-> (ByteString, [ByteString])
-> (String, [String])
forall a a' b b'. (a -> a') -> (b -> b') -> (a, b) -> (a', b')
*** (ByteString -> String) -> [ByteString] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map ByteString -> String
BS.unpack) ([(ByteString, [ByteString])] -> [(String, [String])])
-> (String -> [(ByteString, [ByteString])])
-> String
-> [(String, [String])]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> [(ByteString, [ByteString])]
BS.parseMakefile (ByteString -> [(ByteString, [ByteString])])
-> (String -> ByteString) -> String -> [(ByteString, [ByteString])]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> ByteString
BS.pack
needMakefileDependencies :: FilePath -> Action ()
needMakefileDependencies :: String -> Action ()
needMakefileDependencies file :: String
file = [ByteString] -> Action ()
needBS ([ByteString] -> Action ())
-> (ByteString -> [ByteString]) -> ByteString -> Action ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((ByteString, [ByteString]) -> [ByteString])
-> [(ByteString, [ByteString])] -> [ByteString]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (ByteString, [ByteString]) -> [ByteString]
forall a b. (a, b) -> b
snd ([(ByteString, [ByteString])] -> [ByteString])
-> (ByteString -> [(ByteString, [ByteString])])
-> ByteString
-> [ByteString]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> [(ByteString, [ByteString])]
BS.parseMakefile (ByteString -> Action ()) -> Action ByteString -> Action ()
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< IO ByteString -> Action ByteString
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (String -> IO ByteString
BS.readFile String
file)
neededMakefileDependencies :: FilePath -> Action ()
neededMakefileDependencies :: String -> Action ()
neededMakefileDependencies file :: String
file = [ByteString] -> Action ()
neededBS ([ByteString] -> Action ())
-> (ByteString -> [ByteString]) -> ByteString -> Action ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((ByteString, [ByteString]) -> [ByteString])
-> [(ByteString, [ByteString])] -> [ByteString]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (ByteString, [ByteString]) -> [ByteString]
forall a b. (a, b) -> b
snd ([(ByteString, [ByteString])] -> [ByteString])
-> (ByteString -> [(ByteString, [ByteString])])
-> ByteString
-> [ByteString]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ByteString -> [(ByteString, [ByteString])]
BS.parseMakefile (ByteString -> Action ()) -> Action ByteString -> Action ()
forall (m :: * -> *) a b. Monad m => (a -> m b) -> m a -> m b
=<< IO ByteString -> Action ByteString
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (String -> IO ByteString
BS.readFile String
file)
shakeArgsAccumulate :: ShakeOptions -> [OptDescr (Either String (a -> a))] -> a -> (a -> [String] -> IO (Maybe (Rules ()))) -> IO ()
shakeArgsAccumulate :: ShakeOptions
-> [OptDescr (Either String (a -> a))]
-> a
-> (a -> [String] -> IO (Maybe (Rules ())))
-> IO ()
shakeArgsAccumulate opts :: ShakeOptions
opts flags :: [OptDescr (Either String (a -> a))]
flags def :: a
def f :: a -> [String] -> IO (Maybe (Rules ()))
f = ShakeOptions
-> [OptDescr (Either String (a -> a))]
-> ([a -> a] -> [String] -> IO (Maybe (Rules ())))
-> IO ()
forall a.
ShakeOptions
-> [OptDescr (Either String a)]
-> ([a] -> [String] -> IO (Maybe (Rules ())))
-> IO ()
shakeArgsWith ShakeOptions
opts [OptDescr (Either String (a -> a))]
flags (([a -> a] -> [String] -> IO (Maybe (Rules ()))) -> IO ())
-> ([a -> a] -> [String] -> IO (Maybe (Rules ()))) -> IO ()
forall a b. (a -> b) -> a -> b
$ \flags :: [a -> a]
flags targets :: [String]
targets -> a -> [String] -> IO (Maybe (Rules ()))
f ((a -> (a -> a) -> a) -> a -> [a -> a] -> a
forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl' (((a -> a) -> a -> a) -> a -> (a -> a) -> a
forall a b c. (a -> b -> c) -> b -> a -> c
flip (a -> a) -> a -> a
forall a b. (a -> b) -> a -> b
($)) a
def [a -> a]
flags) [String]
targets
shakeArgsPrune :: ShakeOptions -> ([FilePath] -> IO ()) -> Rules () -> IO ()
shakeArgsPrune :: ShakeOptions -> ([String] -> IO ()) -> Rules () -> IO ()
shakeArgsPrune opts :: ShakeOptions
opts prune :: [String] -> IO ()
prune rules :: Rules ()
rules = ShakeOptions
-> ([String] -> IO ())
-> [OptDescr (Either String Any)]
-> ([Any] -> [String] -> IO (Maybe (Rules ())))
-> IO ()
forall a.
ShakeOptions
-> ([String] -> IO ())
-> [OptDescr (Either String a)]
-> ([a] -> [String] -> IO (Maybe (Rules ())))
-> IO ()
shakeArgsPruneWith ShakeOptions
opts [String] -> IO ()
prune [] [Any] -> [String] -> IO (Maybe (Rules ()))
forall (m :: * -> *) p.
Monad m =>
p -> [String] -> m (Maybe (Rules ()))
f
where f :: p -> [String] -> m (Maybe (Rules ()))
f _ files :: [String]
files = Maybe (Rules ()) -> m (Maybe (Rules ()))
forall (m :: * -> *) a. Monad m => a -> m a
return (Maybe (Rules ()) -> m (Maybe (Rules ())))
-> Maybe (Rules ()) -> m (Maybe (Rules ()))
forall a b. (a -> b) -> a -> b
$ Rules () -> Maybe (Rules ())
forall a. a -> Maybe a
Just (Rules () -> Maybe (Rules ())) -> Rules () -> Maybe (Rules ())
forall a b. (a -> b) -> a -> b
$ if [String] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null [String]
files then Rules ()
rules else [String] -> Rules ()
want [String]
files Rules () -> Rules () -> Rules ()
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> Rules () -> Rules ()
withoutActions Rules ()
rules
shakeArgsPruneWith :: ShakeOptions -> ([FilePath] -> IO ()) -> [OptDescr (Either String a)] -> ([a] -> [String] -> IO (Maybe (Rules ()))) -> IO ()
shakeArgsPruneWith :: ShakeOptions
-> ([String] -> IO ())
-> [OptDescr (Either String a)]
-> ([a] -> [String] -> IO (Maybe (Rules ())))
-> IO ()
shakeArgsPruneWith opts :: ShakeOptions
opts prune :: [String] -> IO ()
prune flags :: [OptDescr (Either String a)]
flags act :: [a] -> [String] -> IO (Maybe (Rules ()))
act = do
let flags2 :: [OptDescr (Either String (Maybe a))]
flags2 = String
-> [String]
-> ArgDescr (Either String (Maybe a))
-> String
-> OptDescr (Either String (Maybe a))
forall a. String -> [String] -> ArgDescr a -> String -> OptDescr a
Option "P" ["prune"] (Either String (Maybe a) -> ArgDescr (Either String (Maybe a))
forall a. a -> ArgDescr a
NoArg (Either String (Maybe a) -> ArgDescr (Either String (Maybe a)))
-> Either String (Maybe a) -> ArgDescr (Either String (Maybe a))
forall a b. (a -> b) -> a -> b
$ Maybe a -> Either String (Maybe a)
forall a b. b -> Either a b
Right Maybe a
forall a. Maybe a
Nothing) "Remove stale files" OptDescr (Either String (Maybe a))
-> [OptDescr (Either String (Maybe a))]
-> [OptDescr (Either String (Maybe a))]
forall a. a -> [a] -> [a]
: (OptDescr (Either String a) -> OptDescr (Either String (Maybe a)))
-> [OptDescr (Either String a)]
-> [OptDescr (Either String (Maybe a))]
forall a b. (a -> b) -> [a] -> [b]
map ((a -> Maybe a)
-> OptDescr (Either String a) -> OptDescr (Either String (Maybe a))
forall a b.
(a -> b)
-> OptDescr (Either String a) -> OptDescr (Either String b)
fmapOptDescr a -> Maybe a
forall a. a -> Maybe a
Just) [OptDescr (Either String a)]
flags
IORef Bool
pruning <- Bool -> IO (IORef Bool)
forall a. a -> IO (IORef a)
newIORef Bool
False
ShakeOptions
-> [OptDescr (Either String (Maybe a))]
-> ([Maybe a] -> [String] -> IO (Maybe (Rules ())))
-> IO ()
forall a.
ShakeOptions
-> [OptDescr (Either String a)]
-> ([a] -> [String] -> IO (Maybe (Rules ())))
-> IO ()
shakeArgsWith ShakeOptions
opts [OptDescr (Either String (Maybe a))]
flags2 (([Maybe a] -> [String] -> IO (Maybe (Rules ()))) -> IO ())
-> ([Maybe a] -> [String] -> IO (Maybe (Rules ()))) -> IO ()
forall a b. (a -> b) -> a -> b
$ \opts :: [Maybe a]
opts args :: [String]
args ->
case [Maybe a] -> Maybe [a]
forall (t :: * -> *) (m :: * -> *) a.
(Traversable t, Monad m) =>
t (m a) -> m (t a)
sequence [Maybe a]
opts of
Nothing -> do
IORef Bool -> Bool -> IO ()
forall a. IORef a -> a -> IO ()
writeIORef IORef Bool
pruning Bool
True
Maybe (Rules ()) -> IO (Maybe (Rules ()))
forall (m :: * -> *) a. Monad m => a -> m a
return Maybe (Rules ())
forall a. Maybe a
Nothing
Just opts :: [a]
opts -> [a] -> [String] -> IO (Maybe (Rules ()))
act [a]
opts [String]
args
IO Bool -> IO () -> IO ()
forall (m :: * -> *). Monad m => m Bool -> m () -> m ()
whenM (IORef Bool -> IO Bool
forall a. IORef a -> IO a
readIORef IORef Bool
pruning) (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$
(String -> IO ()) -> IO ()
forall a. (String -> IO a) -> IO a
IO.withTempFile ((String -> IO ()) -> IO ()) -> (String -> IO ()) -> IO ()
forall a b. (a -> b) -> a -> b
$ \file :: String
file -> do
ShakeOptions
-> [OptDescr (Either String (Maybe a))]
-> ([Maybe a] -> [String] -> IO (Maybe (Rules ())))
-> IO ()
forall a.
ShakeOptions
-> [OptDescr (Either String a)]
-> ([a] -> [String] -> IO (Maybe (Rules ())))
-> IO ()
shakeArgsWith ShakeOptions
opts{shakeLiveFiles :: [String]
shakeLiveFiles=String
file String -> [String] -> [String]
forall a. a -> [a] -> [a]
: ShakeOptions -> [String]
shakeLiveFiles ShakeOptions
opts} [OptDescr (Either String (Maybe a))]
flags2 (([Maybe a] -> [String] -> IO (Maybe (Rules ()))) -> IO ())
-> ([Maybe a] -> [String] -> IO (Maybe (Rules ()))) -> IO ()
forall a b. (a -> b) -> a -> b
$ \opts :: [Maybe a]
opts args :: [String]
args ->
[a] -> [String] -> IO (Maybe (Rules ()))
act ([Maybe a] -> [a]
forall a. [Maybe a] -> [a]
catMaybes [Maybe a]
opts) [String]
args
[String]
src <- String -> [String]
lines (String -> [String]) -> IO String -> IO [String]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> String -> IO String
IO.readFile' String
file
[String] -> IO ()
prune [String]
src