module Distribution.Simple.GHC.Build where
import Distribution.Compat.Prelude
import Prelude ()
import Control.Monad.IO.Class
import qualified Data.Set as Set
import Distribution.PackageDescription as PD hiding (buildInfo)
import Distribution.Simple.Build.Inputs
import Distribution.Simple.Flag (Flag)
import Distribution.Simple.GHC.Build.ExtraSources
import Distribution.Simple.GHC.Build.Link
import Distribution.Simple.GHC.Build.Modules
import Distribution.Simple.GHC.Build.Utils (withDynFLib)
import Distribution.Simple.LocalBuildInfo
import Distribution.Simple.Program
import Distribution.Simple.Utils
import Distribution.Types.ComponentLocalBuildInfo (componentIsIndefinite)
import Distribution.Types.ParStrat
import Distribution.Utils.NubList (fromNubListR)
import System.Directory hiding (exeExtension)
import System.FilePath
build
:: Flag ParStrat
-> PackageDescription
-> PreBuildComponentInputs
-> IO ()
build :: Flag ParStrat
-> PackageDescription -> PreBuildComponentInputs -> IO ()
build Flag ParStrat
numJobs PackageDescription
pkg_descr PreBuildComponentInputs
pbci = do
let
verbosity :: Verbosity
verbosity = PreBuildComponentInputs -> Verbosity
buildVerbosity PreBuildComponentInputs
pbci
component :: Component
component = PreBuildComponentInputs -> Component
buildComponent PreBuildComponentInputs
pbci
isLib :: Bool
isLib = PreBuildComponentInputs -> Bool
buildIsLib PreBuildComponentInputs
pbci
lbi :: LocalBuildInfo
lbi = PreBuildComponentInputs -> LocalBuildInfo
localBuildInfo PreBuildComponentInputs
pbci
clbi :: ComponentLocalBuildInfo
clbi = PreBuildComponentInputs -> ComponentLocalBuildInfo
buildCLBI PreBuildComponentInputs
pbci
let targetDir_absolute :: FilePath
targetDir_absolute = LocalBuildInfo -> ComponentLocalBuildInfo -> FilePath
componentBuildDir LocalBuildInfo
lbi ComponentLocalBuildInfo
clbi
buildTargetDir_absolute :: FilePath
buildTargetDir_absolute
| Bool
isLib = FilePath
targetDir_absolute
| FilePath
targetDirName : [FilePath]
_ <- [FilePath] -> [FilePath]
forall a. [a] -> [a]
reverse ([FilePath] -> [FilePath]) -> [FilePath] -> [FilePath]
forall a b. (a -> b) -> a -> b
$ FilePath -> [FilePath]
splitDirectories FilePath
targetDir_absolute =
FilePath
targetDir_absolute FilePath -> FilePath -> FilePath
</> (FilePath
targetDirName FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ FilePath
"-tmp")
| Bool
otherwise = FilePath -> FilePath
forall a. HasCallStack => FilePath -> a
error FilePath
"GHC.build: targetDir is empty"
IO () -> IO ()
forall a. IO a -> IO a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ do
Verbosity -> Bool -> FilePath -> IO ()
createDirectoryIfMissingVerbose Verbosity
verbosity Bool
True FilePath
targetDir_absolute
Verbosity -> Bool -> FilePath -> IO ()
createDirectoryIfMissingVerbose Verbosity
verbosity Bool
True FilePath
buildTargetDir_absolute
FilePath
_targetDir <- IO FilePath -> IO FilePath
forall a. IO a -> IO a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO FilePath -> IO FilePath) -> IO FilePath -> IO FilePath
forall a b. (a -> b) -> a -> b
$ FilePath -> IO FilePath
makeRelativeToCurrentDirectory FilePath
targetDir_absolute
FilePath
buildTargetDir <-
if Bool
isLib
then IO FilePath -> IO FilePath
forall a. IO a -> IO a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO FilePath -> IO FilePath) -> IO FilePath -> IO FilePath
forall a b. (a -> b) -> a -> b
$ FilePath -> IO FilePath
makeRelativeToCurrentDirectory FilePath
buildTargetDir_absolute
else FilePath -> IO FilePath
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return FilePath
buildTargetDir_absolute
(ConfiguredProgram
ghcProg, ProgramDb
_) <- IO (ConfiguredProgram, ProgramDb)
-> IO (ConfiguredProgram, ProgramDb)
forall a. IO a -> IO a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO (ConfiguredProgram, ProgramDb)
-> IO (ConfiguredProgram, ProgramDb))
-> IO (ConfiguredProgram, ProgramDb)
-> IO (ConfiguredProgram, ProgramDb)
forall a b. (a -> b) -> a -> b
$ Verbosity
-> Program -> ProgramDb -> IO (ConfiguredProgram, ProgramDb)
requireProgram Verbosity
verbosity Program
ghcProgram (LocalBuildInfo -> ProgramDb
withPrograms LocalBuildInfo
lbi)
let
wantVanilla :: Bool
wantVanilla = if Bool
isLib then LocalBuildInfo -> Bool
withVanillaLib LocalBuildInfo
lbi else Bool
False
wantStatic :: Bool
wantStatic = if Bool
isLib then LocalBuildInfo -> Bool
withStaticLib LocalBuildInfo
lbi else Bool -> Bool
not (Bool
wantDynamic Bool -> Bool -> Bool
|| Bool
wantProf)
wantDynamic :: Bool
wantDynamic = case Component
component of
CLib{} -> LocalBuildInfo -> Bool
withSharedLib LocalBuildInfo
lbi
CFLib ForeignLib
flib -> ForeignLib -> Bool
withDynFLib ForeignLib
flib
CExe{} -> LocalBuildInfo -> Bool
withDynExe LocalBuildInfo
lbi
CTest{} -> LocalBuildInfo -> Bool
withDynExe LocalBuildInfo
lbi
CBench{} -> LocalBuildInfo -> Bool
withDynExe LocalBuildInfo
lbi
wantProf :: Bool
wantProf = if Bool
isLib then LocalBuildInfo -> Bool
withProfLib LocalBuildInfo
lbi else LocalBuildInfo -> Bool
withProfExe LocalBuildInfo
lbi
wantedWays :: Set BuildWay
wantedWays =
[BuildWay] -> Set BuildWay
forall a. Ord a => [a] -> Set a
Set.fromList ([BuildWay] -> Set BuildWay) -> [BuildWay] -> Set BuildWay
forall a b. (a -> b) -> a -> b
$
(if Bool
isLib then [BuildWay] -> [BuildWay]
forall a. a -> a
id else Int -> [BuildWay] -> [BuildWay]
forall a. Int -> [a] -> [a]
take Int
1) ([BuildWay] -> [BuildWay]) -> [BuildWay] -> [BuildWay]
forall a b. (a -> b) -> a -> b
$
[BuildWay
ProfWay | Bool
wantProf]
[BuildWay] -> [BuildWay] -> [BuildWay]
forall a. Semigroup a => a -> a -> a
<> [BuildWay
DynWay | Bool
wantDynamic Bool -> Bool -> Bool
&& Bool -> Bool
not (ComponentLocalBuildInfo -> Bool
componentIsIndefinite ComponentLocalBuildInfo
clbi)]
[BuildWay] -> [BuildWay] -> [BuildWay]
forall a. Semigroup a => a -> a -> a
<> [BuildWay
StaticWay | Bool
wantStatic Bool -> Bool -> Bool
|| Bool
wantVanilla Bool -> Bool -> Bool
|| Bool -> Bool
not (Bool
wantDynamic Bool -> Bool -> Bool
|| Bool
wantProf)]
IO () -> IO ()
forall a. IO a -> IO a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO () -> IO ()) -> IO () -> IO ()
forall a b. (a -> b) -> a -> b
$ Verbosity -> FilePath -> IO ()
info Verbosity
verbosity (FilePath
"Wanted build ways: " FilePath -> FilePath -> FilePath
forall a. [a] -> [a] -> [a]
++ [BuildWay] -> FilePath
forall a. Show a => a -> FilePath
show (Set BuildWay -> [BuildWay]
forall a. Set a -> [a]
Set.toList Set BuildWay
wantedWays))
BuildWay -> GhcOptions
buildOpts <- Flag ParStrat
-> ConfiguredProgram
-> PackageDescription
-> FilePath
-> Set BuildWay
-> PreBuildComponentInputs
-> IO (BuildWay -> GhcOptions)
buildHaskellModules Flag ParStrat
numJobs ConfiguredProgram
ghcProg PackageDescription
pkg_descr FilePath
buildTargetDir_absolute Set BuildWay
wantedWays PreBuildComponentInputs
pbci
NubListR FilePath
extraSources <- ConfiguredProgram
-> FilePath -> PreBuildComponentInputs -> IO (NubListR FilePath)
buildAllExtraSources ConfiguredProgram
ghcProg FilePath
buildTargetDir PreBuildComponentInputs
pbci
ConfiguredProgram
-> PackageDescription
-> [FilePath]
-> (FilePath, FilePath)
-> (Set BuildWay, BuildWay -> GhcOptions)
-> PreBuildComponentInputs
-> IO ()
linkOrLoadComponent ConfiguredProgram
ghcProg PackageDescription
pkg_descr (NubListR FilePath -> [FilePath]
forall a. NubListR a -> [a]
fromNubListR NubListR FilePath
extraSources) (FilePath
buildTargetDir, FilePath
targetDir_absolute) (Set BuildWay
wantedWays, BuildWay -> GhcOptions
buildOpts) PreBuildComponentInputs
pbci