{-# LANGUAGE NoImplicitPrelude     #-}
{-# LANGUAGE DataKinds             #-}
{-# LANGUAGE DuplicateRecordFields #-}
{-# LANGUAGE OverloadedRecordDot   #-}
{-# LANGUAGE OverloadedStrings     #-}
{-# LANGUAGE ScopedTypeVariables   #-}

-- | Dealing with Cabal.


module Stack.Package
  ( readDotBuildinfo
  , resolvePackage
  , packageFromPackageDescription
  , Package (..)
  , PackageConfig (..)
  , buildLogPath
  , PackageException (..)
  , resolvePackageDescription
  , packageDependencies
  , applyForceCustomBuild
  , hasBuildableMainLibrary
  , mainLibraryHasExposedModules
  , packageUnknownTools
  , buildableForeignLibs
  , buildableSubLibs
  , buildableExes
  , buildableTestSuites
  , buildableBenchmarks
  , getPackageOpts
  , processPackageDepsToList
  , listOfPackageDeps
  , setOfPackageDeps
  , topSortPackageComponent
  ) where

import qualified Data.Map.Strict as M
import qualified Data.Set as S
import           Data.STRef ( STRef, modifySTRef', readSTRef, newSTRef )
import qualified Data.Text as T
import           Distribution.CabalSpecVersion ( cabalSpecToVersionDigits )
import           Distribution.Compiler
                   ( CompilerFlavor (..), PerCompilerFlavor (..) )
import           Distribution.ModuleName ( ModuleName )
import           Distribution.Package ( mkPackageName )
import           Distribution.PackageDescription
                   ( Benchmark (..), BuildInfo (..), BuildType (..)
                   , CondTree (..), Condition (..), ConfVar (..)
                   , Dependency (..), Executable (..), ForeignLib (..)
                   , GenericPackageDescription (..), HookedBuildInfo
                   , Library (..), PackageDescription (..), PackageFlag (..)
                   , SetupBuildInfo (..), TestSuite (..), allLibraries
                   , buildType, depPkgName, depVerRange
                   )
import qualified Distribution.PackageDescription as Executable
                   ( Executable (..) )
import           Distribution.Simple.PackageDescription ( readHookedBuildInfo )
import           Distribution.System ( OS (..), Arch, Platform (..) )
import           Distribution.Text ( display )
import qualified Distribution.Types.CondTree as Cabal
import           Distribution.Utils.Path ( getSymbolicPath )
import           Distribution.Verbosity ( silent )
import           Distribution.Version
                   ( anyVersion, mkVersion, orLaterVersion )
import           Path
                   ( (</>), parent, parseAbsDir, parseRelDir, parseRelFile
                   , stripProperPrefix
                   )
import           Path.Extra ( concatAndCollapseAbsDir, toFilePathNoTrailingSep )
import           Stack.Component
                   ( componentDependencyMap, foldOnNameAndBuildInfo
                   , isComponentBuildable, stackBenchmarkFromCabal
                   , stackExecutableFromCabal, stackForeignLibraryFromCabal
                   , stackLibraryFromCabal, stackTestFromCabal
                   , stackUnqualToQual
                   )
import           Stack.ComponentFile
                   ( buildDir, componentAutogenDir, componentBuildDir
                   , componentOutputDir, packageAutogenDir
                   )
import           Stack.Constants (relFileCabalMacrosH, relDirLogs)
import           Stack.Constants.Config ( distDirFromDir )
import           Stack.PackageFile ( getPackageFile, stackPackageFileFromCabal )
import           Stack.Prelude hiding ( Display (..) )
import           Stack.Types.BuildConfig
                   ( HasBuildConfig (..), getProjectWorkDir )
import           Stack.Types.CompCollection
                   ( CompCollection, collectionLookup, foldAndMakeCollection
                   , foldComponentToAnotherCollection, getBuildableSetText
                   )
import           Stack.Types.Compiler ( ActualCompiler (..) )
import           Stack.Types.CompilerPaths ( cabalVersionL )
import           Stack.Types.Component
                   ( HasBuildInfo, HasComponentInfo, StackUnqualCompName (..) )
import qualified Stack.Types.Component as Component
import           Stack.Types.Config ( Config (..), HasConfig (..) )
import           Stack.Types.Dependency
                   ( DepLibrary (..), DepType (..), DepValue (..)
                   , cabalSetupDepsToStackDep, libraryDepFromVersionRange
                   )
import           Stack.Types.EnvConfig ( HasEnvConfig )
import           Stack.Types.Installed
                   ( InstallMap, Installed (..), InstalledMap
                   , installedToPackageIdOpt
                   )
import           Stack.Types.NamedComponent
                   ( NamedComponent (..), isPotentialDependency
                   , subLibComponents
                   )
import           Stack.Types.Package
                   ( BioInput(..), BuildInfoOpts (..), Package (..)
                   , PackageConfig (..), PackageException (..)
                   , dotCabalCFilePath, packageIdentifier
                   )
import           Stack.Types.PackageFile
                   ( DotCabalPath, PackageComponentFile (..) )
import           Stack.Types.SourceMap (Target(..))
import           Stack.Types.Version
                   ( VersionRange, intersectVersionRanges, withinRange )
import           System.FilePath ( replaceExtension )
import           RIO.Seq ((|>))

-- | Read @<package>.buildinfo@ ancillary files produced by some Setup.hs hooks.

-- The file includes Cabal file syntax to be merged into the package description

-- derived from the package's Cabal file.

--

-- NOTE: not to be confused with BuildInfo, an Stack-internal datatype.

readDotBuildinfo :: MonadIO m => Path Abs File -> m HookedBuildInfo
readDotBuildinfo :: forall (m :: * -> *).
MonadIO m =>
Path Abs File -> m HookedBuildInfo
readDotBuildinfo Path Abs File
buildinfofp =
  IO HookedBuildInfo -> m HookedBuildInfo
forall a. IO a -> m a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO HookedBuildInfo -> m HookedBuildInfo)
-> IO HookedBuildInfo -> m HookedBuildInfo
forall a b. (a -> b) -> a -> b
$ Verbosity -> String -> IO HookedBuildInfo
readHookedBuildInfo Verbosity
silent (Path Abs File -> String
forall b t. Path b t -> String
toFilePath Path Abs File
buildinfofp)

-- | Resolve a parsed Cabal file into a 'Package', which contains all of the

-- info needed for Stack to build the 'Package' given the current configuration.

resolvePackage :: PackageConfig -> GenericPackageDescription -> Package
resolvePackage :: PackageConfig -> GenericPackageDescription -> Package
resolvePackage PackageConfig
packageConfig GenericPackageDescription
gpkg =
  PackageConfig -> [PackageFlag] -> PackageDescription -> Package
packageFromPackageDescription
    PackageConfig
packageConfig
    (GenericPackageDescription -> [PackageFlag]
genPackageFlags GenericPackageDescription
gpkg)
    (PackageConfig -> GenericPackageDescription -> PackageDescription
resolvePackageDescription PackageConfig
packageConfig GenericPackageDescription
gpkg)

packageFromPackageDescription ::
     PackageConfig
  -> [PackageFlag]
  -> PackageDescription
  -> Package
packageFromPackageDescription :: PackageConfig -> [PackageFlag] -> PackageDescription -> Package
packageFromPackageDescription
    PackageConfig
packageConfig
    [PackageFlag]
pkgFlags
    PackageDescription
pkg
  = Package
      { $sel:name:Package :: PackageName
name = PackageName
name
      , $sel:version:Package :: Version
version = PackageIdentifier -> Version
pkgVersion PackageIdentifier
pkgId
      , $sel:license:Package :: Either License License
license = PackageDescription -> Either License License
licenseRaw PackageDescription
pkg
      , $sel:ghcOptions:Package :: [Text]
ghcOptions =  PackageConfig
packageConfig.ghcOptions
      , $sel:cabalConfigOpts:Package :: [Text]
cabalConfigOpts =  PackageConfig
packageConfig.cabalConfigOpts
      , $sel:flags:Package :: Map FlagName Bool
flags = PackageConfig
packageConfig.flags
      , $sel:defaultFlags:Package :: Map FlagName Bool
defaultFlags = [(FlagName, Bool)] -> Map FlagName Bool
forall k a. Ord k => [(k, a)] -> Map k a
M.fromList
          [(PackageFlag -> FlagName
flagName PackageFlag
flag, PackageFlag -> Bool
flagDefault PackageFlag
flag) | PackageFlag
flag <- [PackageFlag]
pkgFlags]
      , $sel:library:Package :: Maybe StackLibrary
library = Library -> StackLibrary
stackLibraryFromCabal (Library -> StackLibrary) -> Maybe Library -> Maybe StackLibrary
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> PackageDescription -> Maybe Library
library PackageDescription
pkg
      , $sel:subLibraries:Package :: CompCollection StackLibrary
subLibraries =
          (Library -> StackLibrary)
-> [Library] -> CompCollection StackLibrary
forall compB (sourceCollection :: * -> *) compA.
(HasBuildInfo compB, HasName compB, Foldable sourceCollection) =>
(compA -> compB) -> sourceCollection compA -> CompCollection compB
foldAndMakeCollection Library -> StackLibrary
stackLibraryFromCabal ([Library] -> CompCollection StackLibrary)
-> [Library] -> CompCollection StackLibrary
forall a b. (a -> b) -> a -> b
$ PackageDescription -> [Library]
subLibraries PackageDescription
pkg
      , $sel:foreignLibraries:Package :: CompCollection StackForeignLibrary
foreignLibraries =
          (ForeignLib -> StackForeignLibrary)
-> [ForeignLib] -> CompCollection StackForeignLibrary
forall compB (sourceCollection :: * -> *) compA.
(HasBuildInfo compB, HasName compB, Foldable sourceCollection) =>
(compA -> compB) -> sourceCollection compA -> CompCollection compB
foldAndMakeCollection ForeignLib -> StackForeignLibrary
stackForeignLibraryFromCabal ([ForeignLib] -> CompCollection StackForeignLibrary)
-> [ForeignLib] -> CompCollection StackForeignLibrary
forall a b. (a -> b) -> a -> b
$ PackageDescription -> [ForeignLib]
foreignLibs PackageDescription
pkg
      , $sel:testSuites:Package :: CompCollection StackTestSuite
testSuites =
          (TestSuite -> StackTestSuite)
-> [TestSuite] -> CompCollection StackTestSuite
forall compB (sourceCollection :: * -> *) compA.
(HasBuildInfo compB, HasName compB, Foldable sourceCollection) =>
(compA -> compB) -> sourceCollection compA -> CompCollection compB
foldAndMakeCollection TestSuite -> StackTestSuite
stackTestFromCabal ([TestSuite] -> CompCollection StackTestSuite)
-> [TestSuite] -> CompCollection StackTestSuite
forall a b. (a -> b) -> a -> b
$ PackageDescription -> [TestSuite]
testSuites PackageDescription
pkg
      , $sel:benchmarks:Package :: CompCollection StackBenchmark
benchmarks =
          (Benchmark -> StackBenchmark)
-> [Benchmark] -> CompCollection StackBenchmark
forall compB (sourceCollection :: * -> *) compA.
(HasBuildInfo compB, HasName compB, Foldable sourceCollection) =>
(compA -> compB) -> sourceCollection compA -> CompCollection compB
foldAndMakeCollection Benchmark -> StackBenchmark
stackBenchmarkFromCabal ([Benchmark] -> CompCollection StackBenchmark)
-> [Benchmark] -> CompCollection StackBenchmark
forall a b. (a -> b) -> a -> b
$ PackageDescription -> [Benchmark]
benchmarks PackageDescription
pkg
      , $sel:executables:Package :: CompCollection StackExecutable
executables =
          (Executable -> StackExecutable)
-> [Executable] -> CompCollection StackExecutable
forall compB (sourceCollection :: * -> *) compA.
(HasBuildInfo compB, HasName compB, Foldable sourceCollection) =>
(compA -> compB) -> sourceCollection compA -> CompCollection compB
foldAndMakeCollection Executable -> StackExecutable
stackExecutableFromCabal ([Executable] -> CompCollection StackExecutable)
-> [Executable] -> CompCollection StackExecutable
forall a b. (a -> b) -> a -> b
$ PackageDescription -> [Executable]
executables PackageDescription
pkg
      , $sel:buildType:Package :: BuildType
buildType = PackageDescription -> BuildType
buildType PackageDescription
pkg
      , $sel:setupDeps:Package :: Maybe (Map PackageName DepValue)
setupDeps = (SetupBuildInfo -> Map PackageName DepValue)
-> Maybe SetupBuildInfo -> Maybe (Map PackageName DepValue)
forall a b. (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap SetupBuildInfo -> Map PackageName DepValue
cabalSetupDepsToStackDep (PackageDescription -> Maybe SetupBuildInfo
setupBuildInfo PackageDescription
pkg)
      , $sel:cabalSpec:Package :: CabalSpecVersion
cabalSpec = PackageDescription -> CabalSpecVersion
specVersion PackageDescription
pkg
      , $sel:file:Package :: StackPackageFile
file = PackageDescription -> StackPackageFile
stackPackageFileFromCabal PackageDescription
pkg
      , $sel:testEnabled:Package :: Bool
testEnabled =  PackageConfig
packageConfig.enableTests
      , $sel:benchmarkEnabled:Package :: Bool
benchmarkEnabled = PackageConfig
packageConfig.enableBenchmarks
      }
 where
  -- Gets all of the modules, files, build files, and data files that constitute

  -- the package. This is primarily used for dirtiness checking during build, as

  -- well as use by "stack ghci"

  pkgId :: PackageIdentifier
pkgId = PackageDescription -> PackageIdentifier
package PackageDescription
pkg
  name :: PackageName
name = PackageIdentifier -> PackageName
pkgName PackageIdentifier
pkgId

-- | This is an action used to collect info needed for "stack ghci". This info

-- isn't usually needed, so computation of it is deferred.

getPackageOpts ::
     (HasEnvConfig env, MonadReader env m, MonadThrow m, MonadUnliftIO m )
  => Package
  -> InstallMap
  -> InstalledMap
  -> [PackageName]
  -> [PackageName]
  -> Path Abs File
  -> m ( Map NamedComponent (Map ModuleName (Path Abs File))
       , Map NamedComponent [DotCabalPath]
       , Map NamedComponent BuildInfoOpts
       )
getPackageOpts :: forall env (m :: * -> *).
(HasEnvConfig env, MonadReader env m, MonadThrow m,
 MonadUnliftIO m) =>
Package
-> InstallMap
-> InstalledMap
-> [PackageName]
-> [PackageName]
-> Path Abs File
-> m (Map NamedComponent (Map ModuleName (Path Abs File)),
      Map NamedComponent [DotCabalPath],
      Map NamedComponent BuildInfoOpts)
getPackageOpts
    Package
stackPackage
    InstallMap
installMap
    InstalledMap
installedMap
    [PackageName]
omitPkgs
    [PackageName]
addPkgs
    Path Abs File
cabalFP
  = do
      PackageComponentFile !Map NamedComponent (Map ModuleName (Path Abs File))
componentsModules Map NamedComponent [DotCabalPath]
componentFiles Set (Path Abs File)
_ [PackageWarning]
_ <-
        Package -> Path Abs File -> m PackageComponentFile
forall s (m :: * -> *).
(HasEnvConfig s, MonadReader s m, MonadThrow m, MonadUnliftIO m) =>
Package -> Path Abs File -> m PackageComponentFile
getPackageFile Package
stackPackage Path Abs File
cabalFP
      let subLibs :: [Text]
subLibs =
            Set Text -> [Text]
forall a. Set a -> [a]
S.toList (Set Text -> [Text]) -> Set Text -> [Text]
forall a b. (a -> b) -> a -> b
$ Set NamedComponent -> Set Text
subLibComponents (Set NamedComponent -> Set Text) -> Set NamedComponent -> Set Text
forall a b. (a -> b) -> a -> b
$ Map NamedComponent (Map ModuleName (Path Abs File))
-> Set NamedComponent
forall k a. Map k a -> Set k
M.keysSet Map NamedComponent (Map ModuleName (Path Abs File))
componentsModules
      [PackageName]
excludedSubLibs <- (Text -> m PackageName) -> [Text] -> m [PackageName]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [b]
mapM (String -> m PackageName
forall (m :: * -> *). MonadThrow m => String -> m PackageName
parsePackageNameThrowing (String -> m PackageName)
-> (Text -> String) -> Text -> m PackageName
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> String
T.unpack) [Text]
subLibs
      Map NamedComponent BuildInfoOpts
componentsOpts <- InstallMap
-> InstalledMap
-> [PackageName]
-> [PackageName]
-> Path Abs File
-> Package
-> Map NamedComponent [DotCabalPath]
-> m (Map NamedComponent BuildInfoOpts)
forall env (m :: * -> *).
(HasEnvConfig env, MonadThrow m, MonadReader env m, MonadIO m) =>
InstallMap
-> InstalledMap
-> [PackageName]
-> [PackageName]
-> Path Abs File
-> Package
-> Map NamedComponent [DotCabalPath]
-> m (Map NamedComponent BuildInfoOpts)
generatePkgDescOpts
        InstallMap
installMap
        InstalledMap
installedMap
        ([PackageName]
excludedSubLibs [PackageName] -> [PackageName] -> [PackageName]
forall a. [a] -> [a] -> [a]
++ [PackageName]
omitPkgs)
        [PackageName]
addPkgs
        Path Abs File
cabalFP
        Package
stackPackage
        Map NamedComponent [DotCabalPath]
componentFiles
      (Map NamedComponent (Map ModuleName (Path Abs File)),
 Map NamedComponent [DotCabalPath],
 Map NamedComponent BuildInfoOpts)
-> m (Map NamedComponent (Map ModuleName (Path Abs File)),
      Map NamedComponent [DotCabalPath],
      Map NamedComponent BuildInfoOpts)
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Map NamedComponent (Map ModuleName (Path Abs File))
componentsModules, Map NamedComponent [DotCabalPath]
componentFiles, Map NamedComponent BuildInfoOpts
componentsOpts)

-- | Generate GHC options for the package's components, and a list of options

-- which apply generally to the package, not one specific component.

generatePkgDescOpts ::
     (HasEnvConfig env, MonadThrow m, MonadReader env m, MonadIO m)
  => InstallMap
  -> InstalledMap
  -> [PackageName]
     -- ^ Packages to omit from the "-package" / "-package-id" flags

  -> [PackageName]
     -- ^ Packages to add to the "-package" flags

  -> Path Abs File
  -> Package
  -> Map NamedComponent [DotCabalPath]
  -> m (Map NamedComponent BuildInfoOpts)
generatePkgDescOpts :: forall env (m :: * -> *).
(HasEnvConfig env, MonadThrow m, MonadReader env m, MonadIO m) =>
InstallMap
-> InstalledMap
-> [PackageName]
-> [PackageName]
-> Path Abs File
-> Package
-> Map NamedComponent [DotCabalPath]
-> m (Map NamedComponent BuildInfoOpts)
generatePkgDescOpts
    InstallMap
installMap
    InstalledMap
installedMap
    [PackageName]
omitPackages
    [PackageName]
addPackages
    Path Abs File
cabalFP
    Package
pkg
    Map NamedComponent [DotCabalPath]
componentPaths
  = do
      Config
config <- Getting Config env Config -> m Config
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view Getting Config env Config
forall env. HasConfig env => Lens' env Config
Lens' env Config
configL
      Version
cabalVersion <- Getting Version env Version -> m Version
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view Getting Version env Version
forall env. HasCompiler env => SimpleGetter env Version
SimpleGetter env Version
cabalVersionL
      Path Abs Dir
distDir <- Path Abs Dir -> m (Path Abs Dir)
forall env (m :: * -> *).
(HasEnvConfig env, MonadReader env m, MonadThrow m) =>
Path Abs Dir -> m (Path Abs Dir)
distDirFromDir Path Abs Dir
cabalDir
      let generate :: NamedComponent -> StackBuildInfo -> BuildInfoOpts
generate NamedComponent
componentName StackBuildInfo
buildInfo = BioInput -> BuildInfoOpts
generateBuildInfoOpts BioInput
            { InstallMap
installMap :: InstallMap
$sel:installMap:BioInput :: InstallMap
installMap
            , InstalledMap
installedMap :: InstalledMap
$sel:installedMap:BioInput :: InstalledMap
installedMap
            , Path Abs Dir
cabalDir :: Path Abs Dir
$sel:cabalDir:BioInput :: Path Abs Dir
cabalDir
            , Path Abs Dir
distDir :: Path Abs Dir
$sel:distDir:BioInput :: Path Abs Dir
distDir
            , [PackageName]
omitPackages :: [PackageName]
$sel:omitPackages:BioInput :: [PackageName]
omitPackages
            , [PackageName]
addPackages :: [PackageName]
$sel:addPackages:BioInput :: [PackageName]
addPackages
            , StackBuildInfo
buildInfo :: StackBuildInfo
$sel:buildInfo:BioInput :: StackBuildInfo
buildInfo
            , $sel:dotCabalPaths:BioInput :: [DotCabalPath]
dotCabalPaths =
                [DotCabalPath] -> Maybe [DotCabalPath] -> [DotCabalPath]
forall a. a -> Maybe a -> a
fromMaybe [] (NamedComponent
-> Map NamedComponent [DotCabalPath] -> Maybe [DotCabalPath]
forall k a. Ord k => k -> Map k a -> Maybe a
M.lookup NamedComponent
componentName Map NamedComponent [DotCabalPath]
componentPaths)
            , $sel:configLibDirs:BioInput :: [String]
configLibDirs = Config
config.extraLibDirs
            , $sel:configIncludeDirs:BioInput :: [String]
configIncludeDirs = Config
config.extraIncludeDirs
            , NamedComponent
componentName :: NamedComponent
$sel:componentName:BioInput :: NamedComponent
componentName
            , Version
cabalVersion :: Version
$sel:cabalVersion:BioInput :: Version
cabalVersion
            }
      let insertInMap :: NamedComponent
-> StackBuildInfo
-> Map NamedComponent BuildInfoOpts
-> Map NamedComponent BuildInfoOpts
insertInMap NamedComponent
name StackBuildInfo
compVal = NamedComponent
-> BuildInfoOpts
-> Map NamedComponent BuildInfoOpts
-> Map NamedComponent BuildInfoOpts
forall k a. Ord k => k -> a -> Map k a -> Map k a
M.insert NamedComponent
name (NamedComponent -> StackBuildInfo -> BuildInfoOpts
generate NamedComponent
name StackBuildInfo
compVal)
      let translatedInsertInMap :: (Text -> NamedComponent)
-> StackUnqualCompName
-> StackBuildInfo
-> Map NamedComponent BuildInfoOpts
-> Map NamedComponent BuildInfoOpts
translatedInsertInMap Text -> NamedComponent
constructor StackUnqualCompName
name =
            NamedComponent
-> StackBuildInfo
-> Map NamedComponent BuildInfoOpts
-> Map NamedComponent BuildInfoOpts
insertInMap ((Text -> NamedComponent) -> StackUnqualCompName -> NamedComponent
stackUnqualToQual Text -> NamedComponent
constructor StackUnqualCompName
name)
      let makeBuildInfoOpts :: (Package -> c a)
-> (Text -> NamedComponent)
-> Map NamedComponent BuildInfoOpts
-> Map NamedComponent BuildInfoOpts
makeBuildInfoOpts Package -> c a
selector Text -> NamedComponent
constructor =
            c a
-> (StackUnqualCompName
    -> StackBuildInfo
    -> Map NamedComponent BuildInfoOpts
    -> Map NamedComponent BuildInfoOpts)
-> Map NamedComponent BuildInfoOpts
-> Map NamedComponent BuildInfoOpts
forall a (c :: * -> *) t.
(HasField "buildInfo" a StackBuildInfo,
 HasField "name" a StackUnqualCompName, Foldable c) =>
c a -> (StackUnqualCompName -> StackBuildInfo -> t -> t) -> t -> t
foldOnNameAndBuildInfo
              (Package -> c a
selector Package
pkg)
              ((Text -> NamedComponent)
-> StackUnqualCompName
-> StackBuildInfo
-> Map NamedComponent BuildInfoOpts
-> Map NamedComponent BuildInfoOpts
translatedInsertInMap Text -> NamedComponent
constructor)
      let aggregateAllBuildInfoOpts :: Map NamedComponent BuildInfoOpts
-> Map NamedComponent BuildInfoOpts
aggregateAllBuildInfoOpts =
              (Package -> Maybe StackLibrary)
-> (Text -> NamedComponent)
-> Map NamedComponent BuildInfoOpts
-> Map NamedComponent BuildInfoOpts
forall {a} {c :: * -> *}.
(HasField "name" a StackUnqualCompName,
 HasField "buildInfo" a StackBuildInfo, Foldable c) =>
(Package -> c a)
-> (Text -> NamedComponent)
-> Map NamedComponent BuildInfoOpts
-> Map NamedComponent BuildInfoOpts
makeBuildInfoOpts (.library) (NamedComponent -> Text -> NamedComponent
forall a b. a -> b -> a
const NamedComponent
CLib)
            (Map NamedComponent BuildInfoOpts
 -> Map NamedComponent BuildInfoOpts)
-> (Map NamedComponent BuildInfoOpts
    -> Map NamedComponent BuildInfoOpts)
-> Map NamedComponent BuildInfoOpts
-> Map NamedComponent BuildInfoOpts
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Package -> CompCollection StackLibrary)
-> (Text -> NamedComponent)
-> Map NamedComponent BuildInfoOpts
-> Map NamedComponent BuildInfoOpts
forall {a} {c :: * -> *}.
(HasField "name" a StackUnqualCompName,
 HasField "buildInfo" a StackBuildInfo, Foldable c) =>
(Package -> c a)
-> (Text -> NamedComponent)
-> Map NamedComponent BuildInfoOpts
-> Map NamedComponent BuildInfoOpts
makeBuildInfoOpts (.subLibraries) Text -> NamedComponent
CSubLib
            (Map NamedComponent BuildInfoOpts
 -> Map NamedComponent BuildInfoOpts)
-> (Map NamedComponent BuildInfoOpts
    -> Map NamedComponent BuildInfoOpts)
-> Map NamedComponent BuildInfoOpts
-> Map NamedComponent BuildInfoOpts
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Package -> CompCollection StackExecutable)
-> (Text -> NamedComponent)
-> Map NamedComponent BuildInfoOpts
-> Map NamedComponent BuildInfoOpts
forall {a} {c :: * -> *}.
(HasField "name" a StackUnqualCompName,
 HasField "buildInfo" a StackBuildInfo, Foldable c) =>
(Package -> c a)
-> (Text -> NamedComponent)
-> Map NamedComponent BuildInfoOpts
-> Map NamedComponent BuildInfoOpts
makeBuildInfoOpts (.executables) Text -> NamedComponent
CExe
            (Map NamedComponent BuildInfoOpts
 -> Map NamedComponent BuildInfoOpts)
-> (Map NamedComponent BuildInfoOpts
    -> Map NamedComponent BuildInfoOpts)
-> Map NamedComponent BuildInfoOpts
-> Map NamedComponent BuildInfoOpts
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Package -> CompCollection StackBenchmark)
-> (Text -> NamedComponent)
-> Map NamedComponent BuildInfoOpts
-> Map NamedComponent BuildInfoOpts
forall {a} {c :: * -> *}.
(HasField "name" a StackUnqualCompName,
 HasField "buildInfo" a StackBuildInfo, Foldable c) =>
(Package -> c a)
-> (Text -> NamedComponent)
-> Map NamedComponent BuildInfoOpts
-> Map NamedComponent BuildInfoOpts
makeBuildInfoOpts (.benchmarks) Text -> NamedComponent
CBench
            (Map NamedComponent BuildInfoOpts
 -> Map NamedComponent BuildInfoOpts)
-> (Map NamedComponent BuildInfoOpts
    -> Map NamedComponent BuildInfoOpts)
-> Map NamedComponent BuildInfoOpts
-> Map NamedComponent BuildInfoOpts
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Package -> CompCollection StackTestSuite)
-> (Text -> NamedComponent)
-> Map NamedComponent BuildInfoOpts
-> Map NamedComponent BuildInfoOpts
forall {a} {c :: * -> *}.
(HasField "name" a StackUnqualCompName,
 HasField "buildInfo" a StackBuildInfo, Foldable c) =>
(Package -> c a)
-> (Text -> NamedComponent)
-> Map NamedComponent BuildInfoOpts
-> Map NamedComponent BuildInfoOpts
makeBuildInfoOpts (.testSuites) Text -> NamedComponent
CTest
      Map NamedComponent BuildInfoOpts
-> m (Map NamedComponent BuildInfoOpts)
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Map NamedComponent BuildInfoOpts
 -> m (Map NamedComponent BuildInfoOpts))
-> Map NamedComponent BuildInfoOpts
-> m (Map NamedComponent BuildInfoOpts)
forall a b. (a -> b) -> a -> b
$ Map NamedComponent BuildInfoOpts
-> Map NamedComponent BuildInfoOpts
aggregateAllBuildInfoOpts Map NamedComponent BuildInfoOpts
forall a. Monoid a => a
mempty
 where
  cabalDir :: Path Abs Dir
cabalDir = Path Abs File -> Path Abs Dir
forall b t. Path b t -> Path b Dir
parent Path Abs File
cabalFP

-- | Generate GHC options for the target. Since Cabal also figures out these

-- options, currently this is only used for invoking GHCI (via stack ghci).

generateBuildInfoOpts :: BioInput -> BuildInfoOpts
generateBuildInfoOpts :: BioInput -> BuildInfoOpts
generateBuildInfoOpts BioInput
bi =
  BuildInfoOpts
    { $sel:opts:BuildInfoOpts :: [String]
opts =
           [String]
ghcOpts
        [String] -> [String] -> [String]
forall a. [a] -> [a] -> [a]
++ (String -> String) -> [String] -> [String]
forall a b. (a -> b) -> [a] -> [b]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (String
"-optP" <>) BioInput
bi.buildInfo.cppOptions
    -- NOTE for future changes: Due to this use of nubOrd (and other uses

    -- downstream), these generated options must not rely on multiple

    -- argument sequences.  For example, ["--main-is", "Foo.hs", "--main-

    -- is", "Bar.hs"] would potentially break due to the duplicate

    -- "--main-is" being removed.

    --

    -- See https://github.com/commercialhaskell/stack/issues/1255

    , $sel:oneWordOpts:BuildInfoOpts :: [String]
oneWordOpts = [String] -> [String]
forall a. Ord a => [a] -> [a]
nubOrd ([String] -> [String]) -> [String] -> [String]
forall a b. (a -> b) -> a -> b
$ [[String]] -> [String]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat
        [[String]
extOpts, [String]
srcOpts, [String]
includeOpts, [String]
libOpts, [String]
fworks, [String]
cObjectFiles]
    , $sel:packageFlags:BuildInfoOpts :: [String]
packageFlags = [String]
deps
    , $sel:cabalMacros:BuildInfoOpts :: Path Abs File
cabalMacros = Path Abs Dir
componentAutogen Path Abs Dir -> Path Rel File -> Path Abs File
forall b t. Path b Dir -> Path Rel t -> Path b t
</> Path Rel File
relFileCabalMacrosH
    }
 where
  cObjectFiles :: [String]
cObjectFiles = (Path Abs File -> Maybe String) -> [Path Abs File] -> [String]
forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe
    ( (Path Abs File -> String) -> Maybe (Path Abs File) -> Maybe String
forall a b. (a -> b) -> Maybe a -> Maybe b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap Path Abs File -> String
forall b t. Path b t -> String
toFilePath
    (Maybe (Path Abs File) -> Maybe String)
-> (Path Abs File -> Maybe (Path Abs File))
-> Path Abs File
-> Maybe String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Path Abs Dir
-> NamedComponent
-> Path Abs Dir
-> Path Abs File
-> Maybe (Path Abs File)
forall (m :: * -> *).
MonadThrow m =>
Path Abs Dir
-> NamedComponent
-> Path Abs Dir
-> Path Abs File
-> m (Path Abs File)
makeObjectFilePathFromC BioInput
bi.cabalDir BioInput
bi.componentName BioInput
bi.distDir
    )
    [Path Abs File]
cfiles
  cfiles :: [Path Abs File]
cfiles = (DotCabalPath -> Maybe (Path Abs File))
-> [DotCabalPath] -> [Path Abs File]
forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe DotCabalPath -> Maybe (Path Abs File)
dotCabalCFilePath BioInput
bi.dotCabalPaths
  installVersion :: (a, b) -> b
installVersion = (a, b) -> b
forall a b. (a, b) -> b
snd
  -- Generates: -package=base -package=base16-bytestring-0.1.1.6 ...

  deps :: [String]
deps =
    [[String]] -> [String]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat
      [ case PackageName -> InstalledMap -> Maybe (InstallLocation, Installed)
forall k a. Ord k => k -> Map k a -> Maybe a
M.lookup PackageName
name BioInput
bi.installedMap of
          Just (InstallLocation
_, Stack.Types.Installed.Library PackageIdentifier
_ident InstalledLibraryInfo
installedInfo) ->
            InstalledLibraryInfo -> [String]
installedToPackageIdOpt InstalledLibraryInfo
installedInfo
          Maybe (InstallLocation, Installed)
_ -> [String
"-package=" String -> String -> String
forall a. Semigroup a => a -> a -> a
<> PackageName -> String
packageNameString PackageName
name String -> String -> String
forall a. Semigroup a => a -> a -> a
<>
            String
-> ((InstallLocation, Version) -> String)
-> Maybe (InstallLocation, Version)
-> String
forall b a. b -> (a -> b) -> Maybe a -> b
maybe String
"" -- This empty case applies to e.g. base.

              (((String
"-" <>) (String -> String) -> (Version -> String) -> Version -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Version -> String
versionString) (Version -> String)
-> ((InstallLocation, Version) -> Version)
-> (InstallLocation, Version)
-> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (InstallLocation, Version) -> Version
forall a b. (a, b) -> b
installVersion)
              (PackageName -> InstallMap -> Maybe (InstallLocation, Version)
forall k a. Ord k => k -> Map k a -> Maybe a
M.lookup PackageName
name BioInput
bi.installMap)]
      | PackageName
name <- [PackageName]
pkgs
      ]
  pkgs :: [PackageName]
pkgs =
    BioInput
bi.addPackages [PackageName] -> [PackageName] -> [PackageName]
forall a. [a] -> [a] -> [a]
++
    [ PackageName
name
    | Dependency PackageName
name VersionRange
_ NonEmptySet LibraryName
_ <- BioInput
bi.buildInfo.targetBuildDepends
      -- TODO: Cabal 3.0 introduced multiple public libraries in a single

      -- dependency

    , PackageName
name PackageName -> [PackageName] -> Bool
forall (t :: * -> *) a. (Foldable t, Eq a) => a -> t a -> Bool
`notElem` BioInput
bi.omitPackages
    ]
  PerCompilerFlavor [String]
ghcOpts [String]
_ = BioInput
bi.buildInfo.options
  extOpts :: [String]
extOpts =
       (Language -> String) -> [Language] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map ((String
"-X" ++) (String -> String) -> (Language -> String) -> Language -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Language -> String
forall a. Pretty a => a -> String
display) BioInput
bi.buildInfo.allLanguages
    [String] -> [String] -> [String]
forall a. Semigroup a => a -> a -> a
<> (Extension -> String) -> [Extension] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map ((String
"-X" ++) (String -> String) -> (Extension -> String) -> Extension -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Extension -> String
forall a. Pretty a => a -> String
display) BioInput
bi.buildInfo.usedExtensions
  srcOpts :: [String]
srcOpts =
    (Path Abs Dir -> String) -> [Path Abs Dir] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map ((String
"-i" <>) (String -> String)
-> (Path Abs Dir -> String) -> Path Abs Dir -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Path Abs Dir -> String
forall loc. Path loc Dir -> String
toFilePathNoTrailingSep)
      ([[Path Abs Dir]] -> [Path Abs Dir]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat
        [ [ Version -> NamedComponent -> Path Abs Dir -> Path Abs Dir
componentBuildDir BioInput
bi.cabalVersion BioInput
bi.componentName BioInput
bi.distDir ]
        , [ BioInput
bi.cabalDir
          | [SymbolicPath PackageDir SourceDir] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null BioInput
bi.buildInfo.hsSourceDirs
          ]
        , (SymbolicPath PackageDir SourceDir -> Maybe (Path Abs Dir))
-> [SymbolicPath PackageDir SourceDir] -> [Path Abs Dir]
forall a b. (a -> Maybe b) -> [a] -> [b]
mapMaybe
            (String -> Maybe (Path Abs Dir)
toIncludeDir (String -> Maybe (Path Abs Dir))
-> (SymbolicPath PackageDir SourceDir -> String)
-> SymbolicPath PackageDir SourceDir
-> Maybe (Path Abs Dir)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. SymbolicPath PackageDir SourceDir -> String
forall from to. SymbolicPath from to -> String
getSymbolicPath)
            BioInput
bi.buildInfo.hsSourceDirs
        , [ Path Abs Dir
componentAutogen ]
        , Maybe (Path Abs Dir) -> [Path Abs Dir]
forall a. Maybe a -> [a]
maybeToList (Version -> Path Abs Dir -> Maybe (Path Abs Dir)
packageAutogenDir BioInput
bi.cabalVersion BioInput
bi.distDir)
        , [ NamedComponent -> Path Abs Dir -> Path Abs Dir
componentOutputDir BioInput
bi.componentName BioInput
bi.distDir ]
        ]) [String] -> [String] -> [String]
forall a. [a] -> [a] -> [a]
++
    [ String
"-stubdir=" String -> String -> String
forall a. [a] -> [a] -> [a]
++ Path Abs Dir -> String
forall loc. Path loc Dir -> String
toFilePathNoTrailingSep (Path Abs Dir -> Path Abs Dir
buildDir BioInput
bi.distDir) ]
  componentAutogen :: Path Abs Dir
componentAutogen =
    Version -> NamedComponent -> Path Abs Dir -> Path Abs Dir
componentAutogenDir BioInput
bi.cabalVersion BioInput
bi.componentName BioInput
bi.distDir
  toIncludeDir :: String -> Maybe (Path Abs Dir)
toIncludeDir String
"." = Path Abs Dir -> Maybe (Path Abs Dir)
forall a. a -> Maybe a
Just BioInput
bi.cabalDir
  toIncludeDir String
relDir = Path Abs Dir -> String -> Maybe (Path Abs Dir)
forall (m :: * -> *).
MonadThrow m =>
Path Abs Dir -> String -> m (Path Abs Dir)
concatAndCollapseAbsDir BioInput
bi.cabalDir String
relDir
  includeOpts :: [String]
includeOpts =
    (String -> String) -> [String] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map (String
"-I" <>) (BioInput
bi.configIncludeDirs [String] -> [String] -> [String]
forall a. Semigroup a => a -> a -> a
<> [String]
pkgIncludeOpts)
  pkgIncludeOpts :: [String]
pkgIncludeOpts =
    [ Path Abs Dir -> String
forall loc. Path loc Dir -> String
toFilePathNoTrailingSep Path Abs Dir
absDir
    | String
dir <- BioInput
bi.buildInfo.includeDirs
    , Path Abs Dir
absDir <- String -> [Path Abs Dir]
handleDir String
dir
    ]
  libOpts :: [String]
libOpts =
    (String -> String) -> [String] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map (String
"-l" <>) BioInput
bi.buildInfo.extraLibs [String] -> [String] -> [String]
forall a. Semigroup a => a -> a -> a
<>
    (String -> String) -> [String] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map (String
"-L" <>) (BioInput
bi.configLibDirs [String] -> [String] -> [String]
forall a. Semigroup a => a -> a -> a
<> [String]
pkgLibDirs)
  pkgLibDirs :: [String]
pkgLibDirs =
    [ Path Abs Dir -> String
forall loc. Path loc Dir -> String
toFilePathNoTrailingSep Path Abs Dir
absDir
    | String
dir <- BioInput
bi.buildInfo.extraLibDirs
    , Path Abs Dir
absDir <- String -> [Path Abs Dir]
handleDir String
dir
    ]
  handleDir :: String -> [Path Abs Dir]
handleDir String
dir = case (String -> Maybe (Path Abs Dir)
forall (m :: * -> *). MonadThrow m => String -> m (Path Abs Dir)
parseAbsDir String
dir, String -> Maybe (Path Rel Dir)
forall (m :: * -> *). MonadThrow m => String -> m (Path Rel Dir)
parseRelDir String
dir) of
    (Just Path Abs Dir
ab, Maybe (Path Rel Dir)
_       ) -> [Path Abs Dir
ab]
    (Maybe (Path Abs Dir)
_      , Just Path Rel Dir
rel) -> [BioInput
bi.cabalDir Path Abs Dir -> Path Rel Dir -> Path Abs Dir
forall b t. Path b Dir -> Path Rel t -> Path b t
</> Path Rel Dir
rel]
    (Maybe (Path Abs Dir)
Nothing, Maybe (Path Rel Dir)
Nothing ) -> []
  fworks :: [String]
fworks = (String -> String) -> [String] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map (String
"-framework=" <>) BioInput
bi.buildInfo.frameworks

-- | Make the .o path from the .c file path for a component. Example:

--

-- @

-- executable FOO

--   c-sources:        cbits/text_search.c

-- @

--

-- Produces

--

-- <dist-dir>/build/FOO/FOO-tmp/cbits/text_search.o

--

-- Example:

--

-- λ> makeObjectFilePathFromC

--     $(mkAbsDir "/Users/chris/Repos/hoogle")

--     CLib

--     $(mkAbsDir "/Users/chris/Repos/hoogle/.stack-work/Cabal-x.x.x/dist")

--     $(mkAbsFile "/Users/chris/Repos/hoogle/cbits/text_search.c")

-- Just "/Users/chris/Repos/hoogle/.stack-work/Cabal-x.x.x/dist/build/cbits/text_search.o"

-- λ> makeObjectFilePathFromC

--     $(mkAbsDir "/Users/chris/Repos/hoogle")

--     (CExe "hoogle")

--     $(mkAbsDir "/Users/chris/Repos/hoogle/.stack-work/Cabal-x.x.x/dist")

--     $(mkAbsFile "/Users/chris/Repos/hoogle/cbits/text_search.c")

-- Just "/Users/chris/Repos/hoogle/.stack-work/Cabal-x.x.x/dist/build/hoogle/hoogle-tmp/cbits/text_search.o"

-- λ>

makeObjectFilePathFromC ::
     MonadThrow m
  => Path Abs Dir      -- ^ The cabal directory.

  -> NamedComponent    -- ^ The name of the component.

  -> Path Abs Dir      -- ^ Dist directory.

  -> Path Abs File     -- ^ The path to the .c file.

  -> m (Path Abs File) -- ^ The path to the .o file for the component.

makeObjectFilePathFromC :: forall (m :: * -> *).
MonadThrow m =>
Path Abs Dir
-> NamedComponent
-> Path Abs Dir
-> Path Abs File
-> m (Path Abs File)
makeObjectFilePathFromC Path Abs Dir
cabalDir NamedComponent
namedComponent Path Abs Dir
distDir Path Abs File
cFilePath = do
  Path Rel File
relCFilePath <- Path Abs Dir -> Path Abs File -> m (Path Rel File)
forall (m :: * -> *) b t.
MonadThrow m =>
Path b Dir -> Path b t -> m (Path Rel t)
stripProperPrefix Path Abs Dir
cabalDir Path Abs File
cFilePath
  Path Rel File
relOFilePath <-
    String -> m (Path Rel File)
forall (m :: * -> *). MonadThrow m => String -> m (Path Rel File)
parseRelFile (String -> String -> String
replaceExtension (Path Rel File -> String
forall b t. Path b t -> String
toFilePath Path Rel File
relCFilePath) String
"o")
  Path Abs File -> m (Path Abs File)
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (NamedComponent -> Path Abs Dir -> Path Abs Dir
componentOutputDir NamedComponent
namedComponent Path Abs Dir
distDir Path Abs Dir -> Path Rel File -> Path Abs File
forall b t. Path b Dir -> Path Rel t -> Path b t
</> Path Rel File
relOFilePath)

-- | Get all dependencies of the package (buildable targets only).

packageDependencies ::
     PackageDescription
  -> Map PackageName VersionRange
packageDependencies :: PackageDescription -> Map PackageName VersionRange
packageDependencies PackageDescription
pkg =
  (VersionRange -> VersionRange -> VersionRange)
-> [(PackageName, VersionRange)] -> Map PackageName VersionRange
forall k a. Ord k => (a -> a -> a) -> [(k, a)] -> Map k a
M.fromListWith VersionRange -> VersionRange -> VersionRange
intersectVersionRanges ([(PackageName, VersionRange)] -> Map PackageName VersionRange)
-> [(PackageName, VersionRange)] -> Map PackageName VersionRange
forall a b. (a -> b) -> a -> b
$
    (Dependency -> (PackageName, VersionRange))
-> [Dependency] -> [(PackageName, VersionRange)]
forall a b. (a -> b) -> [a] -> [b]
map (Dependency -> PackageName
depPkgName (Dependency -> PackageName)
-> (Dependency -> VersionRange)
-> Dependency
-> (PackageName, VersionRange)
forall b c c'. (b -> c) -> (b -> c') -> b -> (c, c')
forall (a :: * -> * -> *) b c c'.
Arrow a =>
a b c -> a b c' -> a b (c, c')
&&& Dependency -> VersionRange
depVerRange) ([Dependency] -> [(PackageName, VersionRange)])
-> [Dependency] -> [(PackageName, VersionRange)]
forall a b. (a -> b) -> a -> b
$
         (BuildInfo -> [Dependency]) -> [BuildInfo] -> [Dependency]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap BuildInfo -> [Dependency]
targetBuildDepends (PackageDescription -> [BuildInfo]
allBuildInfo' PackageDescription
pkg)
      [Dependency] -> [Dependency] -> [Dependency]
forall a. Semigroup a => a -> a -> a
<> [Dependency]
-> (SetupBuildInfo -> [Dependency])
-> Maybe SetupBuildInfo
-> [Dependency]
forall b a. b -> (a -> b) -> Maybe a -> b
maybe [] SetupBuildInfo -> [Dependency]
setupDepends (PackageDescription -> Maybe SetupBuildInfo
setupBuildInfo PackageDescription
pkg)

-- | Variant of 'allBuildInfo' from Cabal that, like versions before Cabal 2.2

-- only includes buildable components.

allBuildInfo' :: PackageDescription -> [BuildInfo]
allBuildInfo' :: PackageDescription -> [BuildInfo]
allBuildInfo' PackageDescription
pkg_descr = [ BuildInfo
bi | Library
lib <- PackageDescription -> [Library]
allLibraries PackageDescription
pkg_descr
                               , let bi :: BuildInfo
bi = Library -> BuildInfo
libBuildInfo Library
lib
                               , BuildInfo -> Bool
buildable BuildInfo
bi ]
                       [BuildInfo] -> [BuildInfo] -> [BuildInfo]
forall a. [a] -> [a] -> [a]
++ [ BuildInfo
bi | ForeignLib
flib <- PackageDescription -> [ForeignLib]
foreignLibs PackageDescription
pkg_descr
                               , let bi :: BuildInfo
bi = ForeignLib -> BuildInfo
foreignLibBuildInfo ForeignLib
flib
                               , BuildInfo -> Bool
buildable BuildInfo
bi ]
                       [BuildInfo] -> [BuildInfo] -> [BuildInfo]
forall a. [a] -> [a] -> [a]
++ [ BuildInfo
bi | Executable
exe <- PackageDescription -> [Executable]
executables PackageDescription
pkg_descr
                               , let bi :: BuildInfo
bi = Executable -> BuildInfo
buildInfo Executable
exe
                               , BuildInfo -> Bool
buildable BuildInfo
bi ]
                       [BuildInfo] -> [BuildInfo] -> [BuildInfo]
forall a. [a] -> [a] -> [a]
++ [ BuildInfo
bi | TestSuite
tst <- PackageDescription -> [TestSuite]
testSuites PackageDescription
pkg_descr
                               , let bi :: BuildInfo
bi = TestSuite -> BuildInfo
testBuildInfo TestSuite
tst
                               , BuildInfo -> Bool
buildable BuildInfo
bi ]
                       [BuildInfo] -> [BuildInfo] -> [BuildInfo]
forall a. [a] -> [a] -> [a]
++ [ BuildInfo
bi | Benchmark
tst <- PackageDescription -> [Benchmark]
benchmarks PackageDescription
pkg_descr
                               , let bi :: BuildInfo
bi = Benchmark -> BuildInfo
benchmarkBuildInfo Benchmark
tst
                               , BuildInfo -> Bool
buildable BuildInfo
bi ]

-- | Evaluates the conditions of a 'GenericPackageDescription', yielding

-- a resolved 'PackageDescription'.

resolvePackageDescription ::
     PackageConfig
  -> GenericPackageDescription
  -> PackageDescription
resolvePackageDescription :: PackageConfig -> GenericPackageDescription -> PackageDescription
resolvePackageDescription
    PackageConfig
packageConfig
    ( GenericPackageDescription
        PackageDescription
desc Maybe Version
_ [PackageFlag]
defaultFlags Maybe (CondTree ConfVar [Dependency] Library)
mlib [(UnqualComponentName, CondTree ConfVar [Dependency] Library)]
subLibs [(UnqualComponentName, CondTree ConfVar [Dependency] ForeignLib)]
foreignLibs' [(UnqualComponentName, CondTree ConfVar [Dependency] Executable)]
exes [(UnqualComponentName, CondTree ConfVar [Dependency] TestSuite)]
tests [(UnqualComponentName, CondTree ConfVar [Dependency] Benchmark)]
benches
    )
  = PackageDescription
desc
      { library = fmap (resolveConditions rc updateLibDeps) mlib
      , subLibraries = map
          ( \(UnqualComponentName
n, CondTree ConfVar [Dependency] Library
v) ->
              (ResolveConditions
-> (Library -> [Dependency] -> Library)
-> CondTree ConfVar [Dependency] Library
-> Library
forall target cs.
(Semigroup target, Monoid target, Show target) =>
ResolveConditions
-> (target -> cs -> target) -> CondTree ConfVar cs target -> target
resolveConditions ResolveConditions
rc Library -> [Dependency] -> Library
updateLibDeps CondTree ConfVar [Dependency] Library
v){libName = LSubLibName n}
          )
          subLibs
      , foreignLibs = map
          ( \(UnqualComponentName
n, CondTree ConfVar [Dependency] ForeignLib
v) ->
              (ResolveConditions
-> (ForeignLib -> [Dependency] -> ForeignLib)
-> CondTree ConfVar [Dependency] ForeignLib
-> ForeignLib
forall target cs.
(Semigroup target, Monoid target, Show target) =>
ResolveConditions
-> (target -> cs -> target) -> CondTree ConfVar cs target -> target
resolveConditions ResolveConditions
rc ForeignLib -> [Dependency] -> ForeignLib
updateForeignLibDeps CondTree ConfVar [Dependency] ForeignLib
v){foreignLibName = n}
          )
          foreignLibs'
      , executables = map
          ( \(UnqualComponentName
n, CondTree ConfVar [Dependency] Executable
v) -> (ResolveConditions
-> (Executable -> [Dependency] -> Executable)
-> CondTree ConfVar [Dependency] Executable
-> Executable
forall target cs.
(Semigroup target, Monoid target, Show target) =>
ResolveConditions
-> (target -> cs -> target) -> CondTree ConfVar cs target -> target
resolveConditions ResolveConditions
rc Executable -> [Dependency] -> Executable
updateExeDeps CondTree ConfVar [Dependency] Executable
v){exeName = n} )
          exes
      , testSuites = map
          ( \(UnqualComponentName
n, CondTree ConfVar [Dependency] TestSuite
v) ->
              (ResolveConditions
-> (TestSuite -> [Dependency] -> TestSuite)
-> CondTree ConfVar [Dependency] TestSuite
-> TestSuite
forall target cs.
(Semigroup target, Monoid target, Show target) =>
ResolveConditions
-> (target -> cs -> target) -> CondTree ConfVar cs target -> target
resolveConditions ResolveConditions
rc TestSuite -> [Dependency] -> TestSuite
updateTestDeps CondTree ConfVar [Dependency] TestSuite
v){testName = n}
          )
          tests
      , benchmarks = map
          ( \(UnqualComponentName
n, CondTree ConfVar [Dependency] Benchmark
v) ->
              (ResolveConditions
-> (Benchmark -> [Dependency] -> Benchmark)
-> CondTree ConfVar [Dependency] Benchmark
-> Benchmark
forall target cs.
(Semigroup target, Monoid target, Show target) =>
ResolveConditions
-> (target -> cs -> target) -> CondTree ConfVar cs target -> target
resolveConditions ResolveConditions
rc Benchmark -> [Dependency] -> Benchmark
updateBenchmarkDeps CondTree ConfVar [Dependency] Benchmark
v){benchmarkName = n}
          )
          benches
      }
 where
  flags :: Map FlagName Bool
flags = Map FlagName Bool -> Map FlagName Bool -> Map FlagName Bool
forall k a. Ord k => Map k a -> Map k a -> Map k a
M.union PackageConfig
packageConfig.flags ([PackageFlag] -> Map FlagName Bool
flagMap [PackageFlag]
defaultFlags)
  rc :: ResolveConditions
rc = ActualCompiler
-> Platform -> Map FlagName Bool -> ResolveConditions
mkResolveConditions
         PackageConfig
packageConfig.compilerVersion
         PackageConfig
packageConfig.platform
         Map FlagName Bool
flags
  updateLibDeps :: Library -> [Dependency] -> Library
updateLibDeps Library
lib [Dependency]
deps = Library
lib
    { libBuildInfo = (libBuildInfo lib) {targetBuildDepends = deps} }
  updateForeignLibDeps :: ForeignLib -> [Dependency] -> ForeignLib
updateForeignLibDeps ForeignLib
lib [Dependency]
deps = ForeignLib
lib
    { foreignLibBuildInfo =
        (foreignLibBuildInfo lib) {targetBuildDepends = deps}
    }
  updateExeDeps :: Executable -> [Dependency] -> Executable
updateExeDeps Executable
exe [Dependency]
deps = Executable
exe
    { Executable.buildInfo = (buildInfo exe) {targetBuildDepends = deps} }
  updateTestDeps :: TestSuite -> [Dependency] -> TestSuite
updateTestDeps TestSuite
test [Dependency]
deps = TestSuite
test
    { testBuildInfo = (testBuildInfo test) {targetBuildDepends = deps} }
  updateBenchmarkDeps :: Benchmark -> [Dependency] -> Benchmark
updateBenchmarkDeps Benchmark
bench [Dependency]
deps = Benchmark
bench
    { benchmarkBuildInfo =
        (benchmarkBuildInfo bench) {targetBuildDepends = deps}
    }

-- | Make a map from a list of flag specifications.

--

-- What is @flagManual@ for?

flagMap :: [PackageFlag] -> Map FlagName Bool
flagMap :: [PackageFlag] -> Map FlagName Bool
flagMap = [(FlagName, Bool)] -> Map FlagName Bool
forall k a. Ord k => [(k, a)] -> Map k a
M.fromList ([(FlagName, Bool)] -> Map FlagName Bool)
-> ([PackageFlag] -> [(FlagName, Bool)])
-> [PackageFlag]
-> Map FlagName Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (PackageFlag -> (FlagName, Bool))
-> [PackageFlag] -> [(FlagName, Bool)]
forall a b. (a -> b) -> [a] -> [b]
map PackageFlag -> (FlagName, Bool)
pair
 where
  pair :: PackageFlag -> (FlagName, Bool)
  pair :: PackageFlag -> (FlagName, Bool)
pair = PackageFlag -> FlagName
flagName (PackageFlag -> FlagName)
-> (PackageFlag -> Bool) -> PackageFlag -> (FlagName, Bool)
forall b c c'. (b -> c) -> (b -> c') -> b -> (c, c')
forall (a :: * -> * -> *) b c c'.
Arrow a =>
a b c -> a b c' -> a b (c, c')
&&& PackageFlag -> Bool
flagDefault

