{- hake: make tool. ruby : rake = haskell : hake Copyright (C) 2008-2008 Yoshikuni Jujo This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . -} module Development.Hake.HiddenTools ( runHake , isOldThanSomeOf , hakefileUpdateOption , defaultTrgtStr ) where import System.Directory (createDirectory, doesDirectoryExist, doesFileExist, copyFile, getModificationTime) import System.Process (runProcess, waitForProcess) import System.Exit (ExitCode(ExitSuccess)) import System.Time (ClockTime) import System.IO (openFile, hClose, IOMode(WriteMode)) import Control.Applicative ((<$>), liftA2) import Control.Monad (when) import Control.Monad.Utils (unlessM) import Control.Exception (bracket) maybeGetModificationTime :: FilePath -> IO (Maybe ClockTime) maybeGetModificationTime fn = do ex <- doesFileExist fn if ex then Just <$> getModificationTime fn else return Nothing isOldThanSomeOf :: FilePath -> [FilePath] -> IO Bool isOldThanSomeOf dfn sfns = liftA2 ((myOr .) . map . (<)) (maybeGetModificationTime dfn) (mapM maybeGetModificationTime sfns) where -- for task like "clean" myOr [] = True myOr bs = or bs hakefileUpdateOption :: String hakefileUpdateOption = "--hakefile-is-updated" runHake :: FilePath -> FilePath -> [ FilePath ] -> [ String ] -> IO ExitCode runHake src exe othrs args = do unlessM (doesDirectoryExist "_hake") $ createDirectory "_hake" othrsUD <- fmap or $ flip mapM othrs $ \fn -> do let dist = "_hake/" ++ basename fn updated <- isOldThanSomeOf dist [ fn ] when updated $ copyFile fn dist return updated hakefileUD <- isOldThanSomeOf ("_hake/" ++ exe ++ ".hs") [ src ] when hakefileUD $ readFile src >>= writeFile ("_hake/" ++ exe ++ ".hs") #ifndef DEBUG ret <- bracket (flip openFile WriteMode $ "_hake/" ++ exe ++ ".error") hClose $ \errH -> let mErrH = Just errH in #else let mErrH = Nothing in #endif /* DEBUG */ runProcess "ghc" [ "--make", exe ] (Just "_hake") Nothing Nothing Nothing mErrH >>= waitForProcess let args_ = if othrsUD || hakefileUD then (hakefileUpdateOption:args) else args case ret of ExitSuccess -> return () _ -> readFile ("_hake/" ++ exe ++ ".error") >>= putStr runProcess ("_hake/" ++ exe) (if null args then ("default":args_) else args_) Nothing Nothing Nothing Nothing Nothing >>= waitForProcess basename :: FilePath -> FilePath basename = reverse . takeWhile (/='/') . reverse defaultTrgtStr :: String defaultTrgtStr = "default"