hake-0.4: Development/Hake/HiddenTools.cpphs
{- hake: make tool. ruby : rake = haskell : hake
Copyright (C) 2008-2008 Yoshikuni Jujo <PAF01143@nifty.ne.jp>
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 <http://www.gnu.org/licenses/>.
-}
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"