data ResolveConditions = ResolveConditions
  { ResolveConditions -> Map FlagName Bool
flags :: Map FlagName Bool
  , ResolveConditions -> ActualCompiler
compilerVersion :: ActualCompiler
  , ResolveConditions -> OS
os :: OS
  , ResolveConditions -> Arch
arch :: Arch
  }

-- | Generic a @ResolveConditions@ using sensible defaults.

mkResolveConditions ::
     ActualCompiler -- ^ Compiler version

  -> Platform -- ^ installation target platform

  -> Map FlagName Bool -- ^ enabled flags

  -> ResolveConditions
mkResolveConditions :: ActualCompiler
-> Platform -> Map FlagName Bool -> ResolveConditions
mkResolveConditions ActualCompiler
compilerVersion (Platform Arch
arch OS
os) Map FlagName Bool
flags = ResolveConditions
  { Map FlagName Bool
$sel:flags:ResolveConditions :: Map FlagName Bool
flags :: Map FlagName Bool
flags
  , ActualCompiler
$sel:compilerVersion:ResolveConditions :: ActualCompiler
compilerVersion :: ActualCompiler
compilerVersion
  , OS
$sel:os:ResolveConditions :: OS
os :: OS
os
  , Arch
$sel:arch:ResolveConditions :: Arch
arch :: Arch
arch
  }

