stack-2.15.1: src/Stack/Types/Config.hs
{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE DefaultSignatures #-}
{-# LANGUAGE GADTs #-}
{-# LANGUAGE MultiWayIf #-}
{-# LANGUAGE NoFieldSelectors #-}
{-# LANGUAGE OverloadedRecordDot #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE QuasiQuotes #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE ViewPatterns #-}
module Stack.Types.Config
(
Config (..)
, HasConfig (..)
, askLatestSnapshotUrl
, configProjectRoot
, ghcInstallHook
-- * Lens helpers
, buildOptsL
, envOverrideSettingsL
, globalOptsL
, stackGlobalConfigL
, stackRootL
, workDirL
-- * Helper logging functions
, prettyStackDevL
) where
import Casa.Client ( CasaRepoPrefix )
import Distribution.System ( Platform )
import Path ( (</>), parent, reldir, relfile )
import RIO.Process ( HasProcessContext (..), ProcessContext )
import Stack.Prelude
import Stack.Types.ApplyGhcOptions ( ApplyGhcOptions (..) )
import Stack.Types.ApplyProgOptions ( ApplyProgOptions (..) )
import Stack.Types.BuildOpts ( BuildOpts )
import Stack.Types.CabalConfigKey ( CabalConfigKey )
import Stack.Types.Compiler ( CompilerRepository )
import Stack.Types.CompilerBuild ( CompilerBuild )
import Stack.Types.Docker ( DockerOpts )
import Stack.Types.DumpLogs ( DumpLogs )
import Stack.Types.EnvSettings ( EnvSettings )
import Stack.Types.GHCVariant ( GHCVariant (..), HasGHCVariant (..) )
import Stack.Types.Nix ( NixOpts )
import Stack.Types.Platform ( HasPlatform (..), PlatformVariant )
import Stack.Types.Project ( Project (..) )
import Stack.Types.ProjectConfig ( ProjectConfig (..) )
import Stack.Types.PvpBounds ( PvpBounds )
import Stack.Types.Resolver ( AbstractResolver )
import Stack.Types.Runner ( HasRunner (..), Runner, globalOptsL )
import Stack.Types.SCM ( SCM )
import Stack.Types.SetupInfo ( SetupInfo )
import Stack.Types.Storage ( UserStorage )
import Stack.Types.TemplateName ( TemplateName )
import Stack.Types.Version ( VersionCheck (..), VersionRange )
-- | The top-level Stackage configuration.
data Config = Config
{ workDir :: !(Path Rel Dir)
-- ^ this allows to override .stack-work directory
, userConfigPath :: !(Path Abs File)
-- ^ Path to user configuration file (usually ~/.stack/config.yaml)
, build :: !BuildOpts
-- ^ Build configuration
, docker :: !DockerOpts
-- ^ Docker configuration
, nix :: !NixOpts
-- ^ Execution environment (e.g nix-shell) configuration
, processContextSettings :: !(EnvSettings -> IO ProcessContext)
-- ^ Environment variables to be passed to external tools
, localProgramsBase :: !(Path Abs Dir)
-- ^ Non-platform-specific path containing local installations
, localPrograms :: !(Path Abs Dir)
-- ^ Path containing local installations (mainly GHC)
, hideTHLoading :: !Bool
-- ^ Hide the Template Haskell "Loading package ..." messages from the
-- console
, prefixTimestamps :: !Bool
-- ^ Prefix build output with timestamps for each line.
, platform :: !Platform
-- ^ The platform we're building for, used in many directory names
, platformVariant :: !PlatformVariant
-- ^ Variant of the platform, also used in directory names
, ghcVariant :: !(Maybe GHCVariant)
-- ^ The variant of GHC requested by the user.
, ghcBuild :: !(Maybe CompilerBuild)
-- ^ Override build of the compiler distribution (e.g. standard, gmp4,
-- tinfo6)
, latestSnapshot :: !Text
-- ^ URL of a JSON file providing the latest LTS and Nightly snapshots.
, systemGHC :: !Bool
-- ^ Should we use the system-installed GHC (on the PATH) if
-- available? Can be overridden by command line options.
, installGHC :: !Bool
-- ^ Should we automatically install GHC if missing or the wrong
-- version is available? Can be overridden by command line options.
, skipGHCCheck :: !Bool
-- ^ Don't bother checking the GHC version or architecture.
, skipMsys :: !Bool
-- ^ On Windows: don't use a sandboxed MSYS
, compilerCheck :: !VersionCheck
-- ^ Specifies which versions of the compiler are acceptable.
, compilerRepository :: !CompilerRepository
-- ^ Specifies the repository containing the compiler sources
, localBin :: !(Path Abs Dir)
-- ^ Directory we should install executables into
, requireStackVersion :: !VersionRange
-- ^ Require a version of Stack within this range.
, jobs :: !Int
-- ^ How many concurrent jobs to run, defaults to number of capabilities
, overrideGccPath :: !(Maybe (Path Abs File))
-- ^ Optional gcc override path
, extraIncludeDirs :: ![FilePath]
-- ^ --extra-include-dirs arguments
, extraLibDirs :: ![FilePath]
-- ^ --extra-lib-dirs arguments
, customPreprocessorExts :: ![Text]
-- ^ List of custom preprocessors to complete the hard coded ones
, concurrentTests :: !Bool
-- ^ Run test suites concurrently
, templateParams :: !(Map Text Text)
-- ^ Parameters for templates.
, scmInit :: !(Maybe SCM)
-- ^ Initialize SCM (e.g. git) when creating new projects.
, ghcOptionsByName :: !(Map PackageName [Text])
-- ^ Additional GHC options to apply to specific packages.
, ghcOptionsByCat :: !(Map ApplyGhcOptions [Text])
-- ^ Additional GHC options to apply to categories of packages
, cabalConfigOpts :: !(Map CabalConfigKey [Text])
-- ^ Additional options to be passed to ./Setup.hs configure
, setupInfoLocations :: ![String]
-- ^ URLs or paths to stack-setup.yaml files, for finding tools.
-- If none present, the default setup-info is used.
, setupInfoInline :: !SetupInfo
-- ^ Additional SetupInfo to use to find tools.
, pvpBounds :: !PvpBounds
-- ^ How PVP upper bounds should be added to packages
, modifyCodePage :: !Bool
-- ^ Force the code page to UTF-8 on Windows
, rebuildGhcOptions :: !Bool
-- ^ Rebuild on GHC options changes
, applyGhcOptions :: !ApplyGhcOptions
-- ^ Which packages do --ghc-options on the command line apply to?
, applyProgOptions :: !ApplyProgOptions
-- ^ Which packages do all and any --PROG-option options on the command line
-- apply to?
, allowNewer :: !Bool
-- ^ Ignore version ranges in .cabal files. Funny naming chosen to
-- match cabal.
, allowNewerDeps :: !(Maybe [PackageName])
-- ^ Ignore dependency upper and lower bounds only for specified
-- packages. No effect unless allow-newer is enabled.
, defaultTemplate :: !(Maybe TemplateName)
-- ^ The default template to use when none is specified.
-- (If Nothing, the 'default' default template is used.)
, allowDifferentUser :: !Bool
-- ^ Allow users other than the Stack root owner to use the Stack
-- installation.
, dumpLogs :: !DumpLogs
-- ^ Dump logs of local non-dependencies when doing a build.
, project :: !(ProjectConfig (Project, Path Abs File))
-- ^ Project information and stack.yaml file location
, allowLocals :: !Bool
-- ^ Are we allowed to build local packages? The script
-- command disallows this.
, saveHackageCreds :: !Bool
-- ^ Should we save Hackage credentials to a file?
, hackageBaseUrl :: !Text
-- ^ Hackage base URL used when uploading packages
, runner :: !Runner
, pantryConfig :: !PantryConfig
, stackRoot :: !(Path Abs Dir)
, resolver :: !(Maybe AbstractResolver)
-- ^ Any resolver override from the command line
, userStorage :: !UserStorage
-- ^ Database connection pool for user Stack database
, hideSourcePaths :: !Bool
-- ^ Enable GHC hiding source paths?
, recommendUpgrade :: !Bool
-- ^ Recommend a Stack upgrade?
, notifyIfNixOnPath :: !Bool
-- ^ Notify if the Nix package manager (nix) is on the PATH, but
-- Stack's Nix integration is not enabled?
, notifyIfGhcUntested :: !Bool
-- ^ Notify if Stack has not been tested with the GHC version?
, notifyIfCabalUntested :: !Bool
-- ^ Notify if Stack has not been tested with the Cabal version?
, notifyIfArchUnknown :: !Bool
-- ^ Notify if the specified machine architecture is unknown to Cabal (the
-- library)?
, noRunCompile :: !Bool
-- ^ Use --no-run and --compile options when using `stack script`
, stackDeveloperMode :: !Bool
-- ^ Turn on Stack developer mode for additional messages?
, casa :: !(Maybe (CasaRepoPrefix, Int))
-- ^ Optional Casa configuration
}
-- | The project root directory, if in a project.
configProjectRoot :: Config -> Maybe (Path Abs Dir)
configProjectRoot c =
case c.project of
PCProject (_, fp) -> Just $ parent fp
PCGlobalProject -> Nothing
PCNoProject _deps -> Nothing
-- | Get the URL to request the information on the latest snapshots
askLatestSnapshotUrl :: (MonadReader env m, HasConfig env) => m Text
askLatestSnapshotUrl = view $ configL . to (.latestSnapshot)
-- | @STACK_ROOT\/hooks\/@
hooksDir :: HasConfig env => RIO env (Path Abs Dir)
hooksDir = do
sr <- view $ configL . to (.stackRoot)
pure (sr </> [reldir|hooks|])
-- | @STACK_ROOT\/hooks\/ghc-install.sh@
ghcInstallHook :: HasConfig env => RIO env (Path Abs File)
ghcInstallHook = do
hd <- hooksDir
pure (hd </> [relfile|ghc-install.sh|])
-----------------------------------
-- Lens classes
-----------------------------------
-- | Class for environment values that can provide a 'Config'.
class ( HasPlatform env
, HasGHCVariant env
, HasProcessContext env
, HasPantryConfig env
, HasTerm env
, HasRunner env
) => HasConfig env where
configL :: Lens' env Config
-----------------------------------
-- Lens instances
-----------------------------------
instance HasPlatform Config where
platformL = lens (.platform) (\x y -> x { platform = y })
platformVariantL =
lens (.platformVariant) (\x y -> x { platformVariant = y })
instance HasGHCVariant Config where
ghcVariantL = to $ fromMaybe GHCStandard . (.ghcVariant)
instance HasProcessContext Config where
processContextL = runnerL . processContextL
instance HasPantryConfig Config where
pantryConfigL = lens
(.pantryConfig)
(\x y -> x { pantryConfig = y })
instance HasConfig Config where
configL = id
{-# INLINE configL #-}
instance HasRunner Config where
runnerL = lens (.runner) (\x y -> x { runner = y })
instance HasLogFunc Config where
logFuncL = runnerL . logFuncL
instance HasStylesUpdate Config where
stylesUpdateL = runnerL . stylesUpdateL
instance HasTerm Config where
useColorL = runnerL . useColorL
termWidthL = runnerL . termWidthL
-----------------------------------
-- Helper lenses
-----------------------------------
stackRootL :: HasConfig s => Lens' s (Path Abs Dir)
stackRootL =
configL . lens (.stackRoot) (\x y -> x { stackRoot = y })
stackGlobalConfigL :: HasConfig s => Lens' s (Path Abs File)
stackGlobalConfigL = configL . lens
(.userConfigPath)
(\x y -> x { userConfigPath = y })
buildOptsL :: HasConfig s => Lens' s BuildOpts
buildOptsL = configL . lens (.build) (\x y -> x { build = y })
envOverrideSettingsL ::
HasConfig env
=> Lens' env (EnvSettings -> IO ProcessContext)
envOverrideSettingsL = configL . lens
(.processContextSettings)
(\x y -> x { processContextSettings = y })
-- | @".stack-work"@
workDirL :: HasConfig env => Lens' env (Path Rel Dir)
workDirL = configL . lens (.workDir) (\x y -> x { workDir = y })
-- | In dev mode, print as a warning, otherwise as debug
prettyStackDevL :: HasConfig env => [StyleDoc] -> RIO env ()
prettyStackDevL docs = do
config <- view configL
if config.stackDeveloperMode
then prettyWarnL docs
else prettyDebugL docs