1{-# LANGUAGE NoImplicitPrelude #-} 2{-# LANGUAGE DeriveGeneric #-} 3{-# LANGUAGE FlexibleInstances #-} 4{-# LANGUAGE OverloadedStrings #-} 5{-# LANGUAGE RecordWildCards #-} 6 7-- | Configuration options for building. 8 9module Stack.Types.Config.Build 10 ( 11 BuildOpts(..) 12 , BuildCommand(..) 13 , defaultBuildOpts 14 , defaultBuildOptsCLI 15 , BuildOptsCLI(..) 16 , BuildOptsMonoid(..) 17 , TestOpts(..) 18 , defaultTestOpts 19 , TestOptsMonoid(..) 20 , HaddockOpts(..) 21 , defaultHaddockOpts 22 , HaddockOptsMonoid(..) 23 , BenchmarkOpts(..) 24 , defaultBenchmarkOpts 25 , BenchmarkOptsMonoid(..) 26 , FileWatchOpts(..) 27 , BuildSubset(..) 28 , ApplyCLIFlag (..) 29 , boptsCLIFlagsByName 30 ) 31 where 32 33import Pantry.Internal.AesonExtended 34import qualified Data.Map.Strict as Map 35import Generics.Deriving.Monoid (memptydefault, mappenddefault) 36import Stack.Prelude 37 38-- | Build options that is interpreted by the build command. 39-- This is built up from BuildOptsCLI and BuildOptsMonoid 40data BuildOpts = 41 BuildOpts {boptsLibProfile :: !Bool 42 ,boptsExeProfile :: !Bool 43 ,boptsLibStrip :: !Bool 44 ,boptsExeStrip :: !Bool 45 ,boptsHaddock :: !Bool 46 -- ^ Build haddocks? 47 ,boptsHaddockOpts :: !HaddockOpts 48 -- ^ Options to pass to haddock 49 ,boptsOpenHaddocks :: !Bool 50 -- ^ Open haddocks in the browser? 51 ,boptsHaddockDeps :: !(Maybe Bool) 52 -- ^ Build haddocks for dependencies? 53 ,boptsHaddockInternal :: !Bool 54 -- ^ Build haddocks for all symbols and packages, like @cabal haddock --internal@ 55 ,boptsHaddockHyperlinkSource :: !Bool 56 -- ^ Build hyperlinked source if possible. Fallback to 57 -- @hscolour@. Disable for no sources. 58 ,boptsInstallExes :: !Bool 59 -- ^ Install executables to user path after building? 60 ,boptsInstallCompilerTool :: !Bool 61 -- ^ Install executables to compiler tools path after building? 62 ,boptsPreFetch :: !Bool 63 -- ^ Fetch all packages immediately 64 -- ^ Watch files for changes and automatically rebuild 65 ,boptsKeepGoing :: !(Maybe Bool) 66 -- ^ Keep building/running after failure 67 ,boptsKeepTmpFiles :: !Bool 68 -- ^ Keep intermediate files and build directories 69 ,boptsForceDirty :: !Bool 70 -- ^ Force treating all local packages as having dirty files 71 72 ,boptsTests :: !Bool 73 -- ^ Turn on tests for local targets 74 ,boptsTestOpts :: !TestOpts 75 -- ^ Additional test arguments 76 77 ,boptsBenchmarks :: !Bool 78 -- ^ Turn on benchmarks for local targets 79 ,boptsBenchmarkOpts :: !BenchmarkOpts 80 -- ^ Additional test arguments 81 -- ^ Commands (with arguments) to run after a successful build 82 -- ^ Only perform the configure step when building 83 ,boptsReconfigure :: !Bool 84 -- ^ Perform the configure step even if already configured 85 ,boptsCabalVerbose :: !Bool 86 -- ^ Ask Cabal to be verbose in its builds 87 ,boptsSplitObjs :: !Bool 88 -- ^ Whether to enable split-objs. 89 ,boptsSkipComponents :: ![Text] 90 -- ^ Which components to skip when building 91 ,boptsInterleavedOutput :: !Bool 92 -- ^ Should we use the interleaved GHC output when building 93 -- multiple packages? 94 ,boptsDdumpDir :: !(Maybe Text) 95 } 96 deriving (Show) 97 98defaultBuildOpts :: BuildOpts 99defaultBuildOpts = BuildOpts 100 { boptsLibProfile = defaultFirstFalse buildMonoidLibProfile 101 , boptsExeProfile = defaultFirstFalse buildMonoidExeProfile 102 , boptsLibStrip = defaultFirstTrue buildMonoidLibStrip 103 , boptsExeStrip = defaultFirstTrue buildMonoidExeStrip 104 , boptsHaddock = False 105 , boptsHaddockOpts = defaultHaddockOpts 106 , boptsOpenHaddocks = defaultFirstFalse buildMonoidOpenHaddocks 107 , boptsHaddockDeps = Nothing 108 , boptsHaddockInternal = defaultFirstFalse buildMonoidHaddockInternal 109 , boptsHaddockHyperlinkSource = defaultFirstTrue buildMonoidHaddockHyperlinkSource 110 , boptsInstallExes = defaultFirstFalse buildMonoidInstallExes 111 , boptsInstallCompilerTool = defaultFirstFalse buildMonoidInstallCompilerTool 112 , boptsPreFetch = defaultFirstFalse buildMonoidPreFetch 113 , boptsKeepGoing = Nothing 114 , boptsKeepTmpFiles = defaultFirstFalse buildMonoidKeepTmpFiles 115 , boptsForceDirty = defaultFirstFalse buildMonoidForceDirty 116 , boptsTests = defaultFirstFalse buildMonoidTests 117 , boptsTestOpts = defaultTestOpts 118 , boptsBenchmarks = defaultFirstFalse buildMonoidBenchmarks 119 , boptsBenchmarkOpts = defaultBenchmarkOpts 120 , boptsReconfigure = defaultFirstFalse buildMonoidReconfigure 121 , boptsCabalVerbose = defaultFirstFalse buildMonoidCabalVerbose 122 , boptsSplitObjs = defaultFirstFalse buildMonoidSplitObjs 123 , boptsSkipComponents = [] 124 , boptsInterleavedOutput = defaultFirstTrue buildMonoidInterleavedOutput 125 , boptsDdumpDir = Nothing 126 } 127 128defaultBuildOptsCLI ::BuildOptsCLI 129defaultBuildOptsCLI = BuildOptsCLI 130 { boptsCLITargets = [] 131 , boptsCLIDryrun = False 132 , boptsCLIFlags = Map.empty 133 , boptsCLIGhcOptions = [] 134 , boptsCLIBuildSubset = BSAll 135 , boptsCLIFileWatch = NoFileWatch 136 , boptsCLIWatchAll = False 137 , boptsCLIExec = [] 138 , boptsCLIOnlyConfigure = False 139 , boptsCLICommand = Build 140 , boptsCLIInitialBuildSteps = False 141 } 142 143-- | How to apply a CLI flag 144data ApplyCLIFlag 145 = ACFAllProjectPackages 146 -- ^ Apply to all project packages which have such a flag name available. 147 | ACFByName !PackageName 148 -- ^ Apply to the specified package only. 149 deriving (Show, Eq, Ord) 150 151-- | Only flags set via 'ACFByName' 152boptsCLIFlagsByName :: BuildOptsCLI -> Map PackageName (Map FlagName Bool) 153boptsCLIFlagsByName = 154 Map.fromList . 155 mapMaybe go . 156 Map.toList . 157 boptsCLIFlags 158 where 159 go (ACFAllProjectPackages, _) = Nothing 160 go (ACFByName name, flags) = Just (name, flags) 161 162-- | Build options that may only be specified from the CLI 163data BuildOptsCLI = BuildOptsCLI 164 { boptsCLITargets :: ![Text] 165 , boptsCLIDryrun :: !Bool 166 , boptsCLIGhcOptions :: ![Text] 167 , boptsCLIFlags :: !(Map ApplyCLIFlag (Map FlagName Bool)) 168 , boptsCLIBuildSubset :: !BuildSubset 169 , boptsCLIFileWatch :: !FileWatchOpts 170 , boptsCLIWatchAll :: !Bool 171 , boptsCLIExec :: ![(String, [String])] 172 , boptsCLIOnlyConfigure :: !Bool 173 , boptsCLICommand :: !BuildCommand 174 , boptsCLIInitialBuildSteps :: !Bool 175 } deriving Show 176 177-- | Command sum type for conditional arguments. 178data BuildCommand 179 = Build 180 | Test 181 | Haddock 182 | Bench 183 | Install 184 deriving (Eq, Show) 185 186-- | Build options that may be specified in the stack.yaml or from the CLI 187data BuildOptsMonoid = BuildOptsMonoid 188 { buildMonoidTrace :: !Any 189 , buildMonoidProfile :: !Any 190 , buildMonoidNoStrip :: !Any 191 , buildMonoidLibProfile :: !FirstFalse 192 , buildMonoidExeProfile :: !FirstFalse 193 , buildMonoidLibStrip :: !FirstTrue 194 , buildMonoidExeStrip :: !FirstTrue 195 , buildMonoidHaddock :: !FirstFalse 196 , buildMonoidHaddockOpts :: !HaddockOptsMonoid 197 , buildMonoidOpenHaddocks :: !FirstFalse 198 , buildMonoidHaddockDeps :: !(First Bool) 199 , buildMonoidHaddockInternal :: !FirstFalse 200 , buildMonoidHaddockHyperlinkSource :: !FirstTrue 201 , buildMonoidInstallExes :: !FirstFalse 202 , buildMonoidInstallCompilerTool :: !FirstFalse 203 , buildMonoidPreFetch :: !FirstFalse 204 , buildMonoidKeepGoing :: !(First Bool) 205 , buildMonoidKeepTmpFiles :: !FirstFalse 206 , buildMonoidForceDirty :: !FirstFalse 207 , buildMonoidTests :: !FirstFalse 208 , buildMonoidTestOpts :: !TestOptsMonoid 209 , buildMonoidBenchmarks :: !FirstFalse 210 , buildMonoidBenchmarkOpts :: !BenchmarkOptsMonoid 211 , buildMonoidReconfigure :: !FirstFalse 212 , buildMonoidCabalVerbose :: !FirstFalse 213 , buildMonoidSplitObjs :: !FirstFalse 214 , buildMonoidSkipComponents :: ![Text] 215 , buildMonoidInterleavedOutput :: !FirstTrue 216 , buildMonoidDdumpDir :: !(First Text) 217 } deriving (Show, Generic) 218 219instance FromJSON (WithJSONWarnings BuildOptsMonoid) where 220 parseJSON = withObjectWarnings "BuildOptsMonoid" 221 (\o -> do let buildMonoidTrace = Any False 222 buildMonoidProfile = Any False 223 buildMonoidNoStrip = Any False 224 buildMonoidLibProfile <- FirstFalse <$> o ..:? buildMonoidLibProfileArgName 225 buildMonoidExeProfile <-FirstFalse <$> o ..:? buildMonoidExeProfileArgName 226 buildMonoidLibStrip <- FirstTrue <$> o ..:? buildMonoidLibStripArgName 227 buildMonoidExeStrip <-FirstTrue <$> o ..:? buildMonoidExeStripArgName 228 buildMonoidHaddock <- FirstFalse <$> o ..:? buildMonoidHaddockArgName 229 buildMonoidHaddockOpts <- jsonSubWarnings (o ..:? buildMonoidHaddockOptsArgName ..!= mempty) 230 buildMonoidOpenHaddocks <- FirstFalse <$> o ..:? buildMonoidOpenHaddocksArgName 231 buildMonoidHaddockDeps <- First <$> o ..:? buildMonoidHaddockDepsArgName 232 buildMonoidHaddockInternal <- FirstFalse <$> o ..:? buildMonoidHaddockInternalArgName 233 buildMonoidHaddockHyperlinkSource <- FirstTrue <$> o ..:? buildMonoidHaddockHyperlinkSourceArgName 234 buildMonoidInstallExes <- FirstFalse <$> o ..:? buildMonoidInstallExesArgName 235 buildMonoidInstallCompilerTool <- FirstFalse <$> o ..:? buildMonoidInstallCompilerToolArgName 236 buildMonoidPreFetch <- FirstFalse <$> o ..:? buildMonoidPreFetchArgName 237 buildMonoidKeepGoing <- First <$> o ..:? buildMonoidKeepGoingArgName 238 buildMonoidKeepTmpFiles <- FirstFalse <$> o ..:? buildMonoidKeepTmpFilesArgName 239 buildMonoidForceDirty <- FirstFalse <$> o ..:? buildMonoidForceDirtyArgName 240 buildMonoidTests <- FirstFalse <$> o ..:? buildMonoidTestsArgName 241 buildMonoidTestOpts <- jsonSubWarnings (o ..:? buildMonoidTestOptsArgName ..!= mempty) 242 buildMonoidBenchmarks <- FirstFalse <$> o ..:? buildMonoidBenchmarksArgName 243 buildMonoidBenchmarkOpts <- jsonSubWarnings (o ..:? buildMonoidBenchmarkOptsArgName ..!= mempty) 244 buildMonoidReconfigure <- FirstFalse <$> o ..:? buildMonoidReconfigureArgName 245 buildMonoidCabalVerbose <- FirstFalse <$> o ..:? buildMonoidCabalVerboseArgName 246 buildMonoidSplitObjs <- FirstFalse <$> o ..:? buildMonoidSplitObjsName 247 buildMonoidSkipComponents <- o ..:? buildMonoidSkipComponentsName ..!= mempty 248 buildMonoidInterleavedOutput <- FirstTrue <$> o ..:? buildMonoidInterleavedOutputName 249 buildMonoidDdumpDir <- o ..:? buildMonoidDdumpDirName ..!= mempty 250 return BuildOptsMonoid{..}) 251 252buildMonoidLibProfileArgName :: Text 253buildMonoidLibProfileArgName = "library-profiling" 254 255buildMonoidExeProfileArgName :: Text 256buildMonoidExeProfileArgName = "executable-profiling" 257 258buildMonoidLibStripArgName :: Text 259buildMonoidLibStripArgName = "library-stripping" 260 261buildMonoidExeStripArgName :: Text 262buildMonoidExeStripArgName = "executable-stripping" 263 264buildMonoidHaddockArgName :: Text 265buildMonoidHaddockArgName = "haddock" 266 267buildMonoidHaddockOptsArgName :: Text 268buildMonoidHaddockOptsArgName = "haddock-arguments" 269 270buildMonoidOpenHaddocksArgName :: Text 271buildMonoidOpenHaddocksArgName = "open-haddocks" 272 273buildMonoidHaddockDepsArgName :: Text 274buildMonoidHaddockDepsArgName = "haddock-deps" 275 276buildMonoidHaddockInternalArgName :: Text 277buildMonoidHaddockInternalArgName = "haddock-internal" 278 279buildMonoidHaddockHyperlinkSourceArgName :: Text 280buildMonoidHaddockHyperlinkSourceArgName = "haddock-hyperlink-source" 281 282buildMonoidInstallExesArgName :: Text 283buildMonoidInstallExesArgName = "copy-bins" 284 285buildMonoidInstallCompilerToolArgName :: Text 286buildMonoidInstallCompilerToolArgName = "copy-compiler-tool" 287 288buildMonoidPreFetchArgName :: Text 289buildMonoidPreFetchArgName = "prefetch" 290 291buildMonoidKeepGoingArgName :: Text 292buildMonoidKeepGoingArgName = "keep-going" 293 294buildMonoidKeepTmpFilesArgName :: Text 295buildMonoidKeepTmpFilesArgName = "keep-tmp-files" 296 297buildMonoidForceDirtyArgName :: Text 298buildMonoidForceDirtyArgName = "force-dirty" 299 300buildMonoidTestsArgName :: Text 301buildMonoidTestsArgName = "test" 302 303buildMonoidTestOptsArgName :: Text 304buildMonoidTestOptsArgName = "test-arguments" 305 306buildMonoidBenchmarksArgName :: Text 307buildMonoidBenchmarksArgName = "bench" 308 309buildMonoidBenchmarkOptsArgName :: Text 310buildMonoidBenchmarkOptsArgName = "benchmark-opts" 311 312buildMonoidReconfigureArgName :: Text 313buildMonoidReconfigureArgName = "reconfigure" 314 315buildMonoidCabalVerboseArgName :: Text 316buildMonoidCabalVerboseArgName = "cabal-verbose" 317 318buildMonoidSplitObjsName :: Text 319buildMonoidSplitObjsName = "split-objs" 320 321buildMonoidSkipComponentsName :: Text 322buildMonoidSkipComponentsName = "skip-components" 323 324buildMonoidInterleavedOutputName :: Text 325buildMonoidInterleavedOutputName = "interleaved-output" 326 327buildMonoidDdumpDirName :: Text 328buildMonoidDdumpDirName = "ddump-dir" 329 330instance Semigroup BuildOptsMonoid where 331 (<>) = mappenddefault 332 333instance Monoid BuildOptsMonoid where 334 mempty = memptydefault 335 mappend = (<>) 336 337-- | Which subset of packages to build 338data BuildSubset 339 = BSAll 340 | BSOnlySnapshot 341 -- ^ Only install packages in the snapshot database, skipping 342 -- packages intended for the local database. 343 | BSOnlyDependencies 344 | BSOnlyLocals 345 -- ^ Refuse to build anything in the snapshot database, see 346 -- https://github.com/commercialhaskell/stack/issues/5272 347 deriving (Show, Eq) 348 349-- | Options for the 'FinalAction' 'DoTests' 350data TestOpts = 351 TestOpts {toRerunTests :: !Bool -- ^ Whether successful tests will be run gain 352 ,toAdditionalArgs :: ![String] -- ^ Arguments passed to the test program 353 ,toCoverage :: !Bool -- ^ Generate a code coverage report 354 ,toDisableRun :: !Bool -- ^ Disable running of tests 355 ,toMaximumTimeSeconds :: !(Maybe Int) -- ^ test suite timeout in seconds 356 } deriving (Eq,Show) 357 358defaultTestOpts :: TestOpts 359defaultTestOpts = TestOpts 360 { toRerunTests = defaultFirstTrue toMonoidRerunTests 361 , toAdditionalArgs = [] 362 , toCoverage = defaultFirstFalse toMonoidCoverage 363 , toDisableRun = defaultFirstFalse toMonoidDisableRun 364 , toMaximumTimeSeconds = Nothing 365 } 366 367data TestOptsMonoid = 368 TestOptsMonoid 369 { toMonoidRerunTests :: !FirstTrue 370 , toMonoidAdditionalArgs :: ![String] 371 , toMonoidCoverage :: !FirstFalse 372 , toMonoidDisableRun :: !FirstFalse 373 , toMonoidMaximumTimeSeconds :: !(First (Maybe Int)) 374 } deriving (Show, Generic) 375 376instance FromJSON (WithJSONWarnings TestOptsMonoid) where 377 parseJSON = withObjectWarnings "TestOptsMonoid" 378 (\o -> do toMonoidRerunTests <- FirstTrue <$> o ..:? toMonoidRerunTestsArgName 379 toMonoidAdditionalArgs <- o ..:? toMonoidAdditionalArgsName ..!= [] 380 toMonoidCoverage <- FirstFalse <$> o ..:? toMonoidCoverageArgName 381 toMonoidDisableRun <- FirstFalse <$> o ..:? toMonoidDisableRunArgName 382 toMonoidMaximumTimeSeconds <- First <$> o ..:? toMonoidMaximumTimeSecondsArgName 383 return TestOptsMonoid{..}) 384 385toMonoidRerunTestsArgName :: Text 386toMonoidRerunTestsArgName = "rerun-tests" 387 388toMonoidAdditionalArgsName :: Text 389toMonoidAdditionalArgsName = "additional-args" 390 391toMonoidCoverageArgName :: Text 392toMonoidCoverageArgName = "coverage" 393 394toMonoidDisableRunArgName :: Text 395toMonoidDisableRunArgName = "no-run-tests" 396 397toMonoidMaximumTimeSecondsArgName :: Text 398toMonoidMaximumTimeSecondsArgName = "test-suite-timeout" 399 400instance Semigroup TestOptsMonoid where 401 (<>) = mappenddefault 402 403instance Monoid TestOptsMonoid where 404 mempty = memptydefault 405 mappend = (<>) 406 407 408 409-- | Haddock Options 410newtype HaddockOpts = 411 HaddockOpts { hoAdditionalArgs :: [String] -- ^ Arguments passed to haddock program 412 } deriving (Eq,Show) 413 414newtype HaddockOptsMonoid = 415 HaddockOptsMonoid {hoMonoidAdditionalArgs :: [String] 416 } deriving (Show, Generic) 417 418defaultHaddockOpts :: HaddockOpts 419defaultHaddockOpts = HaddockOpts {hoAdditionalArgs = []} 420 421instance FromJSON (WithJSONWarnings HaddockOptsMonoid) where 422 parseJSON = withObjectWarnings "HaddockOptsMonoid" 423 (\o -> do hoMonoidAdditionalArgs <- o ..:? hoMonoidAdditionalArgsName ..!= [] 424 return HaddockOptsMonoid{..}) 425 426instance Semigroup HaddockOptsMonoid where 427 (<>) = mappenddefault 428 429instance Monoid HaddockOptsMonoid where 430 mempty = memptydefault 431 mappend = (<>) 432 433hoMonoidAdditionalArgsName :: Text 434hoMonoidAdditionalArgsName = "haddock-args" 435 436 437-- | Options for the 'FinalAction' 'DoBenchmarks' 438data BenchmarkOpts = 439 BenchmarkOpts 440 { beoAdditionalArgs :: !(Maybe String) -- ^ Arguments passed to the benchmark program 441 , beoDisableRun :: !Bool -- ^ Disable running of benchmarks 442 } deriving (Eq,Show) 443 444defaultBenchmarkOpts :: BenchmarkOpts 445defaultBenchmarkOpts = BenchmarkOpts 446 { beoAdditionalArgs = Nothing 447 , beoDisableRun = False 448 } 449 450data BenchmarkOptsMonoid = 451 BenchmarkOptsMonoid 452 { beoMonoidAdditionalArgs :: !(First String) 453 , beoMonoidDisableRun :: !(First Bool) 454 } deriving (Show, Generic) 455 456instance FromJSON (WithJSONWarnings BenchmarkOptsMonoid) where 457 parseJSON = withObjectWarnings "BenchmarkOptsMonoid" 458 (\o -> do beoMonoidAdditionalArgs <- First <$> o ..:? beoMonoidAdditionalArgsArgName 459 beoMonoidDisableRun <- First <$> o ..:? beoMonoidDisableRunArgName 460 return BenchmarkOptsMonoid{..}) 461 462beoMonoidAdditionalArgsArgName :: Text 463beoMonoidAdditionalArgsArgName = "benchmark-arguments" 464 465beoMonoidDisableRunArgName :: Text 466beoMonoidDisableRunArgName = "no-run-benchmarks" 467 468instance Semigroup BenchmarkOptsMonoid where 469 (<>) = mappenddefault 470 471instance Monoid BenchmarkOptsMonoid where 472 mempty = memptydefault 473 mappend = (<>) 474 475data FileWatchOpts 476 = NoFileWatch 477 | FileWatch 478 | FileWatchPoll 479 deriving (Show,Eq) 480