-- | Resolve the condition tree for the library.

resolveConditions ::
     (Semigroup target, Monoid target, Show target)
  => ResolveConditions
  -> (target -> cs -> target)
  -> CondTree ConfVar cs target
  -> target
resolveConditions :: forall target cs.
(Semigroup target, Monoid target, Show target) =>
ResolveConditions
-> (target -> cs -> target) -> CondTree ConfVar cs target -> target
resolveConditions ResolveConditions
rc target -> cs -> target
addDeps (CondNode target
lib cs
deps [CondBranch ConfVar cs target]
cs) = target
basic target -> target -> target
forall a. Semigroup a => a -> a -> a
<> target
children
 where
  basic :: target
basic = target -> cs -> target
addDeps target
lib cs
deps
  children :: target
children = [target] -> target
forall a. Monoid a => [a] -> a
mconcat ((CondBranch ConfVar cs target -> target)
-> [CondBranch ConfVar cs target] -> [target]
forall a b. (a -> b) -> [a] -> [b]
map CondBranch ConfVar cs target -> target
apply [CondBranch ConfVar cs target]
cs)
   where
    apply :: CondBranch ConfVar cs target -> target
apply (Cabal.CondBranch Condition ConfVar
cond CondTree ConfVar cs target
node Maybe (CondTree ConfVar cs target)
mcs) =
      if Condition ConfVar -> Bool
