{-# LANGUAGE NoImplicitPrelude   #-}
{-# LANGUAGE DataKinds           #-}
{-# LANGUAGE NoFieldSelectors    #-}
{-# LANGUAGE OverloadedRecordDot #-}
{-# LANGUAGE OverloadedStrings   #-}

module Stack.Types.ConfigureOpts
  ( ConfigureOpts (..)
  , BaseConfigOpts (..)
  , PackageConfigureOpts (..)
  , configureOpts
  , configureOptsFromDb
  , renderConfigureOpts
  , packageConfigureOptsFromPackage
  ) where

import qualified Data.Map as Map
import qualified Data.Text as T
import           Database.Persist ( Entity, entityVal )
import           Distribution.Types.MungedPackageName
                   ( decodeCompatPackageName )
import           Distribution.Types.PackageName ( unPackageName )
import           Distribution.Types.UnqualComponentName
                   ( unUnqualComponentName )
import qualified Distribution.Version as C
import           GHC.Records ( HasField )
import           Path ( (</>), parseRelDir )
import           Path.Extra ( toFilePathNoTrailingSep )
import           Stack.Constants
                   ( bindirSuffix, compilerOptionsCabalFlag, docDirSuffix
                   , relDirEtc, relDirLib, relDirLibexec, relDirShare
                   )
import           Stack.Prelude
import           Stack.Types.BuildOpts ( BuildOpts (..) )
import           Stack.Types.BuildOptsCLI ( BuildOptsCLI )
import           Stack.Types.Compiler ( getGhcVersion, whichCompiler )
import           Stack.Types.Config ( Config (..), HasConfig (..) )
import           Stack.Types.EnvConfig ( EnvConfig, actualCompilerVersionL )
import           Stack.Types.GhcPkgId ( GhcPkgId, ghcPkgIdString )
import           Stack.Types.IsMutable ( IsMutable (..) )
import           Stack.Types.Package ( Package(..), packageIdentifier )
import           System.FilePath ( pathSeparator )

-- | Basic information used to calculate what the configure options are

data BaseConfigOpts = BaseConfigOpts
  { BaseConfigOpts -> Path Abs Dir
snapDB :: !(Path Abs Dir)
  , BaseConfigOpts -> Path Abs Dir
localDB :: !(Path Abs Dir)
  , BaseConfigOpts -> Path Abs Dir
snapInstallRoot :: !(Path Abs Dir)
  , BaseConfigOpts -> Path Abs Dir
localInstallRoot :: !(Path Abs Dir)
  , BaseConfigOpts -> BuildOpts
buildOpts :: !BuildOpts
  , BaseConfigOpts -> BuildOptsCLI
buildOptsCLI :: !BuildOptsCLI
  , BaseConfigOpts -> [Path Abs Dir]
extraDBs :: ![Path Abs Dir]
  }
  deriving Int -> BaseConfigOpts -> ShowS
[BaseConfigOpts] -> ShowS
BaseConfigOpts -> String
(Int -> BaseConfigOpts -> ShowS)
-> (BaseConfigOpts -> String)
-> ([BaseConfigOpts] -> ShowS)
-> Show BaseConfigOpts
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> BaseConfigOpts -> ShowS
showsPrec :: Int -> BaseConfigOpts -> ShowS
$cshow :: BaseConfigOpts -> String
show :: BaseConfigOpts -> String
$cshowList :: [BaseConfigOpts] -> ShowS
showList :: [BaseConfigOpts] -> ShowS
Show

-- | All these fields come from the 'Package' data type but bringing the whole

-- Package is way too much, hence this datatype.

data PackageConfigureOpts = PackageConfigureOpts
  { PackageConfigureOpts -> [Text]
pkgCabalConfigOpts :: [Text]
  , PackageConfigureOpts -> [Text]
pkgGhcOptions :: [Text]
  , PackageConfigureOpts -> Map FlagName Bool
pkgFlags :: Map FlagName Bool
  , PackageConfigureOpts -> Map FlagName Bool
pkgDefaultFlags :: Map FlagName Bool
  , PackageConfigureOpts -> PackageIdentifier
pkgIdentifier :: PackageIdentifier
  }
  deriving Int -> PackageConfigureOpts -> ShowS
[PackageConfigureOpts] -> ShowS
PackageConfigureOpts -> String
(Int -> PackageConfigureOpts -> ShowS)
-> (PackageConfigureOpts -> String)
-> ([PackageConfigureOpts] -> ShowS)
-> Show PackageConfigureOpts
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> PackageConfigureOpts -> ShowS
showsPrec :: Int -> PackageConfigureOpts -> ShowS
$cshow :: PackageConfigureOpts -> String
show :: PackageConfigureOpts -> String
$cshowList :: [PackageConfigureOpts] -> ShowS
showList :: [PackageConfigureOpts] -> ShowS
Show

packageConfigureOptsFromPackage ::
     Package
  -> PackageConfigureOpts
packageConfigureOptsFromPackage :: Package -> PackageConfigureOpts
packageConfigureOptsFromPackage Package
pkg = PackageConfigureOpts
  { $sel:pkgCabalConfigOpts:PackageConfigureOpts :: [Text]
pkgCabalConfigOpts = Package
pkg.cabalConfigOpts
  , $sel:pkgGhcOptions:PackageConfigureOpts :: [Text]
pkgGhcOptions = Package
pkg.ghcOptions
  , $sel:pkgFlags:PackageConfigureOpts :: Map FlagName Bool
pkgFlags = Package
pkg.flags
  , $sel:pkgDefaultFlags:PackageConfigureOpts :: Map FlagName Bool
pkgDefaultFlags = Package
pkg.defaultFlags
  , $sel:pkgIdentifier:PackageConfigureOpts :: PackageIdentifier
pkgIdentifier = Package -> PackageIdentifier
packageIdentifier Package
pkg
  }

configureOptsFromDb ::
     ( HasField "configCacheDirOptionValue" b1 String
     , HasField "configCacheNoDirOptionValue" b2 String
     )
  => [Entity b1]
  -> [Entity b2]
  -> ConfigureOpts
configureOptsFromDb :: forall b1 b2.
(HasField "configCacheDirOptionValue" b1 String,
 HasField "configCacheNoDirOptionValue" b2 String) =>
[Entity b1] -> [Entity b2] -> ConfigureOpts
configureOptsFromDb [Entity b1]
x [Entity b2]
y = ConfigureOpts
  { $sel:pathRelated:ConfigureOpts :: [String]
pathRelated = (Entity b1 -> String) -> [Entity b1] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map ((.configCacheDirOptionValue) (b1 -> String) -> (Entity b1 -> b1) -> Entity b1 -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Entity b1 -> b1
forall record. Entity record -> record
entityVal) [Entity b1]
x
  , $sel:nonPathRelated:ConfigureOpts :: [String]
nonPathRelated = (Entity b2 -> String) -> [Entity b2] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map ((.configCacheNoDirOptionValue) (b2 -> String) -> (Entity b2 -> b2) -> Entity b2 -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Entity b2 -> b2
forall record. Entity record -> record
entityVal) [Entity b2]
y
  }

-- | Render a @BaseConfigOpts@ to an actual list of options

configureOpts ::
     EnvConfig
  -> BaseConfigOpts
  -> Map PackageIdentifier GhcPkgId -- ^ dependencies

  -> Bool -- ^ local non-extra-dep?

  -> IsMutable
  -> PackageConfigureOpts
  -> ConfigureOpts
configureOpts :: EnvConfig
-> BaseConfigOpts
-> Map PackageIdentifier GhcPkgId
-> Bool
-> IsMutable
-> PackageConfigureOpts
-> ConfigureOpts
configureOpts EnvConfig
econfig BaseConfigOpts
bco Map PackageIdentifier GhcPkgId
deps Bool
isLocal IsMutable
isMutable PackageConfigureOpts
pkgConfigureOpts = ConfigureOpts
  { $sel:pathRelated:ConfigureOpts :: [String]
pathRelated = BaseConfigOpts -> IsMutable -> PackageConfigureOpts -> [String]
configureOptsPathRelated BaseConfigOpts
bco IsMutable
isMutable PackageConfigureOpts
pkgConfigureOpts
  , $sel:nonPathRelated:ConfigureOpts :: [String]
nonPathRelated =
      EnvConfig
-> BaseConfigOpts
-> Map PackageIdentifier GhcPkgId
-> Bool
-> PackageConfigureOpts
-> [String]
configureOptsNonPathRelated EnvConfig
econfig BaseConfigOpts
bco Map PackageIdentifier GhcPkgId
deps Bool
isLocal PackageConfigureOpts
pkgConfigureOpts
  }

configureOptsPathRelated ::
     BaseConfigOpts
  -> IsMutable
  -> PackageConfigureOpts
  -> [String]
configureOptsPathRelated :: BaseConfigOpts -> IsMutable -> PackageConfigureOpts -> [String]
configureOptsPathRelated BaseConfigOpts
bco IsMutable
isMutable PackageConfigureOpts
pkgOpts = [[String]] -> [String]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat
  [ [String
"--user", String
"--package-db=clear", String
"--package-db=global"]
  , (Path Abs Dir -> String) -> [Path Abs Dir] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map ((String
"--package-db=" ++) ShowS -> (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] -> [String]) -> [Path Abs Dir] -> [String]
forall a b. (a -> b) -> a -> b
$ case IsMutable
isMutable of
      IsMutable
Immutable -> BaseConfigOpts
bco.extraDBs [Path Abs Dir] -> [Path Abs Dir] -> [Path Abs Dir]
forall a. [a] -> [a] -> [a]
++ [BaseConfigOpts
bco.snapDB]
      IsMutable
Mutable -> BaseConfigOpts
bco.extraDBs [Path Abs Dir] -> [Path Abs Dir] -> [Path Abs Dir]
forall a. [a] -> [a] -> [a]
++ [BaseConfigOpts
bco.snapDB] [Path Abs Dir] -> [Path Abs Dir] -> [Path Abs Dir]
forall a. [a] -> [a] -> [a]
++ [BaseConfigOpts
bco.localDB]
  , [ String
"--libdir=" String -> ShowS
forall a. [a] -> [a] -> [a]
++ Path Abs Dir -> String
forall loc. Path loc Dir -> String
toFilePathNoTrailingSep (Path Abs Dir
installRoot Path Abs Dir -> Path Rel Dir -> Path Abs Dir
forall b t. Path b Dir -> Path Rel t -> Path b t
</> Path Rel Dir
relDirLib)
    , String
"--bindir=" String -> ShowS
forall a. [a] -> [a] -> [a]
++ Path Abs Dir -> String
forall loc. Path loc Dir -> String
toFilePathNoTrailingSep (Path Abs Dir
installRoot Path Abs Dir -> Path Rel Dir -> Path Abs Dir
forall b t. Path b Dir -> Path Rel t -> Path b t
</> Path Rel Dir
bindirSuffix)
    , String
"--datadir=" String -> ShowS
forall a. [a] -> [a] -> [a]
++ Path Abs Dir -> String
forall loc. Path loc Dir -> String
toFilePathNoTrailingSep (Path Abs Dir
installRoot Path Abs Dir -> Path Rel Dir -> Path Abs Dir
forall b t. Path b Dir -> Path Rel t -> Path b t
</> Path Rel Dir
relDirShare)
    , String
"--libexecdir=" String -> ShowS
forall a. [a] -> [a] -> [a]
++ Path Abs Dir -> String
forall loc. Path loc Dir -> String
toFilePathNoTrailingSep (Path Abs Dir
installRoot Path Abs Dir -> Path Rel Dir -> Path Abs Dir
forall b t. Path b Dir -> Path Rel t -> Path b t
</> Path Rel Dir
relDirLibexec)
    , String
"--sysconfdir=" String -> ShowS
forall a. [a] -> [a] -> [a]
++ Path Abs Dir -> String
forall loc. Path loc Dir -> String
toFilePathNoTrailingSep (Path Abs Dir
installRoot Path Abs Dir -> Path Rel Dir -> Path Abs Dir
forall b t. Path b Dir -> Path Rel t -> Path b t
</> Path Rel Dir
relDirEtc)
    , String
"--docdir=" String -> ShowS
forall a. [a] -> [a] -> [a]
++ Path Abs Dir -> String
forall loc. Path loc Dir -> String
toFilePathNoTrailingSep Path Abs Dir
docDir
    , String
"--htmldir=" String -> ShowS
forall a. [a] -> [a] -> [a]
++ Path Abs Dir -> String
forall loc. Path loc Dir -> String
toFilePathNoTrailingSep Path Abs Dir
docDir
    , String
"--haddockdir=" String -> ShowS
forall a. [a] -> [a] -> [a]
++ Path Abs Dir -> String
forall loc. Path loc Dir -> String
toFilePathNoTrailingSep Path Abs Dir
docDir]
  ]
 where
  installRoot :: Path Abs Dir
installRoot =
    case IsMutable
isMutable of
      IsMutable
Immutable -> BaseConfigOpts
bco.snapInstallRoot
      IsMutable
Mutable -> BaseConfigOpts
bco.localInstallRoot
  docDir :: Path Abs Dir
docDir =
    case Maybe (Path Rel Dir)
pkgVerDir of
      Maybe (Path Rel Dir)
Nothing -> Path Abs Dir
installRoot Path Abs Dir -> Path Rel Dir -> Path Abs Dir
forall b t. Path b Dir -> Path Rel t -> Path b t
</> Path Rel Dir
docDirSuffix
      Just Path Rel Dir
dir -> Path Abs Dir
installRoot Path Abs Dir -> Path Rel Dir -> Path Abs Dir
forall b t. Path b Dir -> Path Rel t -> Path b t
</> Path Rel Dir
docDirSuffix Path Rel Dir -> Path Rel Dir -> Path Rel Dir
forall b t. Path b Dir -> Path Rel t -> Path b t
</> Path Rel Dir
dir
  pkgVerDir :: Maybe (Path Rel Dir)
pkgVerDir = String -> Maybe (Path Rel Dir)
forall (m :: * -> *). MonadThrow m => String -> m (Path Rel Dir)
parseRelDir
    (  PackageIdentifier -> String
packageIdentifierString PackageConfigureOpts
pkgOpts.pkgIdentifier
    String -> ShowS
forall a. [a] -> [a] -> [a]
++ [Char
pathSeparator]
    )

-- | Same as 'configureOpts', but does not include directory path options

configureOptsNonPathRelated ::
     EnvConfig
  -> BaseConfigOpts
  -> Map PackageIdentifier GhcPkgId -- ^ Dependencies.

  -> Bool -- ^ Is this a local, non-extra-dep?

  -> PackageConfigureOpts
  -> [String]
configureOptsNonPathRelated :: EnvConfig
-> BaseConfigOpts
-> Map PackageIdentifier GhcPkgId
-> Bool
-> PackageConfigureOpts
-> [String]
configureOptsNonPathRelated EnvConfig
econfig BaseConfigOpts
bco Map PackageIdentifier GhcPkgId
deps Bool
isLocal PackageConfigureOpts
package = [[String]] -> [String]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat
  [ [String]
depOptions
  , [ String
"--enable-library-profiling"
    | BuildOpts
bopts.libProfile Bool -> Bool -> Bool
|| BuildOpts
bopts.exeProfile
    ]
  , [String
"--enable-profiling" | BuildOpts
bopts.exeProfile Bool -> Bool -> Bool
&& Bool
isLocal]
  , [String
"--enable-split-objs" | BuildOpts
bopts.splitObjs]
  , [ String
"--disable-library-stripping"
    | Bool -> Bool
not (Bool -> Bool) -> Bool -> Bool
forall a b. (a -> b) -> a -> b
$ BuildOpts
bopts.libStrip Bool -> Bool -> Bool
|| BuildOpts
bopts.exeStrip
    ]
  , [String
"--disable-executable-stripping" | Bool -> Bool
not BuildOpts
bopts.exeStrip Bool -> Bool -> Bool
&& Bool
isLocal]
  , [String]
flags
  , (Text -> String) -> [Text] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map Text -> String
T.unpack PackageConfigureOpts
package.pkgCabalConfigOpts
  , [Text] -> [String]
processGhcOptions PackageConfigureOpts
package.pkgGhcOptions
  , ShowS -> [String] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map (String
"--extra-include-dirs=" ++) Config
config.extraIncludeDirs
  , ShowS -> [String] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map (String
"--extra-lib-dirs=" ++) Config
config.extraLibDirs
  , [String]
-> (Path Abs File -> [String]) -> Maybe (Path Abs File) -> [String]
forall b a. b -> (a -> b) -> Maybe a -> b
maybe
      []
      (\Path Abs File
customGcc -> [String
"--with-gcc=" String -> ShowS
forall a. [a] -> [a] -> [a]
++ Path Abs File -> String
forall b t. Path b t -> String
toFilePath Path Abs File
customGcc])
      Config
config.overrideGccPath
  , [String
"--exact-configuration"]
  , [String
"--ghc-option=-fhide-source-paths" | Version -> Bool
hideSourcePaths Version
cv]
  ]
 where
  -- This function parses the GHC options that are providing in the

  -- stack.yaml file. In order to handle RTS arguments correctly, we need

  -- to provide the RTS arguments as a single argument.

  processGhcOptions :: [Text] -> [String]
  processGhcOptions :: [Text] -> [String]
processGhcOptions [Text]
args =
    let ([Text]
preRtsArgs, [Text]
mid) = (Text -> Bool) -> [Text] -> ([Text], [Text])
forall a. (a -> Bool) -> [a] -> ([a], [a])
break (Text
"+RTS" ==) [Text]
args
        ([Text]
rtsArgs, [Text]
end) = (Text -> Bool) -> [Text] -> ([Text], [Text])
forall a. (a -> Bool) -> [a] -> ([a], [a])
break (Text
"-RTS" ==) [Text]
mid
        fullRtsArgs :: [Text]
fullRtsArgs =
          case [Text]
rtsArgs of
            [] ->
              -- This means that we didn't have any RTS args - no `+RTS` - and

              -- therefore no need for a `-RTS`.

              []
            [Text]
_ ->
              -- In this case, we have some RTS args. `break` puts the `"-RTS"`

              -- string in the `snd` list, so we want to append it on the end of

              -- `rtsArgs` here.

              --

              -- We're not checking that `-RTS` is the first element of `end`.

              -- This is because the GHC RTS allows you to omit a trailing -RTS

              -- if that's the last of the arguments. This permits a GHC options

              -- in stack.yaml that matches what you might pass directly to GHC.

              [[Text] -> Text
T.unwords ([Text] -> Text) -> [Text] -> Text
forall a b. (a -> b) -> a -> b
$ [Text]
rtsArgs [Text] -> [Text] -> [Text]
forall a. [a] -> [a] -> [a]
++ [Text
"-RTS"]]
        -- We drop the first element from `end`, because it is always either

        -- `"-RTS"` (and we don't want that as a separate argument) or the list

        -- is empty (and `drop _ [] = []`).

        postRtsArgs :: [Text]
postRtsArgs = Int -> [Text] -> [Text]
forall a. Int -> [a] -> [a]
drop Int
1 [Text]
end
        newArgs :: [Text]
newArgs = [[Text]] -> [Text]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat [[Text]
preRtsArgs, [Text]
fullRtsArgs, [Text]
postRtsArgs]
    in  (Text -> [String]) -> [Text] -> [String]
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap (\Text
x -> [WhichCompiler -> String
compilerOptionsCabalFlag WhichCompiler
wc, Text -> String
T.unpack Text
x]) [Text]
newArgs

  wc :: WhichCompiler
wc = Getting WhichCompiler EnvConfig WhichCompiler
-> EnvConfig -> WhichCompiler
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view (Getting WhichCompiler EnvConfig ActualCompiler
forall env. HasSourceMap env => SimpleGetter env ActualCompiler
SimpleGetter EnvConfig ActualCompiler
actualCompilerVersionL Getting WhichCompiler EnvConfig ActualCompiler
-> ((WhichCompiler -> Const WhichCompiler WhichCompiler)
    -> ActualCompiler -> Const WhichCompiler ActualCompiler)
-> Getting WhichCompiler EnvConfig WhichCompiler
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (ActualCompiler -> WhichCompiler)
-> SimpleGetter ActualCompiler WhichCompiler
forall s a. (s -> a) -> SimpleGetter s a
to ActualCompiler -> WhichCompiler
whichCompiler) EnvConfig
econfig
  cv :: Version
cv = Getting Version EnvConfig Version -> EnvConfig -> Version
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view (Getting Version EnvConfig ActualCompiler
forall env. HasSourceMap env => SimpleGetter env ActualCompiler
SimpleGetter EnvConfig ActualCompiler
actualCompilerVersionL Getting Version EnvConfig ActualCompiler
-> ((Version -> Const Version Version)
    -> ActualCompiler -> Const Version ActualCompiler)
-> Getting Version EnvConfig Version
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (ActualCompiler -> Version) -> SimpleGetter ActualCompiler Version
forall s a. (s -> a) -> SimpleGetter s a
to ActualCompiler -> Version
getGhcVersion) EnvConfig
econfig

  hideSourcePaths :: Version -> Bool
hideSourcePaths Version
ghcVersion =
    Version
ghcVersion Version -> Version -> Bool
forall a. Ord a => a -> a -> Bool
>= [Int] -> Version
C.mkVersion [Int
8, Int
2] Bool -> Bool -> Bool
&& Config
config.hideSourcePaths

  config :: Config
config = Getting Config EnvConfig Config -> EnvConfig -> Config
forall s (m :: * -> *) a. MonadReader s m => Getting a s a -> m a
view Getting Config EnvConfig Config
forall env. HasConfig env => Lens' env Config
Lens' EnvConfig Config
configL EnvConfig
econfig
  bopts :: BuildOpts
bopts = BaseConfigOpts
bco.buildOpts
  mapAndAppend :: (k -> a -> a) -> [a] -> Map k a -> [a]
mapAndAppend k -> a -> a
fn = (k -> a -> [a] -> [a]) -> [a] -> Map k a -> [a]
forall k a b. (k -> a -> b -> b) -> b -> Map k a -> b
Map.foldrWithKey' ((a -> [a] -> [a]) -> (a -> a) -> a -> [a] -> [a]
forall a b. (a -> b) -> (a -> a) -> a -> b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (:) ((a -> a) -> a -> [a] -> [a])
-> (k -> a -> a) -> k -> a -> [a] -> [a]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. k -> a -> a
fn)
  -- Unioning atop defaults is needed so that all flags are specified with

  -- --exact-configuration.

  flags :: [String]
flags = (FlagName -> Bool -> String)
-> [String] -> Map FlagName Bool -> [String]
forall {k} {a} {a}. (k -> a -> a) -> [a] -> Map k a -> [a]
mapAndAppend
    FlagName -> Bool -> String
renderFlags
    []
    (PackageConfigureOpts
package.pkgFlags Map FlagName Bool -> Map FlagName Bool -> Map FlagName Bool
forall k a. Ord k => Map k a -> Map k a -> Map k a
`Map.union` PackageConfigureOpts
package.pkgDefaultFlags)
  renderFlags :: FlagName -> Bool -> String
renderFlags FlagName
name Bool
enabled =
       String
"-f"
    String -> ShowS
forall a. Semigroup a => a -> a -> a
<> (if Bool
enabled then String
"" else String
"-")
    String -> ShowS
forall a. Semigroup a => a -> a -> a
<> FlagName -> String
flagNameString FlagName
name

  depOptions :: [String]
depOptions = (PackageIdentifier -> GhcPkgId -> String)
-> [String] -> Map PackageIdentifier GhcPkgId -> [String]
forall {k} {a} {a}. (k -> a -> a) -> [a] -> Map k a -> [a]
mapAndAppend PackageIdentifier -> GhcPkgId -> String
toDepOption [] Map PackageIdentifier GhcPkgId
deps

  toDepOption :: PackageIdentifier -> GhcPkgId -> String
toDepOption (PackageIdentifier PackageName
name Version
_) GhcPkgId
gid = [String] -> String
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat
    [ String
"--dependency="
    , String
depOptionKey
    , String
"="
    , GhcPkgId -> String
ghcPkgIdString GhcPkgId
gid
    ]
   where
    MungedPackageName PackageName
subPkgName LibraryName
lib = PackageName -> MungedPackageName
decodeCompatPackageName PackageName
name
    depOptionKey :: String
depOptionKey = case LibraryName
lib of
      LibraryName
LMainLibName -> PackageName -> String
unPackageName PackageName
name
      LSubLibName UnqualComponentName
cn ->
        PackageName -> String
unPackageName PackageName
subPkgName String -> ShowS
forall a. Semigroup a => a -> a -> a
<> String
":" String -> ShowS
forall a. Semigroup a => a -> a -> a
<> UnqualComponentName -> String
unUnqualComponentName UnqualComponentName
cn

-- | Configure options to be sent to Setup.hs configure.

data ConfigureOpts = ConfigureOpts
  { ConfigureOpts -> [String]
pathRelated :: ![String]
    -- ^ Options related to various paths. We separate these out since they do

    -- not have an effect on the contents of the compiled binary for checking

    -- if we can use an existing precompiled cache.

  , ConfigureOpts -> [String]
nonPathRelated :: ![String]
    -- ^ Options other than path-related options.

  }
  deriving (Typeable ConfigureOpts
Typeable ConfigureOpts =>
(forall (c :: * -> *).
 (forall d b. Data d => c (d -> b) -> d -> c b)
 -> (forall g. g -> c g) -> ConfigureOpts -> c ConfigureOpts)
-> (forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c ConfigureOpts)
-> (ConfigureOpts -> Constr)
-> (ConfigureOpts -> DataType)
-> (forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c ConfigureOpts))
-> (forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e))
    -> Maybe (c ConfigureOpts))
-> ((forall b. Data b => b -> b) -> ConfigureOpts -> ConfigureOpts)
-> (forall r r'.
    (r -> r' -> r)
    -> r -> (forall d. Data d => d -> r') -> ConfigureOpts -> r)
-> (forall r r'.
    (r' -> r -> r)
    -> r -> (forall d. Data d => d -> r') -> ConfigureOpts -> r)
-> (forall u. (forall d. Data d => d -> u) -> ConfigureOpts -> [u])
-> (forall u.
    Int -> (forall d. Data d => d -> u) -> ConfigureOpts -> u)
-> (forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d) -> ConfigureOpts -> m ConfigureOpts)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> ConfigureOpts -> m ConfigureOpts)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> ConfigureOpts -> m ConfigureOpts)
-> Data ConfigureOpts
ConfigureOpts -> Constr
ConfigureOpts -> DataType
(forall b. Data b => b -> b) -> ConfigureOpts -> ConfigureOpts
forall a.
Typeable a =>
(forall (c :: * -> *).
 (forall d b. Data d => c (d -> b) -> d -> c b)
 -> (forall g. g -> c g) -> a -> c a)
-> (forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c a)
-> (a -> Constr)
-> (a -> DataType)
-> (forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c a))
-> (forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c a))
-> ((forall b. Data b => b -> b) -> a -> a)
-> (forall r r'.
    (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
-> (forall r r'.
    (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
-> (forall u. (forall d. Data d => d -> u) -> a -> [u])
-> (forall u. Int -> (forall d. Data d => d -> u) -> a -> u)
-> (forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> (forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> a -> m a)
-> Data a
forall u. Int -> (forall d. Data d => d -> u) -> ConfigureOpts -> u
forall u. (forall d. Data d => d -> u) -> ConfigureOpts -> [u]
forall r r'.
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> ConfigureOpts -> r
forall r r'.
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> ConfigureOpts -> r
forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> ConfigureOpts -> m ConfigureOpts
forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> ConfigureOpts -> m ConfigureOpts
forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c ConfigureOpts
forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> ConfigureOpts -> c ConfigureOpts
forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c ConfigureOpts)
forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e))
-> Maybe (c ConfigureOpts)
$cgfoldl :: forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> ConfigureOpts -> c ConfigureOpts
gfoldl :: forall (c :: * -> *).
(forall d b. Data d => c (d -> b) -> d -> c b)
-> (forall g. g -> c g) -> ConfigureOpts -> c ConfigureOpts
$cgunfold :: forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c ConfigureOpts
gunfold :: forall (c :: * -> *).
(forall b r. Data b => c (b -> r) -> c r)
-> (forall r. r -> c r) -> Constr -> c ConfigureOpts
$ctoConstr :: ConfigureOpts -> Constr
toConstr :: ConfigureOpts -> Constr
$cdataTypeOf :: ConfigureOpts -> DataType
dataTypeOf :: ConfigureOpts -> DataType
$cdataCast1 :: forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c ConfigureOpts)
dataCast1 :: forall (t :: * -> *) (c :: * -> *).
Typeable t =>
(forall d. Data d => c (t d)) -> Maybe (c ConfigureOpts)
$cdataCast2 :: forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e))
-> Maybe (c ConfigureOpts)
dataCast2 :: forall (t :: * -> * -> *) (c :: * -> *).
Typeable t =>
(forall d e. (Data d, Data e) => c (t d e))
-> Maybe (c ConfigureOpts)
$cgmapT :: (forall b. Data b => b -> b) -> ConfigureOpts -> ConfigureOpts
gmapT :: (forall b. Data b => b -> b) -> ConfigureOpts -> ConfigureOpts
$cgmapQl :: forall r r'.
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> ConfigureOpts -> r
gmapQl :: forall r r'.
(r -> r' -> r)
-> r -> (forall d. Data d => d -> r') -> ConfigureOpts -> r
$cgmapQr :: forall r r'.
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> ConfigureOpts -> r
gmapQr :: forall r r'.
(r' -> r -> r)
-> r -> (forall d. Data d => d -> r') -> ConfigureOpts -> r
$cgmapQ :: forall u. (forall d. Data d => d -> u) -> ConfigureOpts -> [u]
gmapQ :: forall u. (forall d. Data d => d -> u) -> ConfigureOpts -> [u]
$cgmapQi :: forall u. Int -> (forall d. Data d => d -> u) -> ConfigureOpts -> u
gmapQi :: forall u. Int -> (forall d. Data d => d -> u) -> ConfigureOpts -> u
$cgmapM :: forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> ConfigureOpts -> m ConfigureOpts
gmapM :: forall (m :: * -> *).
Monad m =>
(forall d. Data d => d -> m d) -> ConfigureOpts -> m ConfigureOpts
$cgmapMp :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> ConfigureOpts -> m ConfigureOpts
gmapMp :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> ConfigureOpts -> m ConfigureOpts
$cgmapMo :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> ConfigureOpts -> m ConfigureOpts
gmapMo :: forall (m :: * -> *).
MonadPlus m =>
(forall d. Data d => d -> m d) -> ConfigureOpts -> m ConfigureOpts
Data, ConfigureOpts -> ConfigureOpts -> Bool
(ConfigureOpts -> ConfigureOpts -> Bool)
-> (ConfigureOpts -> ConfigureOpts -> Bool) -> Eq ConfigureOpts
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
$c== :: ConfigureOpts -> ConfigureOpts -> Bool
== :: ConfigureOpts -> ConfigureOpts -> Bool
$c/= :: ConfigureOpts -> ConfigureOpts -> Bool
/= :: ConfigureOpts -> ConfigureOpts -> Bool
Eq, (forall x. ConfigureOpts -> Rep ConfigureOpts x)
-> (forall x. Rep ConfigureOpts x -> ConfigureOpts)
-> Generic ConfigureOpts
forall x. Rep ConfigureOpts x -> ConfigureOpts
forall x. ConfigureOpts -> Rep ConfigureOpts x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
$cfrom :: forall x. ConfigureOpts -> Rep ConfigureOpts x
from :: forall x. ConfigureOpts -> Rep ConfigureOpts x
$cto :: forall x. Rep ConfigureOpts x -> ConfigureOpts
to :: forall x. Rep ConfigureOpts x -> ConfigureOpts
Generic, Int -> ConfigureOpts -> ShowS
[ConfigureOpts] -> ShowS
ConfigureOpts -> String
(Int -> ConfigureOpts -> ShowS)
-> (ConfigureOpts -> String)
-> ([ConfigureOpts] -> ShowS)
-> Show ConfigureOpts
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
$cshowsPrec :: Int -> ConfigureOpts -> ShowS
showsPrec :: Int -> ConfigureOpts -> ShowS
$cshow :: ConfigureOpts -> String
show :: ConfigureOpts -> String
$cshowList :: [ConfigureOpts] -> ShowS
showList :: [ConfigureOpts] -> ShowS
Show, Typeable)

instance NFData ConfigureOpts

-- | Render configure options as a single list of options.

renderConfigureOpts :: ConfigureOpts -> [String]
renderConfigureOpts :: ConfigureOpts -> [String]
renderConfigureOpts ConfigureOpts
copts = ConfigureOpts
copts.pathRelated [String] -> [String] -> [String]
forall a. [a] -> [a] -> [a]
++ ConfigureOpts
copts.nonPathRelated