stack-3.11.1: src/Stack/Types/BuildOptsMonoid.hs
{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE DuplicateRecordFields #-}
{-# LANGUAGE NoFieldSelectors #-}
{-# LANGUAGE OverloadedRecordDot #-}
{-# LANGUAGE OverloadedStrings #-}
{-|
Module : Stack.Types.BuildOptsMonoid
Description : Configuration options for building.
License : BSD-3-Clause
Configuration options for building from the command line and/or a configuration
file.
-}
module Stack.Types.BuildOptsMonoid
( BuildOptsMonoid (..)
, HaddockOptsMonoid (..)
, TestOptsMonoid (..)
, BenchmarkOptsMonoid (..)
, CabalVerbosity (..)
, ProgressBarFormat (..)
, buildOptsMonoidHaddockL
, buildOptsMonoidTestsL
, buildOptsMonoidBenchmarksL
, buildOptsMonoidInstallExesL
, buildOptsMonoidSemaphoreL
, toFirstCabalVerbosity
, readProgressBarFormat
) where
import Data.Aeson.Types ( FromJSON (..), withText )
import Data.Aeson.WarningParser
( WithJSONWarnings, (..:?), (..!=), jsonSubWarnings
, withObjectWarnings
)
import qualified Data.Text as T
import Distribution.Parsec ( Parsec (..), simpleParsec )
import Distribution.Verbosity ( Verbosity, normal, verbose )
import Generics.Deriving.Monoid ( mappenddefault, memptydefault )
import Stack.Prelude hiding ( trace )
import Stack.Types.ComponentUtils ( StackUnqualCompName )
-- | Build options that may be specified as non-project specific configuration
-- options under the build key (with certain exceptions) or from the CLI.
data BuildOptsMonoid = BuildOptsMonoid
{ semaphore :: !FirstFalse
, trace :: !Any
-- ^ Cannot be specified under the build key
, profile :: !Any
-- ^ Cannot be specified under the build key
, noStrip :: !Any
-- ^ Cannot be specified under the build key
, libProfile :: !FirstFalse
, exeProfile :: !FirstFalse
, libStrip :: !FirstTrue
, exeStrip :: !FirstTrue
, buildHaddocks :: !FirstFalse
, haddockOpts :: !HaddockOptsMonoid
, openHaddocks :: !FirstFalse
, haddockDeps :: !(First Bool)
, haddockExecutables :: !FirstFalse
, haddockTests :: !FirstFalse
, haddockBenchmarks :: !FirstFalse
, haddockInternal :: !FirstFalse
, haddockHyperlinkSource :: !FirstTrue
, haddockForHackage :: !FirstFalse
, installExes :: !FirstFalse
, installCompilerTool :: !FirstFalse
, preFetch :: !FirstFalse
, keepGoing :: !(First Bool)
, keepTmpFiles :: !FirstFalse
, forceDirty :: !FirstFalse
, tests :: !FirstFalse
, testOpts :: !TestOptsMonoid
, benchmarks :: !FirstFalse
, benchmarkOpts :: !BenchmarkOptsMonoid
, reconfigure :: !FirstFalse
, cabalVerbose :: !(First CabalVerbosity)
, splitObjs :: !FirstFalse
, skipComponents :: ![StackUnqualCompName]
, interleavedOutput :: !FirstTrue
, progressBar :: !(First ProgressBarFormat)
, ddumpDir :: !(First Text)
}
deriving (Generic, Show)
instance FromJSON (WithJSONWarnings BuildOptsMonoid) where
parseJSON = withObjectWarnings "BuildOptsMonoid" $ \o -> do
let trace = Any False
profile = Any False
noStrip = Any False
libProfile <- FirstFalse <$> o ..:? libProfileArgName
exeProfile <-FirstFalse <$> o ..:? exeProfileArgName
libStrip <- FirstTrue <$> o ..:? libStripArgName
exeStrip <-FirstTrue <$> o ..:? exeStripArgName
buildHaddocks <- FirstFalse <$> o ..:? haddockArgName
haddockOpts <- jsonSubWarnings (o ..:? haddockOptsArgName ..!= mempty)
openHaddocks <- FirstFalse <$> o ..:? openHaddocksArgName
haddockDeps <- First <$> o ..:? haddockDepsArgName
haddockExecutables <- FirstFalse <$> o ..:? haddockExecutablesArgName
haddockTests <- FirstFalse <$> o ..:? haddockTestsArgName
haddockBenchmarks <- FirstFalse <$> o ..:? haddockBenchmarksArgName
haddockInternal <- FirstFalse <$> o ..:? haddockInternalArgName
haddockHyperlinkSource <- FirstTrue <$> o ..:? haddockHyperlinkSourceArgName
haddockForHackage <- FirstFalse <$> o ..:? haddockForHackageArgName
installExes <- FirstFalse <$> o ..:? installExesArgName
installCompilerTool <- FirstFalse <$> o ..:? installCompilerToolArgName
preFetch <- FirstFalse <$> o ..:? preFetchArgName
keepGoing <- First <$> o ..:? keepGoingArgName
keepTmpFiles <- FirstFalse <$> o ..:? keepTmpFilesArgName
forceDirty <- FirstFalse <$> o ..:? forceDirtyArgName
tests <- FirstFalse <$> o ..:? testsArgName
testOpts <- jsonSubWarnings (o ..:? testOptsArgName ..!= mempty)
benchmarks <- FirstFalse <$> o ..:? benchmarksArgName
benchmarkOpts <- jsonSubWarnings (o ..:? benchmarkOptsArgName ..!= mempty)
reconfigure <- FirstFalse <$> o ..:? reconfigureArgName
cabalVerbosity <- First <$> o ..:? cabalVerbosityArgName
cabalVerbose' <- FirstFalse <$> o ..:? cabalVerboseArgName
let cabalVerbose = cabalVerbosity <> toFirstCabalVerbosity cabalVerbose'
splitObjs <- FirstFalse <$> o ..:? splitObjsName
skipComponents <- o ..:? skipComponentsName ..!= mempty
interleavedOutput <- FirstTrue <$> o ..:? interleavedOutputName
progressBar <- First <$> o ..:? progressBarName
ddumpDir <- o ..:? ddumpDirName ..!= mempty
semaphore <- FirstFalse <$> o ..:? semaphoreArgName
pure BuildOptsMonoid
{ semaphore
, trace
, profile
, noStrip
, libProfile
, exeProfile
, libStrip
, exeStrip
, buildHaddocks
, haddockOpts
, openHaddocks
, haddockDeps
, haddockExecutables
, haddockTests
, haddockBenchmarks
, haddockInternal
, haddockHyperlinkSource
, haddockForHackage
, installExes
, installCompilerTool
, preFetch
, keepGoing
, keepTmpFiles
, forceDirty
, tests
, testOpts
, benchmarks
, benchmarkOpts
, reconfigure
, cabalVerbose
, splitObjs
, skipComponents
, interleavedOutput
, progressBar
, ddumpDir
}
libProfileArgName :: Text
libProfileArgName = "library-profiling"
exeProfileArgName :: Text
exeProfileArgName = "executable-profiling"
libStripArgName :: Text
libStripArgName = "library-stripping"
exeStripArgName :: Text
exeStripArgName = "executable-stripping"
haddockArgName :: Text
haddockArgName = "haddock"
haddockOptsArgName :: Text
haddockOptsArgName = "haddock-arguments"
openHaddocksArgName :: Text
openHaddocksArgName = "open-haddocks"
haddockDepsArgName :: Text
haddockDepsArgName = "haddock-deps"
haddockExecutablesArgName :: Text
haddockExecutablesArgName = "haddock-executables"
haddockTestsArgName :: Text
haddockTestsArgName = "haddock-tests"
haddockBenchmarksArgName :: Text
haddockBenchmarksArgName = "haddock-benchmarks"
haddockInternalArgName :: Text
haddockInternalArgName = "haddock-internal"
haddockHyperlinkSourceArgName :: Text
haddockHyperlinkSourceArgName = "haddock-hyperlink-source"
haddockForHackageArgName :: Text
haddockForHackageArgName = "haddock-for-hackage"
installExesArgName :: Text
installExesArgName = "copy-bins"
installCompilerToolArgName :: Text
installCompilerToolArgName = "copy-compiler-tool"
preFetchArgName :: Text
preFetchArgName = "prefetch"
keepGoingArgName :: Text
keepGoingArgName = "keep-going"
keepTmpFilesArgName :: Text
keepTmpFilesArgName = "keep-tmp-files"
forceDirtyArgName :: Text
forceDirtyArgName = "force-dirty"
testsArgName :: Text
testsArgName = "test"
testOptsArgName :: Text
testOptsArgName = "test-arguments"
benchmarksArgName :: Text
benchmarksArgName = "bench"
benchmarkOptsArgName :: Text
benchmarkOptsArgName = "benchmark-opts"
reconfigureArgName :: Text
reconfigureArgName = "reconfigure"
cabalVerbosityArgName :: Text
cabalVerbosityArgName = "cabal-verbosity"
cabalVerboseArgName :: Text
cabalVerboseArgName = "cabal-verbose"
splitObjsName :: Text
splitObjsName = "split-objs"
skipComponentsName :: Text
skipComponentsName = "skip-components"
interleavedOutputName :: Text
interleavedOutputName = "interleaved-output"
progressBarName :: Text
progressBarName = "progress-bar"
ddumpDirName :: Text
ddumpDirName = "ddump-dir"
semaphoreArgName :: Text
semaphoreArgName = "semaphore"
instance Semigroup BuildOptsMonoid where
(<>) = mappenddefault
instance Monoid BuildOptsMonoid where
mempty = memptydefault
mappend = (<>)
data TestOptsMonoid = TestOptsMonoid
{ rerunTests :: !FirstTrue
, additionalArgs :: ![String]
, coverage :: !FirstFalse
, runTests :: !FirstTrue
, maximumTimeSeconds :: !(First (Maybe Int))
, timeoutGraceSeconds :: !(First (Maybe Int))
, allowStdin :: !FirstTrue
}
deriving (Show, Generic)
instance FromJSON (WithJSONWarnings TestOptsMonoid) where
parseJSON = withObjectWarnings "TestOptsMonoid" $ \o -> do
rerunTests <- FirstTrue <$> o ..:? rerunTestsArgName
additionalArgs <- o ..:? testAdditionalArgsName ..!= []
coverage <- FirstFalse <$> o ..:? coverageArgName
runTests <- FirstTrue . (not <$>) <$> o ..:? noRunTestsArgName
maximumTimeSeconds <- First <$> o ..:? maximumTimeSecondsArgName
timeoutGraceSeconds <- First <$> o ..:? timeoutGraceSecondsArgName
allowStdin <- FirstTrue <$> o ..:? testsAllowStdinName
pure TestOptsMonoid
{ rerunTests
, additionalArgs
, coverage
, runTests
, maximumTimeSeconds
, timeoutGraceSeconds
, allowStdin
}
rerunTestsArgName :: Text
rerunTestsArgName = "rerun-tests"
testAdditionalArgsName :: Text
testAdditionalArgsName = "additional-args"
coverageArgName :: Text
coverageArgName = "coverage"
noRunTestsArgName :: Text
noRunTestsArgName = "no-run-tests"
maximumTimeSecondsArgName :: Text
maximumTimeSecondsArgName = "test-suite-timeout"
timeoutGraceSecondsArgName :: Text
timeoutGraceSecondsArgName = "test-suite-timeout-grace"
testsAllowStdinName :: Text
testsAllowStdinName = "tests-allow-stdin"
instance Semigroup TestOptsMonoid where
(<>) = mappenddefault
instance Monoid TestOptsMonoid where
mempty = memptydefault
mappend = (<>)
newtype HaddockOptsMonoid = HaddockOptsMonoid
{ additionalArgs :: [String]
}
deriving (Generic, Show)
instance FromJSON (WithJSONWarnings HaddockOptsMonoid) where
parseJSON = withObjectWarnings "HaddockOptsMonoid" $ \o -> do
additionalArgs <- o ..:? haddockAdditionalArgsName ..!= []
pure HaddockOptsMonoid { additionalArgs }
instance Semigroup HaddockOptsMonoid where
(<>) = mappenddefault
instance Monoid HaddockOptsMonoid where
mempty = memptydefault
mappend = (<>)
haddockAdditionalArgsName :: Text
haddockAdditionalArgsName = "haddock-args"
data BenchmarkOptsMonoid = BenchmarkOptsMonoid
{ additionalArgs :: !(First String)
, runBenchmarks :: !FirstTrue
}
deriving (Generic, Show)
instance FromJSON (WithJSONWarnings BenchmarkOptsMonoid) where
parseJSON = withObjectWarnings "BenchmarkOptsMonoid" $ \o -> do
additionalArgs <- First <$> o ..:? benchmarkAdditionalArgsName
runBenchmarks <- FirstTrue . (not <$>) <$> o ..:? noRunBenchmarksArgName
pure BenchmarkOptsMonoid
{ additionalArgs
, runBenchmarks
}
benchmarkAdditionalArgsName :: Text
benchmarkAdditionalArgsName = "benchmark-arguments"
noRunBenchmarksArgName :: Text
noRunBenchmarksArgName = "no-run-benchmarks"
instance Semigroup BenchmarkOptsMonoid where
(<>) = mappenddefault
instance Monoid BenchmarkOptsMonoid where
mempty = memptydefault
mappend :: BenchmarkOptsMonoid -> BenchmarkOptsMonoid -> BenchmarkOptsMonoid
mappend = (<>)
newtype CabalVerbosity
= CabalVerbosity Verbosity
deriving (Eq, Show)
toFirstCabalVerbosity :: FirstFalse -> First CabalVerbosity
toFirstCabalVerbosity vf = First $ vf.firstFalse <&> \p ->
if p then verboseLevel else normalLevel
where
verboseLevel = CabalVerbosity verbose
normalLevel = CabalVerbosity normal
instance FromJSON CabalVerbosity where
parseJSON = withText "CabalVerbosity" $ \t ->
let s = T.unpack t
errMsg = fail $ "Unrecognised Cabal verbosity: " ++ s
in maybe errMsg pure (simpleParsec s)
instance Parsec CabalVerbosity where
parsec = CabalVerbosity <$> parsec
buildOptsMonoidHaddockL :: Lens' BuildOptsMonoid (Maybe Bool)
buildOptsMonoidHaddockL =
lens (.buildHaddocks.firstFalse)
(\buildMonoid t -> buildMonoid {buildHaddocks = FirstFalse t})
buildOptsMonoidTestsL :: Lens' BuildOptsMonoid (Maybe Bool)
buildOptsMonoidTestsL =
lens (.tests.firstFalse)
(\buildMonoid t -> buildMonoid {tests = FirstFalse t})
buildOptsMonoidBenchmarksL :: Lens' BuildOptsMonoid (Maybe Bool)
buildOptsMonoidBenchmarksL =
lens (.benchmarks.firstFalse)
(\buildMonoid t -> buildMonoid {benchmarks = FirstFalse t})
buildOptsMonoidInstallExesL :: Lens' BuildOptsMonoid (Maybe Bool)
buildOptsMonoidInstallExesL =
lens (.installExes.firstFalse)
(\buildMonoid t -> buildMonoid {installExes = FirstFalse t})
buildOptsMonoidSemaphoreL :: Lens' BuildOptsMonoid (Maybe Bool)
buildOptsMonoidSemaphoreL =
lens (.semaphore.firstFalse)
(\buildMonoid t -> buildMonoid {semaphore = FirstFalse t})
-- Type representing formats of Stack's progress bar when building.
data ProgressBarFormat
= NoBar -- No progress bar at all.
| CountOnlyBar -- A bar that only counts packages.
| CappedBar -- A bar capped at a length equivalent to the terminal's width.
| FullBar -- A full progress bar.
deriving (Eq, Show)
instance FromJSON ProgressBarFormat where
parseJSON = withText "ProgressBarFormat" $ \t -> either
fail
pure
(readProgressBarFormat $ T.unpack t)
-- | Parse ProgressBarFormat from a String.
readProgressBarFormat :: String -> Either String ProgressBarFormat
readProgressBarFormat s
| s == "none" = pure NoBar
| s == "count-only" = pure CountOnlyBar
| s == "capped" = pure CappedBar
| s == "full" = pure FullBar
| otherwise = Left $ "Invalid progress bar format: " ++ s