condSatisfied Condition ConfVar
cond
         then ResolveConditions
-> (target -> cs -> target) -> CondTree ConfVar cs target -> target
forall target cs.
(Semigroup target, Monoid target, Show target) =>
ResolveConditions
-> (target -> cs -> target) -> CondTree ConfVar cs target -> target
resolveConditions ResolveConditions
rc target -> cs -> target
addDeps CondTree ConfVar cs target
node
         else target
-> (CondTree ConfVar cs target -> target)
-> Maybe (CondTree ConfVar cs target)
-> target
forall b a. b -> (a -> b) -> Maybe a -> b
maybe target
forall a. Monoid a => a
mempty (ResolveConditions
-> (target -> cs -> target) -> CondTree ConfVar cs target -> target
forall target cs.
(Semigroup target, Monoid target, Show target) =>
ResolveConditions
-> (target -> cs -> target) -> CondTree ConfVar cs target -> target
resolveConditions ResolveConditions
rc target -> cs -> target
addDeps) Maybe (CondTree ConfVar cs target)
mcs
    condSatisfied :: Condition ConfVar -> Bool
condSatisfied Condition ConfVar
c =
      case Condition ConfVar
c of
        Var ConfVar
v -> ConfVar -> Bool
varSatisfied ConfVar
v
        Lit Bool
