module Stackage.Build ( build , defaultBuildSettings , BuildSettings (..) ) where import Control.Monad (unless) import Prelude hiding (pi) import Stackage.CheckCabalVersion (checkCabalVersion) import Stackage.Config import Stackage.InstallInfo import Stackage.ModuleNameConflict import Stackage.Types import Stackage.Util import System.Exit (ExitCode (ExitSuccess), exitWith) import System.IO (BufferMode (NoBuffering), IOMode (WriteMode), hPutStrLn, hSetBuffering, withBinaryFile) import qualified System.IO.UTF8 import System.Process (rawSystem, runProcess, waitForProcess) import qualified Data.ByteString.Lazy.Char8 as L8 defaultBuildSettings :: Maybe Int -- ^ argument to -j -> GhcMajorVersion -> BuildSettings defaultBuildSettings cores version = BuildSettings { sandboxRoot = "sandbox" , expectedFailuresBuild = defaultExpectedFailures version , extraArgs = \bs -> "-fnetwork23" : case bs of BSTest -> [] _ -> case cores of Nothing -> ["-j"] Just 1 -> [] Just j -> ["-j" ++ show j] , testWorkerThreads = 4 , buildDocs = True , tarballDir = "patching/tarballs" , cabalFileDir = Nothing } build :: BuildSettings -> BuildPlan -> IO () build settings' bp = do libVersion <- checkCabalVersion putStrLn "Wiping out old sandbox folder" rm_r $ sandboxRoot settings' rm_r "logs" settings <- fixBuildSettings settings' putStrLn "Creating new package database" ec1 <- rawSystem "ghc-pkg" ["init", packageDir settings] unless (ec1 == ExitSuccess) $ do putStrLn "Unable to create package database via ghc-pkg init" exitWith ec1 menv <- fmap Just $ getModifiedEnv settings let runCabal args handle = runProcess "cabal" args Nothing menv Nothing (Just handle) (Just handle) -- First install build tools so they can be used below. let installBuildTool tool = do let toolsDir = packageDir settings ++ "-tools" rm_r toolsDir ecInit <- rawSystem "ghc-pkg" ["init", toolsDir] unless (ecInit == ExitSuccess) $ do putStrLn "Unable to create package database via ghc-pkg init" exitWith ecInit putStrLn $ "Installing build tool: " ++ tool ec <- withBinaryFile "build-tools.log" WriteMode $ \handle -> do hSetBuffering handle NoBuffering let args = addCabalArgs settings BSTools $ "install" : ("--cabal-lib-version=" ++ libVersion) : "--build-log=logs-tools/$pkg.log" : [tool] hPutStrLn handle ("cabal " ++ unwords (map (\s -> "'" ++ s ++ "'") args)) ph <- runCabal args handle waitForProcess ph unless (ec == ExitSuccess) $ do putStrLn $ concat [ "Building of " , tool , " failed, please see build-tools.log" ] exitWith ec putStrLn $ tool ++ " built" rm_r toolsDir mapM_ installBuildTool $ bpTools bp putStrLn "Beginning Stackage build" ph <- withBinaryFile "build.log" WriteMode $ \handle -> do packageList <- mapM (replaceTarball $ tarballDir settings) $ bpPackageList bp let args = addCabalArgs settings BSBuild $ "install" : ("--cabal-lib-version=" ++ libVersion) : "--build-log=logs/$pkg.log" : "--max-backjumps=-1" : "--reorder-goals" : packageList hPutStrLn handle ("cabal " ++ unwords (map (\s -> "'" ++ s ++ "'") args)) runCabal args handle ec <- waitForProcess ph unless (ec == ExitSuccess) $ do putStrLn "Build failed, please see build.log" L8.readFile "build.log" >>= L8.putStr exitWith ec putStrLn "Build completed successfully, checking for module name conflicts" conflicts <- getModuleNameConflicts $ packageDir settings System.IO.UTF8.writeFile "module-name-conflicts.txt" $ renderModuleNameConflicts conflicts