packages feed

shaker-0.1: src/Shaker/Action/Compile.hs

module Shaker.Action.Compile(
    runCompile
    ,runFullCompile
  )
 where

import Data.List 
import GHC
import DynFlags 
import GHC.Paths
import Shaker.Io
import Shaker.Type
import Control.Monad.Trans 
import Control.Monad.Reader

-- |Run haskell compilation on given file input 
runCompile :: Plugin
runCompile = asks compileInputs >>=  mapM runSingleCompileInput >> return ()

runSingleCompileInput :: CompileInput -> Shaker IO()
runSingleCompileInput (CompileInput sourceDir desc targetInput procFlags strflags inputTargetFiles) = do
        lift $ putStrLn "-------------------------------------"
        lift $ putStrLn $ concat ["   --------- ", desc," ---------"]
        targetFiles <- checkTargetFiles inputTargetFiles 
        lift $ putStrLn $ concat ["   --------- ", "Compiling target : "++ show targetFiles," ---------"]
        lift $ defaultErrorHandler defaultDynFlags $ 
                       runGhc (Just libdir) $ do
                       dflags <- getSessionDynFlags
                       (newFlags,_,_) <- parseDynamicFlags dflags (map noLoc strflags)
	               _ <- setSessionDynFlags $ procFlags $ setSourceAndTarget sourceDir targetInput newFlags
                       target <- mapM (`guessTarget` Nothing) targetFiles
                       setTargets target
        	       _ <- load LoadAllTargets
                       return ()
 
runFullCompile :: Plugin
runFullCompile = setCompileInputForAllHsSources >>= \a -> 
  runSingleCompileInput a >> 
  return () 

-- | Fill the target files to all files in listenerInput if empty
checkTargetFiles :: [String] -> Shaker IO([String])
checkTargetFiles [] = do 
        (ListenerInput fli _) <- asks listenerInput 
        files <- lift $ recurseMultipleListFiles fli
        lift $ filterM (\a -> not `liftM` isFileContainingMain a) files
checkTargetFiles l = return l

setSourceAndTarget :: [String] -> String ->DynFlags -> DynFlags
setSourceAndTarget sources target dflags = dflags{
    importPaths = sources
    ,objectDir = Just target
    ,hiDir = Just target
  }

setCompileInputForAllHsSources :: Shaker IO CompileInput
setCompileInputForAllHsSources = do 
  (cpIn:_) <- asks compileInputs
  filePaths <- lift $ recurseMultipleListFiles $ map (\a -> FileListenInfo a defaultExclude defaultHaskellPatterns ) (cfSourceDirs cpIn)
  toExcludeFiles <- lift $ filterM isFileContainingMain filePaths
  return  $ cpIn {cfTargetFiles = filePaths \\ toExcludeFiles , cfDescription ="Full compilation"  }