b -> Bool
b
        CNot Condition ConfVar
c' -> Bool -> Bool
not (Condition ConfVar -> Bool
condSatisfied Condition ConfVar
c')
        COr Condition ConfVar
cx Condition ConfVar
cy -> Condition ConfVar -> Bool
condSatisfied Condition ConfVar
cx Bool -> Bool -> Bool
|| Condition ConfVar -> Bool
condSatisfied Condition ConfVar
cy
        CAnd Condition ConfVar
cx Condition ConfVar
cy -> Condition ConfVar -> Bool
condSatisfied Condition ConfVar
cx Bool -> Bool -> Bool
&& Condition ConfVar -> Bool
condSatisfied Condition ConfVar
cy
    varSatisfied :: ConfVar -> Bool
varSatisfied ConfVar
v =
      case ConfVar
v of
        OS OS
os -> OS
os OS -> OS -> Bool
forall a. Eq a => a -> a -> Bool
== ResolveConditions
rc.os
        Arch Arch
arch -> Arch
arch Arch -> Arch -> Bool
forall a. Eq a => a -> a -> Bool
== ResolveConditions
rc.arch
        PackageFlag FlagName
flag -> Bool -> Maybe Bool -> Bool
forall a. a -> Maybe a -> a
fromMaybe Bool
False (Maybe Bool -> Bool) -> Maybe Bool -> Bool
forall a b. (a -> b) -> a -> b
$ FlagName -> Map FlagName Bool -> Maybe Bool
forall k a. Ord k => k -> Map k a -> Maybe a
M.lookup FlagName
flag ResolveConditions
rc.flags
        -- NOTE:  ^^^^^ This should never happen, as all flags which are used

        -- must be declared. Defaulting to False.

        Impl CompilerFlavor
flavor VersionRange
range ->
          case (CompilerFlavor
flavor, ResolveConditions
rc.compilerVersion) of
            (CompilerFlavor
GHC, ACGhc Version
vghc) -> Version
vghc Version -> VersionRange -> Bool
`withinRange` VersionRange
range
            (CompilerFlavor, ActualCompiler)
_ -> Bool
False

-- | Path for the package's build log.

buildLogPath ::
     (MonadReader env m, HasBuildConfig env, MonadThrow m)
  => Package
  -> Maybe String
  -> m (Path Abs File)
buildLogPath :: forall env (m :: * -> *).
(MonadReader env m, HasBuildConfig env, MonadThrow m) =>
Package -> Maybe String -> m (Path Abs File)
buildLogPath Package
package' Maybe String
msuffix = do
  env
env <- m env
forall r (m :: * -> *). MonadReader r m => m r
ask
  let stack :: Path Abs Dir
stack = env -> Path Abs Dir
forall env (m :: * -> *).
(HasBuildConfig env, MonadReader env m) =>
m (Path Abs Dir)
getProjectWorkDir env
env
  Path Rel File
fp <- String -> m (Path Rel File)
forall (m :: * -> *). MonadThrow m => String -> m (Path Rel File)
parseRelFile (String -> m (Path Rel File)) -> String -> m (Path Rel File)
forall a b. (a -> b) -> a -> b
$ [String] -> String
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat ([String] -> String) -> [String] -> String
forall a b. (a -> b) -> a -> b
$
    PackageIdentifier -> String
packageIdentifierString (Package -> PackageIdentifier
packageIdentifier Package
package') String -> [String] -> [String]
forall a. a -> [a] -> [a]
:
    ([String] -> [String])
-> (String -> [String] -> [String])
-> Maybe String
-> [String]
-> [String]
forall b a. b -> (a -> b) -> Maybe a -> b
maybe [String] -> [String]
forall a. a -> a
id (\String
suffix -> (String
"-" :) ([String] -> [String])
-> ([String] -> [String]) -> [String] -> [String]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (String
suffix :)) Maybe String
msuffix [String
".log"]
  Path Abs File -> m (Path Abs File)
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Path Abs File -> m (Path Abs File))
-> Path Abs File -> m (Path Abs File)
forall a b. (a -> b) -> a -> b
$ Path Abs Dir
stack Path Abs Dir -> Path Rel File -> Path Abs File
forall b t. Path b Dir -> Path Rel t -> Path b t
</> Path Rel Dir
relDirLogs Path Rel Dir -> Path Rel File -> Path Rel File
forall b t. Path b Dir -> Path Rel t -> Path b t
</> Path Rel File
fp

    {- FIXME
-- | Create a 'ProjectPackage' from a directory containing a package.
mkProjectPackage
  :: forall env. (HasPantryConfig env, HasLogFunc env, HasProcessContext env)
  => PrintWarnings
  -> ResolvedPath Dir
  -> RIO env ProjectPackage
mkProjectPackage printWarnings dir = do
  (gpd, name, cabalfp) <- loadCabalFilePath (resolvedAbsolute dir)
  pure ProjectPackage
    { ppCabalFP = cabalfp
    , ppGPD' = gpd printWarnings
    , ppResolvedDir = dir
    , ppName = name
    }

-- | Create a 'DepPackage' from a 'PackageLocation'
mkDepPackage
  :: forall env. (HasPantryConfig env, HasLogFunc env, HasProcessContext env)
  => PackageLocation
  -> RIO env DepPackage
mkDepPackage pl = do
  (name, gpdio) <-
    case pl of
      PLMutable dir -> do
        (gpdio, name, _cabalfp) <- loadCabalFilePath (resolvedAbsolute dir)
        pure (name, gpdio NoPrintWarnings)
      PLImmutable pli -> do
        PackageIdentifier name _ <- getPackageLocationIdent pli
        run <- askRunInIO
        pure (name, run $ loadCabalFileImmutable pli)
  pure DepPackage
    { dpGPD' = gpdio
    , dpLocation = pl
    , dpName = name
    }

    -}

-- | Force a package to be treated as a custom build type, see

-- <https://github.com/commercialhaskell/stack/issues/4488>

applyForceCustomBuild ::
     Version -- ^ global Cabal version

  -> Package
  -> Package
applyForceCustomBuild :: Version -> Package -> Package
applyForceCustomBuild Version
cabalVersion Package
package
  | Bool
forceCustomBuild =
      Package
package
        { buildType = Custom
        , setupDeps = Just $ M.fromList
            [ ("Cabal", libraryDepFromVersionRange cabalVersionRange)
            , ("base", libraryDepFromVersionRange anyVersion)
            ]
        }
  | Bool
otherwise = Package
package
 where
  cabalVersionRange :: VersionRange
cabalVersionRange =
    Version -> VersionRange
orLaterVersion (Version -> VersionRange) -> Version -> VersionRange
forall a b. (a -> b) -> a -> b
$ [Int] -> Version
mkVersion ([Int] -> Version) -> [Int] -> Version
forall a b. (a -> b) -> a -> b
$ CabalSpecVersion -> [Int]
cabalSpecToVersionDigits
      Package
package.cabalSpec
  forceCustomBuild :: Bool
forceCustomBuild = Package
package.buildType BuildType -> BuildType -> Bool
forall a. Eq a => a -> a -> Bool
== BuildType
Simple
    Bool -> Bool -> Bool
&& Bool -> Bool
not (Version
cabalVersion Version -> VersionRange -> Bool
`withinRange` VersionRange
cabalVersionRange)

-- | Check if the package has a main library that is buildable.

hasBuildableMainLibrary :: Package -> Bool
hasBuildableMainLibrary :: Package -> Bool
hasBuildableMainLibrary Package
package =
  Bool -> (StackLibrary -> Bool) -> Maybe StackLibrary -> Bool
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Bool
False StackLibrary -> Bool
forall component. HasBuildInfo component => component -> Bool
isComponentBuildable Package
package.library

-- | Check if the main library has any exposed modules.

--

-- This should become irrelevant at some point since there's nothing inherently

-- wrong or different with packages exposing only modules in internal libraries

-- (for instance).

mainLibraryHasExposedModules :: Package -> Bool
mainLibraryHasExposedModules :: Package -> Bool
mainLibraryHasExposedModules Package
package =
  Bool -> (StackLibrary -> Bool) -> Maybe StackLibrary -> Bool
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Bool
False (Bool -> Bool
not (Bool -> Bool) -> (StackLibrary -> Bool) -> StackLibrary -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [ModuleName] -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null ([ModuleName] -> Bool)
-> (StackLibrary -> [ModuleName]) -> StackLibrary -> Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (.exposedModules)) Package
package.library

-- | Aggregate all unknown tools from all components. Mostly meant for

-- build tools specified in the legacy manner (build-tools:) that failed the

-- hard-coded lookup. See 'Stack.Types.Component.unknownTools' for more

-- information.

packageUnknownTools :: Package -> Set Text
packageUnknownTools :: Package -> Set Text
packageUnknownTools Package
pkg = Set Text -> Set Text
lib (Set Text
bench Set Text -> Set Text -> Set Text
forall a. Semigroup a => a -> a -> a
<> Set Text
tests Set Text -> Set Text -> Set Text
forall a. Semigroup a => a -> a -> a
<> Set Text
flib Set Text -> Set Text -> Set Text
forall a. Semigroup a => a -> a -> a
<> Set Text
sublib Set Text -> Set Text -> Set Text
forall a. Semigroup a => a -> a -> a
<> Set Text
exe)
 where
  lib :: Set Text -> Set Text
lib Set Text
setT = case Package
pkg.library of
    Just StackLibrary
libV -> StackLibrary -> Set Text -> Set Text
forall x. HasBuildInfo x => x -> Set Text -> Set Text
addUnknownTools StackLibrary
libV Set Text
setT
    Maybe StackLibrary
Nothing -> Set Text
setT
  bench :: Set Text
bench = CompCollection StackBenchmark -> Set Text
forall x. HasBuildInfo x => CompCollection x -> Set Text
gatherUnknownTools Package
pkg.benchmarks
  tests :: Set Text
tests = CompCollection StackTestSuite -> Set Text
forall x. HasBuildInfo x => CompCollection x -> Set Text
gatherUnknownTools Package
pkg.testSuites
  flib :: Set Text
flib = CompCollection StackForeignLibrary -> Set Text
forall x. HasBuildInfo x => CompCollection x -> Set Text
gatherUnknownTools Package
pkg.foreignLibraries
  sublib :: Set Text
sublib = CompCollection StackLibrary -> Set Text
forall x. HasBuildInfo x => CompCollection x -> Set Text
gatherUnknownTools Package
pkg.subLibraries
  exe :: Set Text
exe = CompCollection StackExecutable -> Set Text
forall x. HasBuildInfo x => CompCollection x -> Set Text
gatherUnknownTools Package
pkg.executables
  addUnknownTools :: HasBuildInfo x => x -> Set Text -> Set Text
  addUnknownTools :: forall x. HasBuildInfo x => x -> Set Text -> Set Text
addUnknownTools = Set Text -> Set Text -> Set Text
forall a. Semigroup a => a -> a -> a
(<>) (Set Text -> Set Text -> Set Text)
-> (x -> Set Text) -> x -> Set Text -> Set Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (.buildInfo.unknownTools)
  gatherUnknownTools :: HasBuildInfo x => CompCollection x -> Set Text
  gatherUnknownTools :: forall x. HasBuildInfo x => CompCollection x -> Set Text
gatherUnknownTools = (x -> Set Text -> Set Text)
-> Set Text -> CompCollection x -> Set Text
forall a b. (a -> b -> b) -> b -> CompCollection a -> b
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr' x -> Set Text -> Set Text
forall x. HasBuildInfo x => x -> Set Text -> Set Text
addUnknownTools Set Text
forall a. Monoid a => a
mempty

buildableForeignLibs :: Package -> Set Text
buildableForeignLibs :: Package -> Set Text
buildableForeignLibs Package
pkg = CompCollection StackForeignLibrary -> Set Text
forall component. CompCollection component -> Set Text
getBuildableSetText Package
pkg.foreignLibraries

buildableSubLibs :: Package -> Set Text
buildableSubLibs :: Package -> Set Text
buildableSubLibs Package
pkg = CompCollection StackLibrary -> Set Text
forall component. CompCollection component -> Set Text
getBuildableSetText Package
pkg.subLibraries

buildableExes :: Package -> Set Text
buildableExes :: Package -> Set Text
buildableExes Package
pkg = CompCollection StackExecutable -> Set Text
forall component. CompCollection component -> Set Text
getBuildableSetText Package
pkg.executables

buildableTestSuites :: Package -> Set Text
buildableTestSuites :: Package -> Set Text
buildableTestSuites Package
pkg = CompCollection StackTestSuite -> Set Text
forall component. CompCollection component -> Set Text
getBuildableSetText Package
pkg.testSuites

buildableBenchmarks :: Package -> Set Text
buildableBenchmarks :: Package -> Set Text
buildableBenchmarks Package
pkg = CompCollection StackBenchmark -> Set Text
forall component. CompCollection component -> Set Text
getBuildableSetText Package
pkg.benchmarks

-- | Apply a generic processing function in a Monad over all of the Package's

-- components.

processPackageComponent ::
     forall m a. (Monad m)
  => Package
  -> (forall component. HasComponentInfo component => component -> m a -> m a)
     -- ^ Processing function with all the component's info.

  -> m a
     -- ^ Initial value.

  -> m a
processPackageComponent :: forall (m :: * -> *) a.
Monad m =>
Package
-> (forall component.
    HasComponentInfo component =>
    component -> m a -> m a)
-> m a
-> m a
processPackageComponent Package
pkg forall component.
HasComponentInfo component =>
component -> m a -> m a
componentFn = do
  let componentKindProcessor ::
           forall component. HasComponentInfo component
        => (Package -> CompCollection component)
        -> m a
        -> m a
      componentKindProcessor :: forall component.
HasComponentInfo component =>
(Package -> CompCollection component) -> m a -> m a
componentKindProcessor Package -> CompCollection component
target =
        CompCollection component -> (component -> m a -> m a) -> m a -> m a
forall (m :: * -> *) component a.
Monad m =>
CompCollection component -> (component -> m a -> m a) -> m a -> m a
foldComponentToAnotherCollection
          (Package -> CompCollection component
target Package
pkg)
          component -> m a -> m a
forall component.
HasComponentInfo component =>
component -> m a -> m a
componentFn
      processMainLib :: m a -> m a
processMainLib = (m a -> m a)
-> (StackLibrary -> m a -> m a) -> Maybe StackLibrary -> m a -> m a
forall b a. b -> (a -> b) -> Maybe a -> b
maybe m a -> m a
forall a. a -> a
id StackLibrary -> m a -> m a
forall component.
HasComponentInfo component =>
component -> m a -> m a
componentFn Package
pkg.library
      processAllComp :: m a -> m a
processAllComp =
        ( if Package
pkg.benchmarkEnabled
            then (Package -> CompCollection StackBenchmark) -> m a -> m a
forall component.
HasComponentInfo component =>
(Package -> CompCollection component) -> m a -> m a
componentKindProcessor (.benchmarks)
            else m a -> m a
forall a. a -> a
id
        )
        (m a -> m a) -> (m a -> m a) -> m a -> m a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ( if Package
pkg.testEnabled
              then (Package -> CompCollection StackTestSuite) -> m a -> m a
forall component.
HasComponentInfo component =>
(Package -> CompCollection component) -> m a -> m a
componentKindProcessor (.testSuites)
              else m a -> m a
forall a. a -> a
id
          )
        (m a -> m a) -> (m a -> m a) -> m a -> m a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Package -> CompCollection StackForeignLibrary) -> m a -> m a
