{-# LANGUAGE NoImplicitPrelude #-} {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE RecordWildCards #-} -- | Configuration options for building. module Stack.Types.Config.Build ( BuildOpts(..) , BuildCommand(..) , defaultBuildOpts , defaultBuildOptsCLI , BuildOptsCLI(..) , BuildOptsMonoid(..) , TestOpts(..) , defaultTestOpts , TestOptsMonoid(..) , HaddockOpts(..) , defaultHaddockOpts , HaddockOptsMonoid(..) , BenchmarkOpts(..) , defaultBenchmarkOpts , BenchmarkOptsMonoid(..) , FileWatchOpts(..) , BuildSubset(..) , ApplyCLIFlag (..) , boptsCLIFlagsByName ) where import Pantry.Internal.AesonExtended import qualified Data.Map.Strict as Map import Generics.Deriving.Monoid (memptydefault, mappenddefault) import Stack.Prelude -- | Build options that is interpreted by the build command. -- This is built up from BuildOptsCLI and BuildOptsMonoid data BuildOpts = BuildOpts {boptsLibProfile :: !Bool ,boptsExeProfile :: !Bool ,boptsLibStrip :: !Bool ,boptsExeStrip :: !Bool ,boptsHaddock :: !Bool -- ^ Build haddocks? ,boptsHaddockOpts :: !HaddockOpts -- ^ Options to pass to haddock ,boptsOpenHaddocks :: !Bool -- ^ Open haddocks in the browser? ,boptsHaddockDeps :: !(Maybe Bool) -- ^ Build haddocks for dependencies? ,boptsHaddockInternal :: !Bool -- ^ Build haddocks for all symbols and packages, like @cabal haddock --internal@ ,boptsHaddockHyperlinkSource :: !Bool -- ^ Build hyperlinked source if possible. Fallback to -- @hscolour@. Disable for no sources. ,boptsInstallExes :: !Bool -- ^ Install executables to user path after building? ,boptsInstallCompilerTool :: !Bool -- ^ Install executables to compiler tools path after building? ,boptsPreFetch :: !Bool -- ^ Fetch all packages immediately -- ^ Watch files for changes and automatically rebuild ,boptsKeepGoing :: !(Maybe Bool) -- ^ Keep building/running after failure ,boptsKeepTmpFiles :: !Bool -- ^ Keep intermediate files and build directories ,boptsForceDirty :: !Bool -- ^ Force treating all local packages as having dirty files ,boptsTests :: !Bool -- ^ Turn on tests for local targets ,boptsTestOpts :: !TestOpts -- ^ Additional test arguments ,boptsBenchmarks :: !Bool -- ^ Turn on benchmarks for local targets ,boptsBenchmarkOpts :: !BenchmarkOpts -- ^ Additional test arguments -- ^ Commands (with arguments) to run after a successful build -- ^ Only perform the configure step when building ,boptsReconfigure :: !Bool -- ^ Perform the configure step even if already configured ,boptsCabalVerbose :: !Bool -- ^ Ask Cabal to be verbose in its builds ,boptsSplitObjs :: !Bool -- ^ Whether to enable split-objs. ,boptsSkipComponents :: ![Text] -- ^ Which components to skip when building ,boptsInterleavedOutput :: !Bool -- ^ Should we use the interleaved GHC output when building -- multiple packages? ,boptsDdumpDir :: !(Maybe Text) } deriving (Show) defaultBuildOpts :: BuildOpts defaultBuildOpts = BuildOpts { boptsLibProfile = defaultFirstFalse buildMonoidLibProfile , boptsExeProfile = defaultFirstFalse buildMonoidExeProfile , boptsLibStrip = defaultFirstTrue buildMonoidLibStrip , boptsExeStrip = defaultFirstTrue buildMonoidExeStrip , boptsHaddock = False , boptsHaddockOpts = defaultHaddockOpts , boptsOpenHaddocks = defaultFirstFalse buildMonoidOpenHaddocks , boptsHaddockDeps = Nothing , boptsHaddockInternal = defaultFirstFalse buildMonoidHaddockInternal , boptsHaddockHyperlinkSource = defaultFirstTrue buildMonoidHaddockHyperlinkSource , boptsInstallExes = defaultFirstFalse buildMonoidInstallExes , boptsInstallCompilerTool = defaultFirstFalse buildMonoidInstallCompilerTool , boptsPreFetch = defaultFirstFalse buildMonoidPreFetch , boptsKeepGoing = Nothing , boptsKeepTmpFiles = defaultFirstFalse buildMonoidKeepTmpFiles , boptsForceDirty = defaultFirstFalse buildMonoidForceDirty , boptsTests = defaultFirstFalse buildMonoidTests , boptsTestOpts = defaultTestOpts , boptsBenchmarks = defaultFirstFalse buildMonoidBenchmarks , boptsBenchmarkOpts = defaultBenchmarkOpts , boptsReconfigure = defaultFirstFalse buildMonoidReconfigure , boptsCabalVerbose = defaultFirstFalse buildMonoidCabalVerbose , boptsSplitObjs = defaultFirstFalse buildMonoidSplitObjs , boptsSkipComponents = [] , boptsInterleavedOutput = defaultFirstTrue buildMonoidInterleavedOutput , boptsDdumpDir = Nothing } defaultBuildOptsCLI ::BuildOptsCLI defaultBuildOptsCLI = BuildOptsCLI { boptsCLITargets = [] , boptsCLIDryrun = False , boptsCLIFlags = Map.empty , boptsCLIGhcOptions = [] , boptsCLIBuildSubset = BSAll , boptsCLIFileWatch = NoFileWatch , boptsCLIWatchAll = False , boptsCLIExec = [] , boptsCLIOnlyConfigure = False , boptsCLICommand = Build , boptsCLIInitialBuildSteps = False } -- | How to apply a CLI flag data ApplyCLIFlag = ACFAllProjectPackages -- ^ Apply to all project packages which have such a flag name available. | ACFByName !PackageName -- ^ Apply to the specified package only. deriving (Show, Eq, Ord) -- | Only flags set via 'ACFByName' boptsCLIFlagsByName :: BuildOptsCLI -> Map PackageName (Map FlagName Bool) boptsCLIFlagsByName = Map.fromList . mapMaybe go . Map.toList . boptsCLIFlags where go (ACFAllProjectPackages, _) = Nothing go (ACFByName name, flags) = Just (name, flags) -- | Build options that may only be specified from the CLI data BuildOptsCLI = BuildOptsCLI { boptsCLITargets :: ![Text] , boptsCLIDryrun :: !Bool , boptsCLIGhcOptions :: ![Text] , boptsCLIFlags :: !(Map ApplyCLIFlag (Map FlagName Bool)) , boptsCLIBuildSubset :: !BuildSubset , boptsCLIFileWatch :: !FileWatchOpts , boptsCLIWatchAll :: !Bool , boptsCLIExec :: ![(String, [String])] , boptsCLIOnlyConfigure :: !Bool , boptsCLICommand :: !BuildCommand , boptsCLIInitialBuildSteps :: !Bool } deriving Show -- | Command sum type for conditional arguments. data BuildCommand = Build | Test | Haddock | Bench | Install deriving (Eq, Show) -- | Build options that may be specified in the stack.yaml or from the CLI data BuildOptsMonoid = BuildOptsMonoid { buildMonoidTrace :: !Any , buildMonoidProfile :: !Any , buildMonoidNoStrip :: !Any , buildMonoidLibProfile :: !FirstFalse , buildMonoidExeProfile :: !FirstFalse , buildMonoidLibStrip :: !FirstTrue , buildMonoidExeStrip :: !FirstTrue , buildMonoidHaddock :: !FirstFalse , buildMonoidHaddockOpts :: !HaddockOptsMonoid , buildMonoidOpenHaddocks :: !FirstFalse , buildMonoidHaddockDeps :: !(First Bool) , buildMonoidHaddockInternal :: !FirstFalse , buildMonoidHaddockHyperlinkSource :: !FirstTrue , buildMonoidInstallExes :: !FirstFalse , buildMonoidInstallCompilerTool :: !FirstFalse , buildMonoidPreFetch :: !FirstFalse , buildMonoidKeepGoing :: !(First Bool) , buildMonoidKeepTmpFiles :: !FirstFalse , buildMonoidForceDirty :: !FirstFalse , buildMonoidTests :: !FirstFalse , buildMonoidTestOpts :: !TestOptsMonoid , buildMonoidBenchmarks :: !FirstFalse , buildMonoidBenchmarkOpts :: !BenchmarkOptsMonoid , buildMonoidReconfigure :: !FirstFalse , buildMonoidCabalVerbose :: !FirstFalse , buildMonoidSplitObjs :: !FirstFalse , buildMonoidSkipComponents :: ![Text] , buildMonoidInterleavedOutput :: !FirstTrue , buildMonoidDdumpDir :: !(First Text) } deriving (Show, Generic) instance FromJSON (WithJSONWarnings BuildOptsMonoid) where parseJSON = withObjectWarnings "BuildOptsMonoid" (\o -> do let buildMonoidTrace = Any False buildMonoidProfile = Any False buildMonoidNoStrip = Any False buildMonoidLibProfile <- FirstFalse <$> o ..:? buildMonoidLibProfileArgName buildMonoidExeProfile <-FirstFalse <$> o ..:? buildMonoidExeProfileArgName buildMonoidLibStrip <- FirstTrue <$> o ..:? buildMonoidLibStripArgName buildMonoidExeStrip <-FirstTrue <$> o ..:? buildMonoidExeStripArgName buildMonoidHaddock <- FirstFalse <$> o ..:? buildMonoidHaddockArgName buildMonoidHaddockOpts <- jsonSubWarnings (o ..:? buildMonoidHaddockOptsArgName ..!= mempty) buildMonoidOpenHaddocks <- FirstFalse <$> o ..:? buildMonoidOpenHaddocksArgName buildMonoidHaddockDeps <- First <$> o ..:? buildMonoidHaddockDepsArgName buildMonoidHaddockInternal <- FirstFalse <$> o ..:? buildMonoidHaddockInternalArgName buildMonoidHaddockHyperlinkSource <- FirstTrue <$> o ..:? buildMonoidHaddockHyperlinkSourceArgName buildMonoidInstallExes <- FirstFalse <$> o ..:? buildMonoidInstallExesArgName buildMonoidInstallCompilerTool <- FirstFalse <$> o ..:? buildMonoidInstallCompilerToolArgName buildMonoidPreFetch <- FirstFalse <$> o ..:? buildMonoidPreFetchArgName buildMonoidKeepGoing <- First <$> o ..:? buildMonoidKeepGoingArgName buildMonoidKeepTmpFiles <- FirstFalse <$> o ..:? buildMonoidKeepTmpFilesArgName buildMonoidForceDirty <- FirstFalse <$> o ..:? buildMonoidForceDirtyArgName buildMonoidTests <- FirstFalse <$> o ..:? buildMonoidTestsArgName buildMonoidTestOpts <- jsonSubWarnings (o ..:? buildMonoidTestOptsArgName ..!= mempty) buildMonoidBenchmarks <- FirstFalse <$> o ..:? buildMonoidBenchmarksArgName buildMonoidBenchmarkOpts <- jsonSubWarnings (o ..:? buildMonoidBenchmarkOptsArgName ..!= mempty) buildMonoidReconfigure <- FirstFalse <$> o ..:? buildMonoidReconfigureArgName buildMonoidCabalVerbose <- FirstFalse <$> o ..:? buildMonoidCabalVerboseArgName buildMonoidSplitObjs <- FirstFalse <$> o ..:? buildMonoidSplitObjsName buildMonoidSkipComponents <- o ..:? buildMonoidSkipComponentsName ..!= mempty buildMonoidInterleavedOutput <- FirstTrue <$> o ..:? buildMonoidInterleavedOutputName buildMonoidDdumpDir <- o ..:? buildMonoidDdumpDirName ..!= mempty return BuildOptsMonoid{..}) buildMonoidLibProfileArgName :: Text buildMonoidLibProfileArgName = "library-profiling" buildMonoidExeProfileArgName :: Text buildMonoidExeProfileArgName = "executable-profiling" buildMonoidLibStripArgName :: Text buildMonoidLibStripArgName = "library-stripping" buildMonoidExeStripArgName :: Text buildMonoidExeStripArgName = "executable-stripping" buildMonoidHaddockArgName :: Text buildMonoidHaddockArgName = "haddock" buildMonoidHaddockOptsArgName :: Text buildMonoidHaddockOptsArgName = "haddock-arguments" buildMonoidOpenHaddocksArgName :: Text buildMonoidOpenHaddocksArgName = "open-haddocks" buildMonoidHaddockDepsArgName :: Text buildMonoidHaddockDepsArgName = "haddock-deps" buildMonoidHaddockInternalArgName :: Text buildMonoidHaddockInternalArgName = "haddock-internal" buildMonoidHaddockHyperlinkSourceArgName :: Text buildMonoidHaddockHyperlinkSourceArgName = "haddock-hyperlink-source" buildMonoidInstallExesArgName :: Text buildMonoidInstallExesArgName = "copy-bins" buildMonoidInstallCompilerToolArgName :: Text buildMonoidInstallCompilerToolArgName = "copy-compiler-tool" buildMonoidPreFetchArgName :: Text buildMonoidPreFetchArgName = "prefetch" buildMonoidKeepGoingArgName :: Text buildMonoidKeepGoingArgName = "keep-going" buildMonoidKeepTmpFilesArgName :: Text buildMonoidKeepTmpFilesArgName = "keep-tmp-files" buildMonoidForceDirtyArgName :: Text buildMonoidForceDirtyArgName = "force-dirty" buildMonoidTestsArgName :: Text buildMonoidTestsArgName = "test" buildMonoidTestOptsArgName :: Text buildMonoidTestOptsArgName = "test-arguments" buildMonoidBenchmarksArgName :: Text buildMonoidBenchmarksArgName = "bench" buildMonoidBenchmarkOptsArgName :: Text buildMonoidBenchmarkOptsArgName = "benchmark-opts" buildMonoidReconfigureArgName :: Text buildMonoidReconfigureArgName = "reconfigure" buildMonoidCabalVerboseArgName :: Text buildMonoidCabalVerboseArgName = "cabal-verbose" buildMonoidSplitObjsName :: Text buildMonoidSplitObjsName = "split-objs" buildMonoidSkipComponentsName :: Text buildMonoidSkipComponentsName = "skip-components" buildMonoidInterleavedOutputName :: Text buildMonoidInterleavedOutputName = "interleaved-output" buildMonoidDdumpDirName :: Text buildMonoidDdumpDirName = "ddump-dir" instance Semigroup BuildOptsMonoid where (<>) = mappenddefault instance Monoid BuildOptsMonoid where mempty = memptydefault mappend = (<>) -- | Which subset of packages to build data BuildSubset = BSAll | BSOnlySnapshot -- ^ Only install packages in the snapshot database, skipping -- packages intended for the local database. | BSOnlyDependencies | BSOnlyLocals -- ^ Refuse to build anything in the snapshot database, see -- https://github.com/commercialhaskell/stack/issues/5272 deriving (Show, Eq) -- | Options for the 'FinalAction' 'DoTests' data TestOpts = TestOpts {toRerunTests :: !Bool -- ^ Whether successful tests will be run gain ,toAdditionalArgs :: ![String] -- ^ Arguments passed to the test program ,toCoverage :: !Bool -- ^ Generate a code coverage report ,toDisableRun :: !Bool -- ^ Disable running of tests ,toMaximumTimeSeconds :: !(Maybe Int) -- ^ test suite timeout in seconds } deriving (Eq,Show) defaultTestOpts :: TestOpts defaultTestOpts = TestOpts { toRerunTests = defaultFirstTrue toMonoidRerunTests , toAdditionalArgs = [] , toCoverage = defaultFirstFalse toMonoidCoverage , toDisableRun = defaultFirstFalse toMonoidDisableRun , toMaximumTimeSeconds = Nothing } data TestOptsMonoid = TestOptsMonoid { toMonoidRerunTests :: !FirstTrue , toMonoidAdditionalArgs :: ![String] , toMonoidCoverage :: !FirstFalse , toMonoidDisableRun :: !FirstFalse , toMonoidMaximumTimeSeconds :: !(First (Maybe Int)) } deriving (Show, Generic) instance FromJSON (WithJSONWarnings TestOptsMonoid) where parseJSON = withObjectWarnings "TestOptsMonoid" (\o -> do toMonoidRerunTests <- FirstTrue <$> o ..:? toMonoidRerunTestsArgName toMonoidAdditionalArgs <- o ..:? toMonoidAdditionalArgsName ..!= [] toMonoidCoverage <- FirstFalse <$> o ..:? toMonoidCoverageArgName toMonoidDisableRun <- FirstFalse <$> o ..:? toMonoidDisableRunArgName toMonoidMaximumTimeSeconds <- First <$> o ..:? toMonoidMaximumTimeSecondsArgName return TestOptsMonoid{..}) toMonoidRerunTestsArgName :: Text toMonoidRerunTestsArgName = "rerun-tests" toMonoidAdditionalArgsName :: Text toMonoidAdditionalArgsName = "additional-args" toMonoidCoverageArgName :: Text toMonoidCoverageArgName = "coverage" toMonoidDisableRunArgName :: Text toMonoidDisableRunArgName = "no-run-tests" toMonoidMaximumTimeSecondsArgName :: Text toMonoidMaximumTimeSecondsArgName = "test-suite-timeout" instance Semigroup TestOptsMonoid where (<>) = mappenddefault instance Monoid TestOptsMonoid where mempty = memptydefault mappend = (<>) -- | Haddock Options newtype HaddockOpts = HaddockOpts { hoAdditionalArgs :: [String] -- ^ Arguments passed to haddock program } deriving (Eq,Show) newtype HaddockOptsMonoid = HaddockOptsMonoid {hoMonoidAdditionalArgs :: [String] } deriving (Show, Generic) defaultHaddockOpts :: HaddockOpts defaultHaddockOpts = HaddockOpts {hoAdditionalArgs = []} instance FromJSON (WithJSONWarnings HaddockOptsMonoid) where parseJSON = withObjectWarnings "HaddockOptsMonoid" (\o -> do hoMonoidAdditionalArgs <- o ..:? hoMonoidAdditionalArgsName ..!= [] return HaddockOptsMonoid{..}) instance Semigroup HaddockOptsMonoid where (<>) = mappenddefault instance Monoid HaddockOptsMonoid where mempty = memptydefault mappend = (<>) hoMonoidAdditionalArgsName :: Text hoMonoidAdditionalArgsName = "haddock-args" -- | Options for the 'FinalAction' 'DoBenchmarks' data BenchmarkOpts = BenchmarkOpts { beoAdditionalArgs :: !(Maybe String) -- ^ Arguments passed to the benchmark program , beoDisableRun :: !Bool -- ^ Disable running of benchmarks } deriving (Eq,Show) defaultBenchmarkOpts :: BenchmarkOpts defaultBenchmarkOpts = BenchmarkOpts { beoAdditionalArgs = Nothing , beoDisableRun = False } data BenchmarkOptsMonoid = BenchmarkOptsMonoid { beoMonoidAdditionalArgs :: !(First String) , beoMonoidDisableRun :: !(First Bool) } deriving (Show, Generic) instance FromJSON (WithJSONWarnings BenchmarkOptsMonoid) where parseJSON = withObjectWarnings "BenchmarkOptsMonoid" (\o -> do beoMonoidAdditionalArgs <- First <$> o ..:? beoMonoidAdditionalArgsArgName beoMonoidDisableRun <- First <$> o ..:? beoMonoidDisableRunArgName return BenchmarkOptsMonoid{..}) beoMonoidAdditionalArgsArgName :: Text beoMonoidAdditionalArgsArgName = "benchmark-arguments" beoMonoidDisableRunArgName :: Text beoMonoidDisableRunArgName = "no-run-benchmarks" instance Semigroup BenchmarkOptsMonoid where (<>) = mappenddefault instance Monoid BenchmarkOptsMonoid where mempty = memptydefault mappend = (<>) data FileWatchOpts = NoFileWatch | FileWatch | FileWatchPoll deriving (Show,Eq)