packages feed

ddc-war-0.4.1.1: DDC/War/Job/CompileDS.hs

module DDC.War.Job.CompileDS
	( Spec         (..)
        , Result       (..)
        , resultSuccess
        , build)
where
import BuildBox.Command.File
import BuildBox.Command.System
import BuildBox.Build.Benchmark
import BuildBox.Data.Physical
import BuildBox.IO.Directory
import BuildBox.Pretty
import BuildBox
import System.FilePath
import Control.Monad
import Data.List


-- | Use DDC to compile a source file.
data Spec
        = Spec
        { -- | Root source file of the program (the 'Main.ds')
          specFile               :: FilePath 
                
          -- | Extra DDC options for building in this way.
        , specOptionsDDC         :: [String] 
                
          -- | Extra GHC RTS options for building in this way.
        , specOptionsRTS         :: [String]
                
          -- | Scratch dir to do the build in.
        , specScratchDir         :: String

          -- | Put what DDC says to stdout here.
        , specCompileStdout      :: FilePath
                
          -- | Put what DDC says to stderr here.
        , specCompileStderr      :: FilePath 

          -- | If Just, then we're making an executable, and put the binary here.
          --   Otherwise simply compile it
        , specMaybeMainBin       :: Maybe FilePath 
                
          -- | True if the compile is expected to succeed, else not.
        , specShouldSucceed      :: Bool }
        deriving Show


data Result
        = ResultSuccess Seconds
        | ResultUnexpectedSuccess
        | ResultUnexpectedFailure
        deriving Show

resultSuccess :: Result -> Bool
resultSuccess result
 = case result of
        ResultSuccess{} -> True
        _               -> False


instance Pretty Result where
 ppr result 
  = case result of
        ResultSuccess seconds    -> text "success" <+> parens (ppr seconds)
        ResultUnexpectedFailure  -> text "failed"
        ResultUnexpectedSuccess  -> text "unexpected"


-- | Compile a Disciple source file.
build :: Spec -> Build Result
build (Spec     srcDS optionsDDC optionsRTS
		buildDir mainCompOut mainCompErr
		mMainBin shouldSucceed)

 = do	let ddcaExe = "bin/ddc-alpha" <.> exe

        needs srcDS
        needs ddcaExe
	
	-- The directory holding the Main.ds file.
	let (srcDir, _srcFile)	= splitFileName srcDS
		
	-- Touch the .ds files to the build directory to ensure they're built.
	sources	<- io
		$  liftM (filter (\f -> isSuffixOf ".ds" f || isSuffixOf ".build" f))
		$  lsFilesIn srcDir

	ssystemq $ "touch " ++ (intercalate " " sources)

	-- ensure the output directory exists
	ensureDir buildDir

	-- Do the compile.
	let compile
		| Just mainBin	<- mMainBin
		= do	
			-- If there is an existing binary then remove it.
			ssystemq $ "rm -f " ++ mainBin

			-- Build the program.
	 		timeBuild 
	 		 $ systemTee False 
				(ddcaExe
				++ " -v -make "	  ++ srcDS
				++ " -o "	  ++ mainBin
				++ " -outputdir " ++ buildDir
				++ " " 		  ++ intercalate " " optionsDDC
				++ " +RTS "	  ++ intercalate " " optionsRTS)
				""


		-- Compile the program.
		| otherwise
		= do	timeBuild
	 		 $ systemTee False
				(ddcaExe
				++ " -c "	  ++ srcDS
				++ " -outputdir " ++ buildDir
				++ " " 		  ++ intercalate " " optionsDDC
				++ " +RTS "	  ++ intercalate " " optionsRTS)
				""

	(time, (code, strOut, strErr))
		<- compile
	
        atomicWriteFile mainCompOut strOut
        atomicWriteFile mainCompErr strErr

        case code of
         ExitFailure _
          | shouldSucceed       -> return ResultUnexpectedFailure
        
         ExitSuccess
          | not shouldSucceed   -> return ResultUnexpectedSuccess

         _                      -> return $ ResultSuccess time