forall component.
HasComponentInfo component =>
(Package -> CompCollection component) -> m a -> m a
componentKindProcessor (.foreignLibraries)
        (m a -> m a) -> (m a -> m a) -> m a -> m a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Package -> CompCollection StackExecutable) -> m a -> m a
forall component.
HasComponentInfo component =>
(Package -> CompCollection component) -> m a -> m a
componentKindProcessor (.executables)
        (m a -> m a) -> (m a -> m a) -> m a -> m a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Package -> CompCollection StackLibrary) -> m a -> m a
forall component.
HasComponentInfo component =>
(Package -> CompCollection component) -> m a -> m a
componentKindProcessor (.subLibraries)
        (m a -> m a) -> (m a -> m a) -> m a -> m a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. m a -> m a
processMainLib
  m a -> m a
processAllComp

-- | This is a function to iterate in a monad over all of a package's

-- dependencies, and yield a collection of results (used with list and set).

processPackageMapDeps ::
     (Monad m)
  => Package
  -> (Map PackageName DepValue -> m a -> m a)
  -> m a
  -> m a
processPackageMapDeps :: forall (m :: * -> *) a.
Monad m =>
Package -> (Map PackageName DepValue -> m a -> m a) -> m a -> m a
processPackageMapDeps Package
pkg Map PackageName DepValue -> m a -> m a
fn = do
  let packageSetupDepsProcessor :: m a -> m a
