module Cli.RunCompiler (
runCompiler,
) where
import Control.Monad (foldM,when)
import Data.List (intercalate)
import System.Directory
import System.Exit
import System.FilePath
import System.Posix.Temp (mkdtemp)
import System.IO
import qualified Data.Set as Set
import Base.CompileError
import Base.Mergeable
import Cli.CompileMetadata
import Cli.CompileOptions
import Cli.Compiler
import Cli.ProcessMetadata
import Compilation.CompileInfo
import Config.LoadConfig
import Config.Paths
import Config.Programs
runCompiler :: CompileOptions -> IO ()
runCompiler (CompileOptions _ _ _ ds _ _ p (ExecuteTests tp) f) = do
(backend,resolver) <- loadConfig
base <- resolveBaseModule resolver
ts <- sequence $ map (preloadTests backend base) ds
checkTestFilters ts
allResults <- fmap concat $ sequence $ map (runModuleTests backend base tp) ts
let passed = sum $ map (fst . fst) allResults
let failed = sum $ map (snd . fst) allResults
processResults passed failed (mergeAllM $ map snd allResults) where
preloadTests b base d = do
m <- loadMetadata (p </> d)
(fr0,deps0) <- loadPublicDeps (getCompilerHash b) [base]
checkAllowedStale fr0 f
(fr1,deps1) <- loadTestingDeps (getCompilerHash b) m
checkAllowedStale fr1 f
(fr2,deps2) <- loadPrivateDeps (getCompilerHash b) (deps0++[m]++deps1)
checkAllowedStale fr2 f
return $ LoadedTests p d m (deps0++[m]++deps1) deps2
checkTestFilters ts = do
let possibleTests = Set.fromList $ concat $ map (cmTestFiles . ltMetadata) ts
case Set.toList $ (Set.fromList tp) `Set.difference` possibleTests of
[] -> return ()
fs -> do
hPutStr stderr $ "Some test files do not occur in the selected modules: " ++
intercalate ", " (map show fs) ++ "\n"
exitFailure
processResults passed failed rs
| isCompileError rs = do
hPutStr stderr $ "\nTest errors:\n" ++ (show $ getCompileError rs)
hPutStrLn stderr $ "\nPassed: " ++ show passed ++ " test(s), Failed: " ++ show failed ++ " test(s)"
hPutStrLn stderr $ "Zeolite tests failed."
exitFailure
| otherwise = do
hPutStrLn stderr $ "\nPassed: " ++ show passed ++ " test(s), Failed: " ++ show failed ++ " test(s)"
hPutStrLn stderr $ "Zeolite tests passed."
runCompiler (CompileOptions _ is is2 _ _ _ p (CompileFast c fn f2) f) = do
dir <- mkdtemp "/tmp/zfast_"
absolute <- canonicalizePath p
f2' <- canonicalizePath (p </> f2)
let spec = ModuleSpec {
msRoot = absolute,
msPath = dir,
msPublicDeps = is,
msPrivateDeps = is2,
msPublicFiles = [],
msPrivateFiles = [f2'],
msTestFiles = [],
msExtraFiles = [],
msExtraPaths = [],
msMode = (CompileBinary c fn (absolute </> show c) []),
msForce = f
}
compileModule spec
removeDirectoryRecursive dir
runCompiler (CompileOptions h _ _ ds _ _ p CompileRecompileRecursive f) = do
foldM recursive Set.empty ds >> return () where
recursive da d0 = do
d <- canonicalizePath (p </> d0)
rm <- tryLoadRecompile d
case rm of
Nothing -> do
hPutStrLn stderr $ "Path " ++ d ++ " does not have a valid configuration."
exitFailure
Just m ->
if rmPath m `Set.member` da
then return da
else do
let ds3 = map (\d2 -> d </> d2) (rmPublicDeps m ++ rmPrivateDeps m)
da' <- foldM recursive (rmPath m `Set.insert` da) ds3
runCompiler (CompileOptions h [] [] [d] [] [] p CompileRecompile f)
return da'
runCompiler (CompileOptions _ _ _ ds _ _ p CompileRecompile f) = do
(backend,_) <- loadConfig
fmap mergeAll $ sequence $ map (recompileSingle $ getCompilerHash backend) ds where
recompileSingle h2 d0 = do
let d = p </> d0
rm <- tryLoadRecompile d
upToDate <- isPathUpToDate h2 d
maybeCompile rm upToDate where
maybeCompile Nothing _ = do
hPutStrLn stderr $ "Path " ++ d0 ++ " does not have a valid configuration."
exitFailure
maybeCompile (Just rm') upToDate
| f < ForceAll && upToDate = hPutStrLn stderr $ "Path " ++ d0 ++ " is up to date."
| otherwise = do
let (ModuleConfig p2 d is is2 es ep m) = rm'
absolute <- canonicalizePath (p </> d0)
let fixed = fixPath (absolute </> p2)
(ps,xs,ts) <- findSourceFiles fixed d
let spec = ModuleSpec {
msRoot = fixed,
msPath = d,
msPublicDeps = is,
msPrivateDeps = is2,
msPublicFiles = ps,
msPrivateFiles = xs,
msTestFiles = ts,
msExtraFiles = es,
msExtraPaths = ep,
msMode = m,
msForce = f
}
compileModule spec
runCompiler (CompileOptions _ is is2 ds _ _ p CreateTemplates f) = mapM_ compileSingle ds where
compileSingle d = do
(backend,resolver) <- loadConfig
base <- resolveBaseModule resolver
as <- fmap fixPaths $ sequence $ map (resolveModule resolver (p </> d)) is
as2 <- fmap fixPaths $ sequence $ map (resolveModule resolver (p </> d)) is2
(fr1,deps1) <- loadPublicDeps (getCompilerHash backend) (base:as)
checkAllowedStale fr1 f
(fr2,deps2) <- loadPublicDeps (getCompilerHash backend) as2
checkAllowedStale fr2 f
path <- canonicalizePath p
createModuleTemplates path d deps1 deps2
runCompiler (CompileOptions h is is2 ds es ep p m f) = mapM_ compileSingle ds where
compileSingle d = do
(_,resolver) <- loadConfig
as <- fmap fixPaths $ sequence $ map (resolveModule resolver (p </> d)) is
as2 <- fmap fixPaths $ sequence $ map (resolveModule resolver (p </> d)) is2
isConfigured <- isPathConfigured d
when (isConfigured && f == DoNotForce) $ do
hPutStrLn stderr $ "Module " ++ d ++ " has an existing configuration. " ++
"Recompile with -r or use -f to overwrite the config."
exitFailure
absolute <- canonicalizePath p
let rm = ModuleConfig {
rmRoot = absolute,
rmPath = d,
rmPublicDeps = as,
rmPrivateDeps = as2,
rmExtraFiles = es,
rmExtraPaths = ep,
rmMode = m
}
writeRecompile (p </> d) rm
runCompiler (CompileOptions h [] [] [d] [] [] p CompileRecompile DoNotForce)