module Pier.Build.TargetInfo
( TargetInfo(..)
, TargetResult(..)
, TransitiveDeps(..)
, getTargetInfo
) where
import Control.Monad (filterM)
import Data.List (nub)
import Data.Maybe (catMaybes, fromMaybe)
import Development.Shake
import Development.Shake.FilePath ((</>))
import Distribution.Compiler (CompilerFlavor(GHC))
import Distribution.ModuleName
import Distribution.Package (packageName)
import Distribution.PackageDescription
import Distribution.Text (display)
import Language.Haskell.Extension
import Pier.Build.CFlags
import Pier.Build.ConfiguredPackage
import Pier.Build.Module
import Pier.Build.Stackage
import Pier.Core.Artifact
data TargetInfo = TargetInfo
{ targetCFlags :: CFlags
, targetSourceInputs :: [Artifact]
, targetOtherInputs :: [Artifact]
, targetOptions :: [String]
, targetIncludeDirs :: [FilePath]
, targetSourceDirs :: [Artifact]
, targetOtherModules :: [ModuleName]
}
data TargetResult
= TargetBinary { targetModulePath :: FilePath }
| TargetLibrary
{ targetExposedModules :: [ModuleName]
}
getTargetInfo ::
ConfiguredPackage
-> BuildInfo
-> TargetResult
-> TransitiveDeps
-> InstalledGhc
-> Action TargetInfo
getTargetInfo confd bi result deps ghc = do
let packageSourceDir = confdSourceDir confd
cflags <- getCFlags deps packageSourceDir bi
let allOptions = map ("-X" ++)
(display (fromMaybe Haskell98 $ defaultLanguage bi)
: map display (defaultExtensions bi ++ oldExtensions bi))
++ concat [opts | (GHC,opts) <- options bi]
let srcDirs = sourceDirArtifacts packageSourceDir bi
let fixDashes = map $ \c -> if c == '-' then '_' else c
let pathsMod = fromString $ "Paths_" ++ fixDashes (display $ packageName confd)
let allModules = otherModules bi ++ case result of
TargetLibrary exposed -> exposed
TargetBinary _
-> [pathsMod | pathsMod `notElem` otherModules bi]
moduleFiles <- mapM (findModule ghc confd cflags srcDirs)
allModules
moduleBootFiles <- catMaybes <$> mapM findBootFile moduleFiles
let cFiles = map (packageSourceDir />) $ cSources bi
cIncludes <- collectCIncludes (confdDesc confd) bi (packageSourceDir />)
moduleMainFiles <- case result of
TargetLibrary{} -> return []
TargetBinary f -> do
path <- findMainFile ghc cflags srcDirs f
return [path | path `notElem` moduleFiles]
return TargetInfo
{ targetCFlags = cflags
, targetSourceInputs = cFiles ++ moduleFiles ++ moduleMainFiles
, targetOtherInputs = cIncludes ++ moduleBootFiles
, targetOptions = allOptions
, targetIncludeDirs = includeDirs bi
, targetSourceDirs = srcDirs
, targetOtherModules = otherModules bi
}
collectCIncludes :: PackageDescription -> BuildInfo -> (FilePath -> Artifact) -> Action [Artifact]
collectCIncludes desc bi pkgDir = do
includeInputs <- findIncludeInputs pkgDir bi
extraTmps <- fmap catMaybes . mapM ((\f -> doesArtifactExist f >>= \case
True -> return (Just f)
False -> return Nothing)
. pkgDir)
$ extraTmpFiles desc
return $ includeInputs ++ extraTmps
findIncludeInputs :: (FilePath -> Artifact) -> BuildInfo -> Action [Artifact]
findIncludeInputs pkgDir bi = filterM doesArtifactExist candidates
where
candidates = nub
[ pkgDir $ d </> f
| d <- "" : includeDirs bi
, f <- includes bi ++ installIncludes bi
]