packageSetupDepsProcessor m a
resAction = case Package
pkg.setupDeps of
        Maybe (Map PackageName DepValue)
Nothing -> m a
resAction
        Just Map PackageName DepValue
v -> Map PackageName DepValue -> m a -> m a
fn Map PackageName DepValue
v m a
resAction
      processAllComp :: m a -> m a
processAllComp = Package
-> (forall component.
    HasComponentInfo component =>
    component -> m a -> m a)
-> m a
-> m a
forall (m :: * -> *) a.
Monad m =>
Package
-> (forall component.
    HasComponentInfo component =>
    component -> m a -> m a)
-> m a
-> m a
processPackageComponent Package
pkg (Map PackageName DepValue -> m a -> m a
fn (Map PackageName DepValue -> m a -> m a)
-> (component -> Map PackageName DepValue)
-> component
-> m a
-> m a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. component -> Map PackageName DepValue
forall r1 r2 a.
(HasField "buildInfo" r1 r2, HasField "dependency" r2 a) =>
r1 -> a
componentDependencyMap)
        (m a -> m a) -> (m a -> m a) -> m a -> m a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. m a -> m a
packageSetupDepsProcessor
  m a -> m a
processAllComp

-- | This is a function to iterate in a monad over all of a package component's

-- dependencies, and yield a collection of results.

processPackageDeps ::
     (Monad m, Monoid (targetedCollection resT))
  => Package
  -> (resT -> targetedCollection resT -> targetedCollection resT)
  -> (PackageName -> DepValue -> m resT)
  -> m (targetedCollection resT)
  -> m (targetedCollection resT)
processPackageDeps :: forall (m :: * -> *) (targetedCollection :: * -> *) resT.
(Monad m, Monoid (targetedCollection resT)) =>
Package
-> (resT -> targetedCollection resT -> targetedCollection resT)
-> (PackageName -> DepValue -> m resT)
-> m (targetedCollection resT)
-> m (targetedCollection resT)
processPackageDeps Package
pkg resT -> targetedCollection resT -> targetedCollection resT
combineResults PackageName -> DepValue -> m resT
fn = do
  let asPackageNameSet :: (Package -> CompCollection component) -> Set PackageName
asPackageNameSet Package -> CompCollection component
accessor =
        (Text -> PackageName) -> Set Text -> Set PackageName
forall b a. Ord b => (a -> b) -> Set a -> Set b
S.map (String -> PackageName
mkPackageName (String -> PackageName) -> (Text -> String) -> Text -> PackageName
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> String
T.unpack) (Set Text -> Set PackageName) -> Set Text -> Set PackageName
forall a b. (a -> b) -> a -> b
$ CompCollection component -> Set Text
forall component. CompCollection component -> Set Text
getBuildableSetText (CompCollection component -> Set Text)
-> CompCollection component -> Set Text
forall a b. (a -> b) -> a -> b
$ Package -> CompCollection component
accessor Package
pkg
      (!Set PackageName
subLibNames, !Set PackageName
foreignLibNames) =
        ( (Package -> CompCollection StackLibrary) -> Set PackageName
forall {component}.
(Package -> CompCollection component) -> Set PackageName
asPackageNameSet (.subLibraries)
        , (Package -> CompCollection StackForeignLibrary) -> Set PackageName
forall {component}.
(Package -> CompCollection component) -> Set PackageName
asPackageNameSet (.foreignLibraries)
        )
      shouldIgnoreDep :: PackageName -> Bool
shouldIgnoreDep (PackageName
packageNameV :: PackageName)
        | PackageName
packageNameV PackageName -> PackageName -> Bool
forall a. Eq a => a -> a -> Bool
== Package
pkg.name = Bool
True
        | PackageName
packageNameV PackageName -> Set PackageName -> Bool
forall a. Ord a => a -> Set a -> Bool
`S.member` Set PackageName
subLibNames = Bool
True
        | PackageName
packageNameV PackageName -> Set PackageName -> Bool
forall a. Ord a => a -> Set a -> Bool
`S.member` Set PackageName
foreignLibNames = Bool
True
        | Bool
otherwise = Bool
False
      innerIterator :: PackageName
-> DepValue
-> m (targetedCollection resT)
-> m (targetedCollection resT)
innerIterator PackageName
packageName DepValue
depValue m (targetedCollection resT)
resListInMonad
        | PackageName -> Bool
shouldIgnoreDep PackageName
packageName = m (targetedCollection resT)
resListInMonad
        | Bool
otherwise = do
            targetedCollection resT
resList <- m (targetedCollection resT)
resListInMonad
            resT
newResElement <- PackageName -> DepValue -> m resT
fn PackageName
packageName DepValue
depValue
            targetedCollection resT -> m (targetedCollection resT)
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure (targetedCollection resT -> m (targetedCollection resT))
-> targetedCollection resT -> m (targetedCollection resT)
forall a b. (a -> b) -> a -> b
$ resT -> targetedCollection resT -> targetedCollection resT
combineResults resT
newResElement targetedCollection resT
resList
  Package
-> (Map PackageName DepValue
    -> m (targetedCollection resT) -> m (targetedCollection resT))
-> m (targetedCollection resT)
-> m (targetedCollection resT)
forall (m :: * -> *) a.
Monad m =>
Package -> (Map PackageName DepValue -> m a -> m a) -> m a -> m a
processPackageMapDeps Package
pkg ((m (targetedCollection resT)
 -> Map PackageName DepValue -> m (targetedCollection resT))
-> Map PackageName DepValue
-> m (targetedCollection resT)
-> m (targetedCollection resT)
forall a b c. (a -> b -> c) -> b -> a -> c
flip ((PackageName
 -> DepValue
 -> m (targetedCollection resT)
 -> m (targetedCollection resT))
-> m (targetedCollection resT)
-> Map PackageName DepValue
-> m (targetedCollection resT)
forall k a b. (k -> a -> b -> b) -> b -> Map k a -> b
M.foldrWithKey' PackageName
-> DepValue
-> m (targetedCollection resT)
-> m (targetedCollection resT)
innerIterator))

-- | Iterate/fold on all the package dependencies, components, setup deps and

-- all.

processPackageDepsToList ::
     Monad m
  => Package
  -> (PackageName -> DepValue -> m resT)
  -> m [resT]
processPackageDepsToList :: forall (m :: * -> *) resT.
Monad m =>
Package -> (PackageName -> DepValue -> m resT) -> m [resT]
processPackageDepsToList Package
pkg PackageName -> DepValue -> m resT
fn = Package
-> (resT -> [resT] -> [resT])
-> (PackageName -> DepValue -> m resT)
-> m [resT]
-> m [resT]
forall (m :: * -> *) (targetedCollection :: * -> *) resT.
(Monad m, Monoid (targetedCollection resT)) =>
Package
-> (resT -> targetedCollection resT -> targetedCollection resT)
-> (PackageName -> DepValue -> m resT)
-> m (targetedCollection resT)
-> m (targetedCollection resT)
processPackageDeps Package
pkg (:) PackageName -> DepValue -> m resT
fn ([resT] -> m [resT]
forall a. a -> m a
forall (f :: * -> *) a. Applicative f => a -> f a
pure [])

-- | List all package's dependencies in a "free" context through the identity

-- monad.

listOfPackageDeps :: Package -> [PackageName]
listOfPackageDeps :: Package -> [PackageName]
listOfPackageDeps Package
pkg =
  Identity [PackageName] -> [PackageName]
forall a. Identity a -> a
runIdentity (Identity [PackageName] -> [PackageName])
-> Identity [PackageName] -> [PackageName]
forall a b. (a -> b) -> a -> b
$ Package
-> (PackageName -> DepValue -> Identity PackageName)
-> Identity [PackageName]
forall (m :: * -> *) resT.
Monad m =>
Package -> (PackageName -> DepValue -> m resT) -> m [resT]
processPackageDepsToList Package
pkg (\PackageName
pn DepValue
_ -> PackageName -> Identity PackageName
forall a. a -> Identity a
forall (f :: * -> *) a. Applicative f => a -> f a
pure PackageName
pn)

-- | The set of package's dependencies.

setOfPackageDeps :: Package -> Set PackageName
setOfPackageDeps :: Package -> Set PackageName
setOfPackageDeps Package
pkg =
  Identity (Set PackageName) -> Set PackageName
forall a. Identity a -> a
runIdentity (Identity (Set PackageName) -> Set PackageName)
-> Identity (Set PackageName) -> Set PackageName
forall a b. (a -> b) -> a -> b
$ Package
-> (PackageName -> Set PackageName -> Set PackageName)
-> (PackageName -> DepValue -> Identity PackageName)
-> Identity (Set PackageName)
-> Identity (Set PackageName)
forall (m :: * -> *) (targetedCollection :: * -> *) resT.
(Monad m, Monoid (targetedCollection resT)) =>
Package
-> (resT -> targetedCollection resT -> targetedCollection resT)
-> (PackageName -> DepValue -> m resT)
-> m (targetedCollection resT)
-> m (targetedCollection resT)
processPackageDeps Package
pkg PackageName -> Set PackageName -> Set PackageName
forall a. Ord a => a -> Set a -> Set a
S.insert (\PackageName
pn DepValue
_ -> PackageName -> Identity PackageName
forall a. a -> Identity a
forall (f :: * -> *) a. Applicative f => a -> f a
pure PackageName
pn) (Set PackageName -> Identity (Set PackageName)
forall a. a -> Identity a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Set PackageName
forall a. Monoid a => a
mempty)

-- | This implements a topological sort on all targeted components for the build

-- and their dependencies. It's only targeting internal dependencies, so it's doing

-- a topological sort on a subset of a package's components.

--

-- Note that in Cabal they use the Data.Graph struct to pursue the same goal. But dong this here

-- would require a large number intermediate data structure.

-- This is needed because we need to get the right GhcPkgId of the relevant internal dependencies

-- of a component before building it as a component.

topSortPackageComponent ::
     Package
  -> Target
  -> Bool
   -- ^ Include directTarget or not. False here means we won't

   -- include the actual targets in the result, only their deps.

   -- Using it with False here only in GHCi

  -> Seq NamedComponent
topSortPackageComponent :: Package -> Target -> Bool -> Seq NamedComponent
topSortPackageComponent Package
package Target
target Bool
includeDirectTarget = (forall s. ST s (Seq NamedComponent)) -> Seq NamedComponent
forall a. (forall s. ST s a) -> a
runST ((forall s. ST s (Seq NamedComponent)) -> Seq NamedComponent)
-> (forall s. ST s (Seq NamedComponent)) -> Seq NamedComponent
forall a b. (a -> b) -> a -> b
$ do
  STRef s (Set NamedComponent)
alreadyProcessedRef <- Set NamedComponent -> ST s (STRef s (Set NamedComponent))
forall a s. a -> ST s (STRef s a)
newSTRef (Set NamedComponent
forall a. Monoid a => a
mempty :: Set NamedComponent)
  let processInitialComponents :: component -> ST s (Seq NamedComponent) -> ST s (Seq NamedComponent)
processInitialComponents component
c = case Target
target of
        TargetAll{} -> Bool
-> STRef s (Set NamedComponent)
-> component
-> ST s (Seq NamedComponent)
-> ST s (Seq NamedComponent)
forall s component.
HasComponentInfo component =>
Bool
-> STRef s (Set NamedComponent)
-> component
-> ST s (Seq NamedComponent)
-> ST s (Seq NamedComponent)
processComponent Bool
includeDirectTarget STRef s (Set NamedComponent)
alreadyProcessedRef component
c
        TargetComps Set NamedComponent
targetSet -> if NamedComponent -> Set NamedComponent -> Bool
forall a. Ord a => a -> Set a -> Bool
S.member component
c.qualifiedName Set NamedComponent
targetSet
          then Bool
-> STRef s (Set NamedComponent)
-> component
-> ST s (Seq NamedComponent)
-> ST s (Seq NamedComponent)
forall s component.
HasComponentInfo component =>
Bool
-> STRef s (Set NamedComponent)
-> component
-> ST s (Seq NamedComponent)
-> ST s (Seq NamedComponent)
processComponent Bool
includeDirectTarget STRef s (Set NamedComponent)
alreadyProcessedRef component
c
          else ST s (Seq NamedComponent) -> ST s (Seq NamedComponent)
forall a. a -> a
id
  Package
-> (forall component.
    HasComponentInfo component =>
    component
    -> ST s (Seq NamedComponent) -> ST s (Seq NamedComponent))
-> ST s (Seq NamedComponent)
-> ST s (Seq NamedComponent)
forall (m :: * -> *) a.
Monad m =>
Package
-> (forall component.
    HasComponentInfo component =>
    component -> m a -> m a)
-> m a
-> m a
processPackageComponent Package
package component -> ST s (Seq NamedComponent) -> ST s (Seq NamedComponent)
forall {component}.
(HasName component, HasBuildInfo component,
 HasQualiName component) =>
component -> ST s (Seq NamedComponent) -> ST s (Seq NamedComponent)
forall component.
HasComponentInfo component =>
component -> ST s (Seq NamedComponent) -> ST s (Seq NamedComponent)
processInitialComponents (Seq NamedComponent -> ST s (Seq NamedComponent)
forall a. a -> ST s a
forall (f :: * -> *) a. Applicative f => a -> f a
pure Seq NamedComponent
forall a. Monoid a => a
mempty)
  where
    processComponent :: forall s component. HasComponentInfo component
      => Bool
       -- ^ Finally add this component in the seq

      -> STRef s (Set NamedComponent)
      -> component
      -> ST s (Seq NamedComponent)
      -> ST s (Seq NamedComponent)
    processComponent :: forall s component.
HasComponentInfo component =>
Bool
-> STRef s (Set NamedComponent)
-> component
-> ST s (Seq NamedComponent)
-> ST s (Seq NamedComponent)
processComponent Bool
finallyAddComponent STRef s (Set NamedComponent)
alreadyProcessedRef component
component ST s (Seq NamedComponent)
res = do
      let depMap :: Map PackageName DepValue
depMap = component -> Map PackageName DepValue
forall r1 r2 a.
(HasField "buildInfo" r1 r2, HasField "dependency" r2 a) =>
r1 -> a
componentDependencyMap component
component
          internalDep :: Maybe DepValue
internalDep = PackageName -> Map PackageName DepValue -> Maybe DepValue
forall k a. Ord k => k -> Map k a -> Maybe a
M.lookup Package
package.name Map PackageName DepValue
depMap
          processSubDep :: ST s (Seq NamedComponent)
processSubDep = STRef s (Set NamedComponent)
-> Maybe DepValue
-> ST s (Seq NamedComponent)
-> ST s (Seq NamedComponent)
forall {a} {s}.
HasField "depType" a DepType =>
STRef s (Set NamedComponent)
-> Maybe a
-> ST s (Seq NamedComponent)
-> ST s (Seq NamedComponent)
processOneDep STRef s (Set NamedComponent)
alreadyProcessedRef Maybe DepValue
internalDep ST s (Seq NamedComponent)
res
          qualName :: NamedComponent
qualName = component
component.qualifiedName
          processSubDepSaveName :: ST s (Seq NamedComponent)
processSubDepSaveName
            | Bool
finallyAddComponent = (Seq NamedComponent -> NamedComponent -> Seq NamedComponent
forall a. Seq a -> a -> Seq a
|> NamedComponent
qualName) (Seq NamedComponent -> Seq NamedComponent)
-> ST s (Seq NamedComponent) -> ST s (Seq NamedComponent)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ST s (Seq NamedComponent)
processSubDep
            | Bool
otherwise = ST s (Seq NamedComponent)
processSubDep
      -- This is an optimization, the only components we are likely to process

      -- multiple times are the ones we can find in dependencies, otherwise we

      -- only fold on a single version of each component by design.

      if NamedComponent -> Bool
isPotentialDependency NamedComponent
qualName
        then do
          Set NamedComponent
alreadyProcessed <- STRef s (Set NamedComponent) -> ST s (Set NamedComponent)
forall s a. STRef s a -> ST s a
readSTRef STRef s (Set NamedComponent)
alreadyProcessedRef
          if NamedComponent -> Set NamedComponent -> Bool
forall a. Ord a => a -> Set a -> Bool
S.member NamedComponent
qualName Set NamedComponent
alreadyProcessed
            then ST s (Seq NamedComponent)
res
            else STRef s (Set NamedComponent)
-> (Set NamedComponent -> Set NamedComponent) -> ST s ()
forall s a. STRef s a -> (a -> a) -> ST s ()
modifySTRef' STRef s (Set NamedComponent)
alreadyProcessedRef (NamedComponent -> Set NamedComponent -> Set NamedComponent
forall a. Ord a => a -> Set a -> Set a
S.insert NamedComponent
qualName)
                   ST s () -> ST s (Seq NamedComponent) -> ST s (Seq NamedComponent)
forall a b. ST s a -> ST s b -> ST s b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> ST s (Seq NamedComponent)
processSubDepSaveName
        else ST s (Seq NamedComponent)
processSubDepSaveName
    lookupLibName :: Bool -> Text -> Maybe StackLibrary
lookupLibName Bool
isMain Text
name = if Bool
isMain
      then Package
package.library
      else Text -> CompCollection StackLibrary -> Maybe StackLibrary
forall component.
Text -> CompCollection component -> Maybe component
collectionLookup Text
name Package
package.subLibraries
    processOneDep :: STRef s (Set NamedComponent)
-> Maybe a
-> ST s (Seq NamedComponent)
-> ST s (Seq NamedComponent)
processOneDep STRef s (Set NamedComponent)
alreadyProcessed Maybe a
mDependency ST s (Seq NamedComponent)
res =
      case (.depType) (a -> DepType) -> Maybe a -> Maybe DepType
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe a
mDependency of
        Just (AsLibrary (DepLibrary Bool
mainLibDep Set StackUnqualCompName
subLibDeps)) -> do
          let processMainLibDep :: ST s (Seq NamedComponent) -> ST s (Seq NamedComponent)
processMainLibDep =
                case (Bool
mainLibDep, Bool -> Text -> Maybe StackLibrary
lookupLibName Bool
True Text
forall a. Monoid a => a
mempty) of
                  (Bool
True, Just StackLibrary
mainLib) ->
                    Bool
-> STRef s (Set NamedComponent)
-> StackLibrary
-> ST s (Seq NamedComponent)
-> ST s (Seq NamedComponent)
forall s component.
HasComponentInfo component =>
Bool
-> STRef s (Set NamedComponent)
-> component
-> ST s (Seq NamedComponent)
-> ST s (Seq NamedComponent)
processComponent Bool
True STRef s (Set NamedComponent)
alreadyProcessed StackLibrary
mainLib
                  (Bool, Maybe StackLibrary)
_ -> ST s (Seq NamedComponent) -> ST s (Seq NamedComponent)
forall a. a -> a
id
              processSingleSubLib :: r -> ST s (Seq NamedComponent) -> ST s (Seq NamedComponent)
processSingleSubLib r
name =
                case Bool -> Text -> Maybe StackLibrary
lookupLibName Bool
False r
name.unqualCompToText of
                  Just StackLibrary
lib -> Bool
-> STRef s (Set NamedComponent)
-> StackLibrary
-> ST s (Seq NamedComponent)
-> ST s (Seq NamedComponent)
forall s component.
HasComponentInfo component =>
Bool
-> STRef s (Set NamedComponent)
-> component
-> ST s (Seq NamedComponent)
-> ST s (Seq NamedComponent)
processComponent Bool
True STRef s (Set NamedComponent)
alreadyProcessed StackLibrary
lib
                  Maybe StackLibrary
Nothing -> ST s (Seq NamedComponent) -> ST s (Seq NamedComponent)
forall a. a -> a
id
              processSubLibDep :: ST s (Seq NamedComponent) -> ST s (Seq NamedComponent)
processSubLibDep ST s (Seq NamedComponent)
r = (StackUnqualCompName
 -> ST s (Seq NamedComponent) -> ST s (Seq NamedComponent))
-> ST s (Seq NamedComponent)
-> Set StackUnqualCompName
-> ST s (Seq NamedComponent)
forall a b. (a -> b -> b) -> b -> Set a -> b
forall (t :: * -> *) a b.
Foldable t =>
(a -> b -> b) -> b -> t a -> b
foldr' StackUnqualCompName
-> ST s (Seq NamedComponent) -> ST s (Seq NamedComponent)
forall {r}.
HasField "unqualCompToText" r Text =>
r -> ST s (Seq NamedComponent) -> ST s (Seq NamedComponent)
processSingleSubLib ST s (Seq NamedComponent)
r Set StackUnqualCompName
subLibDeps
          ST s (Seq NamedComponent) -> ST s (Seq NamedComponent)
processSubLibDep (ST s (Seq NamedComponent) -> ST s (Seq NamedComponent)
processMainLibDep ST s (Seq NamedComponent)
res)
        Maybe DepType
_ -> ST s (Seq NamedComponent)
res