Setup.hs 109 KB
Newer Older
Edsko de Vries's avatar
Edsko de Vries committed
1
{-# LANGUAGE ScopedTypeVariables #-}
2 3 4 5
{-# LANGUAGE RecordWildCards     #-}
{-# LANGUAGE RankNTypes          #-}
{-# LANGUAGE DeriveGeneric       #-}
{-# LANGUAGE LambdaCase          #-}
6 7
-----------------------------------------------------------------------------
-- |
8
-- Module      :  Distribution.Client.Setup
9 10 11 12 13 14 15 16 17
-- Copyright   :  (c) David Himmelstrup 2005
-- License     :  BSD-like
--
-- Maintainer  :  lemmih@gmail.com
-- Stability   :  provisional
-- Portability :  portable
--
--
-----------------------------------------------------------------------------
18
module Distribution.Client.Setup
Edsko de Vries's avatar
Edsko de Vries committed
19 20
    ( globalCommand, GlobalFlags(..), defaultGlobalFlags
    , RepoContext(..), withRepoContext
21
    , configureCommand, ConfigFlags(..), configureOptions, filterConfigureFlags
22
    , configPackageDB', configCompilerAux'
23
    , configureExCommand, ConfigExFlags(..), defaultConfigExFlags
Oleg Grenrus's avatar
Oleg Grenrus committed
24
    , buildCommand, BuildFlags(..)
25
    , filterTestFlags
26
    , replCommand, testCommand, benchmarkCommand, testOptions, benchmarkOptions
ttuegel's avatar
ttuegel committed
27
                        , configureExOptions, reconfigureCommand
28
    , installCommand, InstallFlags(..), installOptions, defaultInstallFlags
29
    , filterHaddockArgs, filterHaddockFlags, haddockOptions
30
    , defaultSolver, defaultMaxBackjumps
31
    , listCommand, ListFlags(..), listNeedsCompiler
Moritz Angermann's avatar
Moritz Angermann committed
32
    , updateCommand, UpdateFlags(..), defaultUpdateFlags
33
    , infoCommand, InfoFlags(..)
34
    , fetchCommand, FetchFlags(..)
35
    , freezeCommand, FreezeFlags(..)
36
    , genBoundsCommand
37
    , outdatedCommand, OutdatedFlags(..), IgnoreMajorVersionBumps(..)
38
    , getCommand, unpackCommand, GetFlags(..)
39
    , checkCommand
40
    , formatCommand
41
    , uploadCommand, UploadFlags(..), IsCandidate(..)
42
    , reportCommand, ReportFlags(..)
refold's avatar
refold committed
43
    , runCommand
44
    , initCommand, initOptions, IT.InitFlags(..)
45
    , actAsSetupCommand, ActAsSetupFlags(..)
Daniel Wagner's avatar
Daniel Wagner committed
46
    , execCommand, ExecFlags(..), defaultExecFlags
47
    , userConfigCommand, UserConfigFlags(..)
Maciek Makowski's avatar
Maciek Makowski committed
48
    , manpageCommand
49 50
    , haddockCommand
    , cleanCommand
51 52 53
    , doctestCommand
    , copyCommand
    , registerCommand
54 55

    , parsePackageArgs
Alexis Williams's avatar
Alexis Williams committed
56
    , liftOptions
57
    , yesNoOpt
58 59
    ) where

60 61 62
import Prelude ()
import Distribution.Client.Compat.Prelude hiding (get)

Oleg Grenrus's avatar
Oleg Grenrus committed
63 64 65 66 67
import Distribution.Client.Types.Credentials (Username (..), Password (..))
import Distribution.Client.Types.Repo (RemoteRepo(..), LocalRepo (..))
import Distribution.Client.Types.AllowNewer (AllowNewer(..), AllowOlder(..), RelaxDeps(..))
import Distribution.Client.Types.WriteGhcEnvironmentFilesPolicy

68 69
import Distribution.Client.BuildReports.Types
         ( ReportLevel(..) )
70
import Distribution.Client.Dependency.Types
71
         ( PreSolver(..) )
72 73
import Distribution.Client.IndexUtils.ActiveRepos
         ( ActiveRepos )
Oleg Grenrus's avatar
Oleg Grenrus committed
74
import Distribution.Client.IndexUtils.IndexState
75
         ( TotalIndexState, headTotalIndexState )
76
import qualified Distribution.Client.Init.Types as IT
77
         ( InitFlags(..), PackageType(..), defaultInitFlags )
78 79
import Distribution.Client.Targets
         ( UserConstraint, readUserConstraint )
80 81
import Distribution.Utils.NubList
         ( NubList, toNubList, fromNubList)
82

83
import Distribution.Solver.Types.ConstraintSource
84
import Distribution.Solver.Types.Settings
85

86 87
import Distribution.Simple.Compiler ( Compiler, PackageDB, PackageDBStack )
import Distribution.Simple.Program (ProgramDb, defaultProgramDb)
88 89
import Distribution.Simple.Command hiding (boolOpt, boolOpt')
import qualified Distribution.Simple.Command as Command
90
import Distribution.Simple.Configure
91
       ( configCompilerAuxEx, interpretPackageDbFlags, computeEffectiveProfiling )
92
import qualified Distribution.Simple.Setup as Cabal
93 94 95 96
import Distribution.Simple.Flag
         ( Flag(..), toFlag, flagToMaybe, flagToList, maybeToFlag
         , flagElim, fromFlagOrDefault
         )
97
import Distribution.Simple.Setup
98
         ( ConfigFlags(..), BuildFlags(..), ReplFlags
99
         , TestFlags, BenchmarkFlags
Oleg Grenrus's avatar
Oleg Grenrus committed
100
         , HaddockFlags(..)
101 102
         , CleanFlags(..), DoctestFlags(..)
         , CopyFlags(..), RegisterFlags(..)
103
         , readPackageDbList, showPackageDbList
104 105
         , BooleanFlag(..), optionVerbosity
         , boolOpt, boolOpt', trueArg, falseArg
106
         , optionNumJobs )
107
import Distribution.Simple.InstallDirs
108 109
         ( PathTemplate, InstallDirs(..)
         , toPathTemplate, fromPathTemplate, combinePathTemplate )
110
import Distribution.Version
111
         ( Version, mkVersion )
112
import Distribution.Package
113
         ( PackageName )
114 115
import Distribution.Types.GivenComponent
         ( GivenComponent(..) )
116 117
import Distribution.Types.PackageVersionConstraint
         ( PackageVersionConstraint(..) )
118
import Distribution.Types.UnqualComponentName
119
         ( unqualComponentNameToPackageName )
120
import Distribution.PackageDescription
121
         ( BuildType(..), RepoKind(..), LibraryName(..) )
122
import Distribution.System ( Platform )
123
import Distribution.ReadE
Oleg Grenrus's avatar
Oleg Grenrus committed
124
         ( ReadE(..), succeedReadE, parsecToReadE )
125
import qualified Distribution.Compat.CharParsing as P
126
import Distribution.Verbosity
127
         ( lessVerbose, normal, verboseNoFlags, verboseNoTimestamp )
128
import Distribution.Simple.Utils
Oleg Grenrus's avatar
Oleg Grenrus committed
129
         ( wrapText )
130
import Distribution.Client.GlobalFlags
Edsko de Vries's avatar
Edsko de Vries committed
131 132 133
         ( GlobalFlags(..), defaultGlobalFlags
         , RepoContext(..), withRepoContext
         )
Oleg Grenrus's avatar
Oleg Grenrus committed
134
import Distribution.Client.ManpageFlags (ManpageFlags, defaultManpageFlags, manpageOptions)
135
import Distribution.FieldGrammar.Newtypes (SpecVersion (..))
136

137
import Data.List
138
         ( deleteFirstsBy )
139 140
import System.FilePath
         ( (</>) )
141

142 143
globalCommand :: [Command action] -> CommandUI GlobalFlags
globalCommand commands = CommandUI {
144
    commandName         = "",
145 146
    commandSynopsis     =
         "Command line interface to the Haskell Cabal infrastructure.",
147 148 149 150
    commandUsage        = \pname ->
         "See http://www.haskell.org/cabal/ for more information.\n"
      ++ "\n"
      ++ "Usage: " ++ pname ++ " [GLOBAL FLAGS] [COMMAND [FLAGS]]\n",
151
    commandDescription  = Just $ \pname ->
152 153 154
      let
        commands' = commands ++ [commandAddAction helpCommandUI undefined]
        cmdDescs = getNormalCommandDescriptions commands'
155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182
        -- if new commands are added, we want them to appear even if they
        -- are not included in the custom listing below. Thus, we calculate
        -- the `otherCmds` list and append it under the `other` category.
        -- Alternatively, a new testcase could be added that ensures that
        -- the set of commands listed here is equal to the set of commands
        -- that are actually available.
        otherCmds = deleteFirstsBy (==) (map fst cmdDescs)
          [ "help"
          , "update"
          , "install"
          , "fetch"
          , "list"
          , "info"
          , "user-config"
          , "get"
          , "init"
          , "configure"
          , "build"
          , "clean"
          , "run"
          , "repl"
          , "test"
          , "bench"
          , "check"
          , "sdist"
          , "upload"
          , "report"
          , "freeze"
183
          , "gen-bounds"
184
          , "outdated"
185 186 187
          , "haddock"
          , "hscolour"
          , "exec"
188 189 190 191
          , "new-build"
          , "new-configure"
          , "new-repl"
          , "new-freeze"
192 193 194
          , "new-run"
          , "new-test"
          , "new-bench"
195
          , "new-haddock"
196 197 198
          , "new-exec"
          , "new-update"
          , "new-install"
199
          , "new-clean"
Alexis Williams's avatar
Alexis Williams committed
200
          , "new-sdist"
Oleg Grenrus's avatar
Oleg Grenrus committed
201
          , "list-bin"
202
          -- v1 commands, stateful style
203 204 205 206 207 208 209 210 211 212 213 214
          , "v1-build"
          , "v1-configure"
          , "v1-repl"
          , "v1-freeze"
          , "v1-run"
          , "v1-test"
          , "v1-bench"
          , "v1-haddock"
          , "v1-exec"
          , "v1-update"
          , "v1-install"
          , "v1-clean"
215 216 217 218 219
          , "v1-sdist"
          , "v1-doctest"
          , "v1-copy"
          , "v1-register"
          , "v1-reconfigure"
220 221 222 223 224 225 226 227 228 229 230 231 232 233
          -- v2 commands, nix-style
          , "v2-build"
          , "v2-configure"
          , "v2-repl"
          , "v2-freeze"
          , "v2-run"
          , "v2-test"
          , "v2-bench"
          , "v2-haddock"
          , "v2-exec"
          , "v2-update"
          , "v2-install"
          , "v2-clean"
          , "v2-sdist"
234
          ]
235 236
        maxlen    = maximum $ [length name | (name, _) <- cmdDescs]
        align str = str ++ replicate (maxlen - length str) ' '
237 238 239 240 241
        startGroup n = " ["++n++"]"
        par          = ""
        addCmd n     = case lookup n cmdDescs of
                         Nothing -> ""
                         Just d -> "  " ++ align n ++ "    " ++ d
242 243
      in
         "Commands:\n"
244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273
      ++ unlines (
        [ startGroup "global"
        , addCmd "update"
        , addCmd "install"
        , par
        , addCmd "help"
        , addCmd "info"
        , addCmd "list"
        , addCmd "fetch"
        , addCmd "user-config"
        , par
        , startGroup "package"
        , addCmd "get"
        , addCmd "init"
        , par
        , addCmd "configure"
        , addCmd "build"
        , addCmd "clean"
        , par
        , addCmd "run"
        , addCmd "repl"
        , addCmd "test"
        , addCmd "bench"
        , par
        , addCmd "check"
        , addCmd "sdist"
        , addCmd "upload"
        , addCmd "report"
        , par
        , addCmd "freeze"
274
        , addCmd "gen-bounds"
275
        , addCmd "outdated"
276 277 278
        , addCmd "haddock"
        , addCmd "hscolour"
        , addCmd "exec"
Oleg Grenrus's avatar
Oleg Grenrus committed
279
        , addCmd "list-bin"
280
        , par
281 282 283 284 285 286 287 288 289 290 291 292 293 294 295
        , startGroup "new-style projects (forwards-compatible aliases)"
        , addCmd "v2-build"
        , addCmd "v2-configure"
        , addCmd "v2-repl"
        , addCmd "v2-run"
        , addCmd "v2-test"
        , addCmd "v2-bench"
        , addCmd "v2-freeze"
        , addCmd "v2-haddock"
        , addCmd "v2-exec"
        , addCmd "v2-update"
        , addCmd "v2-install"
        , addCmd "v2-clean"
        , addCmd "v2-sdist"
        , par
296 297 298 299 300 301 302 303 304 305 306 307 308
        , startGroup "legacy command aliases"
        , addCmd "v1-build"
        , addCmd "v1-configure"
        , addCmd "v1-repl"
        , addCmd "v1-run"
        , addCmd "v1-test"
        , addCmd "v1-bench"
        , addCmd "v1-freeze"
        , addCmd "v1-haddock"
        , addCmd "v1-exec"
        , addCmd "v1-update"
        , addCmd "v1-install"
        , addCmd "v1-clean"
309 310 311 312 313
        , addCmd "v1-sdist"
        , addCmd "v1-doctest"
        , addCmd "v1-copy"
        , addCmd "v1-register"
        , addCmd "v1-reconfigure"
314 315 316
        ] ++ if null otherCmds then [] else par
                                           :startGroup "other"
                                           :[addCmd n | n <- otherCmds])
317 318
      ++ "\n"
      ++ "For more information about a command use:\n"
319 320
      ++ "   " ++ pname ++ " COMMAND --help\n"
      ++ "or " ++ pname ++ " help COMMAND\n"
321
      ++ "\n"
322
      ++ "To install Cabal packages from hackage use:\n"
323 324
      ++ "  " ++ pname ++ " install foo [--dry-run]\n"
      ++ "\n"
325 326
      ++ "Occasionally you need to update the list of available packages:\n"
      ++ "  " ++ pname ++ " update\n",
327
    commandNotes = Nothing,
328
    commandDefaultFlags = mempty,
329 330 331 332 333 334 335 336 337 338 339
    commandOptions = args
  }
  where
    args :: ShowOrParseArgs -> [OptionField GlobalFlags]
    args ShowArgs  = argsShown
    args ParseArgs = argsShown ++ argsNotShown

    -- arguments we want to show in the help
    argsShown :: [OptionField GlobalFlags]
    argsShown = [
       option ['V'] ["version"]
340 341 342 343 344 345 346 347 348 349 350 351 352 353
         "Print version information"
         globalVersion (\v flags -> flags { globalVersion = v })
         trueArg

      ,option [] ["numeric-version"]
         "Print just the version number"
         globalNumericVersion (\v flags -> flags { globalNumericVersion = v })
         trueArg

      ,option [] ["config-file"]
         "Set an alternate location for the config file"
         globalConfigFile (\v flags -> flags { globalConfigFile = v })
         (reqArgFlag "FILE")

U-CIQDEV\gbazerman's avatar
U-CIQDEV\gbazerman committed
354 355
      ,option [] ["default-user-config"]
         "Set a location for a cabal.config file for projects without their own cabal.config freeze file."
356
         globalConstraintsFile (\v flags -> flags {globalConstraintsFile = v})
U-CIQDEV\gbazerman's avatar
U-CIQDEV\gbazerman committed
357 358
         (reqArgFlag "FILE")

359
      ,option [] ["ignore-expiry"]
Edsko de Vries's avatar
Edsko de Vries committed
360
         "Ignore expiry dates on signed metadata (use only in exceptional circumstances)"
361 362 363
         globalIgnoreExpiry (\v flags -> flags { globalIgnoreExpiry = v })
         trueArg

364
      ,option [] ["http-transport"]
365
         "Set a transport for http(s) requests. Accepts 'curl', 'wget', 'powershell', and 'plain-http'. (default: 'curl')"
366
         globalHttpTransport (\v flags -> flags { globalHttpTransport = v })
367
         (reqArgFlag "HttpTransport")
ttuegel's avatar
ttuegel committed
368 369 370 371
      ,option [] ["nix"]
         "Nix integration: run commands through nix-shell if a 'shell.nix' file exists"
         globalNix (\v flags -> flags { globalNix = v })
         (boolOpt [] [])
372

373
      ]
374

375 376 377 378
    -- arguments we don't want shown in the help
    argsNotShown :: [OptionField GlobalFlags]
    argsNotShown = [
       option [] ["remote-repo"]
379 380
         "The name and url for a remote repository"
         globalRemoteRepos (\v flags -> flags { globalRemoteRepos = v })
381 382 383 384 385 386
         (reqArg' "NAME:URL" (toNubList . maybeToList . readRemoteRepo) (map showRemoteRepo . fromNubList))

      ,option [] ["local-no-index-repo"]
         "The name and a path for a local no-index repository"
         globalLocalNoIndexRepos (\v flags -> flags { globalLocalNoIndexRepos = v })
         (reqArg' "NAME:PATH" (toNubList . maybeToList . readLocalRepo) (map showLocalRepo . fromNubList))
387 388 389 390 391 392

      ,option [] ["remote-repo-cache"]
         "The location where downloads from all remote repos are cached"
         globalCacheDir (\v flags -> flags { globalCacheDir = v })
         (reqArgFlag "DIR")

393
      ,option [] ["logs-dir", "logsdir"]
394 395 396 397
         "The location to put log files"
         globalLogsDir (\v flags -> flags { globalLogsDir = v })
         (reqArgFlag "DIR")

398 399 400 401
      ,option [] ["world-file"]
         "The location of the world file"
         globalWorldFile (\v flags -> flags { globalWorldFile = v })
         (reqArgFlag "FILE")
402

403
      ,option [] ["store-dir", "storedir"]
404 405 406
         "The location of the nix-local-build store"
         globalStoreDir (\v flags -> flags { globalStoreDir = v })
         (reqArgFlag "DIR")
407 408 409 410 411 412 413

      , option [] ["active-repositories"]
         "The active package repositories"
         globalActiveRepos (\v flags ->  flags { globalActiveRepos = v })
         (reqArg "REPOS" (parsecToReadE (\err -> "Error parsing active-repositories: " ++ err)
                                        (toFlag `fmap` parsec))
                         (map prettyShow . flagToList))
414 415 416 417 418
      ]

-- ------------------------------------------------------------
-- * Config flags
-- ------------------------------------------------------------
419

420
configureCommand :: CommandUI ConfigFlags
421
configureCommand = c
422 423 424 425 426 427 428 429 430 431
  { commandName         = "configure"
  , commandDefaultFlags = mempty
  , commandDescription  = Just $ \_ -> wrapText $
         "Configure how the package is built by setting "
      ++ "package (and other) flags.\n"
      ++ "\n"
      ++ "The configuration affects several other commands, "
      ++ "including v1-build, v1-test, v1-bench, v1-run, v1-repl.\n"
  , commandUsage        = \pname ->
    "Usage: " ++ pname ++ " v1-configure [FLAGS]\n"
432
  , commandNotes = Just $ \pname ->
433 434 435 436 437 438 439
    (Cabal.programFlagsDescription defaultProgramDb ++ "\n")
      ++ "Examples:\n"
      ++ "  " ++ pname ++ " v1-configure\n"
      ++ "    Configure with defaults;\n"
      ++ "  " ++ pname ++ " v1-configure --enable-tests -fcustomflag\n"
      ++ "    Configure building package including tests,\n"
      ++ "    with some package-specific flag.\n"
440
  }
441
 where
442
  c = Cabal.configureCommand defaultProgramDb
443

444 445 446
configureOptions ::  ShowOrParseArgs -> [OptionField ConfigFlags]
configureOptions = commandOptions configureCommand

447 448 449 450 451 452 453 454
-- | Given some 'ConfigFlags' for the version of Cabal that
-- cabal-install was built with, and a target older 'Version' of
-- Cabal that we want to pass these flags to, convert the
-- flags into a form that will be accepted by the older
-- Setup script.  Generally speaking, this just means filtering
-- out flags that the old Cabal library doesn't understand, but
-- in some cases it may also mean "emulating" a feature using
-- some more legacy flags.
455
filterConfigureFlags :: ConfigFlags -> Version -> ConfigFlags
456
filterConfigureFlags flags cabalLibVersion
457 458
  -- NB: we expect the latest version to be the most common case,
  -- so test it first.
459
  | cabalLibVersion >= mkVersion [2,5,0]  = flags_latest
460 461 462 463 464
  -- The naming convention is that flags_version gives flags with
  -- all flags *introduced* in version eliminated.
  -- It is NOT the latest version of Cabal library that
  -- these flags work for; version of introduction is a more
  -- natural metric.
465 466 467 468 469 470 471 472 473
  | cabalLibVersion < mkVersion [1,3,10] = flags_1_3_10
  | cabalLibVersion < mkVersion [1,10,0] = flags_1_10_0
  | cabalLibVersion < mkVersion [1,12,0] = flags_1_12_0
  | cabalLibVersion < mkVersion [1,14,0] = flags_1_14_0
  | cabalLibVersion < mkVersion [1,18,0] = flags_1_18_0
  | cabalLibVersion < mkVersion [1,19,1] = flags_1_19_1
  | cabalLibVersion < mkVersion [1,19,2] = flags_1_19_2
  | cabalLibVersion < mkVersion [1,21,1] = flags_1_21_1
  | cabalLibVersion < mkVersion [1,22,0] = flags_1_22_0
474
  | cabalLibVersion < mkVersion [1,22,1] = flags_1_22_1
475
  | cabalLibVersion < mkVersion [1,23,0] = flags_1_23_0
Christiaan Baaij's avatar
Christiaan Baaij committed
476
  | cabalLibVersion < mkVersion [1,25,0] = flags_1_25_0
477
  | cabalLibVersion < mkVersion [2,1,0]  = flags_2_1_0
478
  | cabalLibVersion < mkVersion [2,5,0]  = flags_2_5_0
479
  | otherwise = error "the impossible just happened" -- see first guard
480
  where
481 482
    flags_latest = flags        {
      -- Cabal >= 1.19.1 uses '--dependency' and does not need '--constraint'.
483 484 485
      -- Note: this is not in the wrong place. configConstraints gets
      -- repopulated in flags_1_19_1 but it needs to be set to empty for
      -- newer versions first.
486
      configConstraints = []
487
      }
488

489
    flags_2_5_0 = flags_latest {
490
      -- Cabal < 2.5 does not understand --dependency=pkg:component=cid
491 492
      -- (public sublibraries), so we convert it to the legacy
      -- --dependency=pkg_or_internal_compoent=cid
493 494 495
        configDependencies =
          let convertToLegacyInternalDep (GivenComponent _ (LSubLibName cn) cid) =
                Just $ GivenComponent
496
                       (unqualComponentNameToPackageName cn)
497
                       LMainLibName
498
                       cid
499 500 501
              convertToLegacyInternalDep (GivenComponent pn LMainLibName cid) =
                Just $ GivenComponent pn LMainLibName cid
          in catMaybes $ convertToLegacyInternalDep <$> configDependencies flags
502 503
        -- Cabal < 2.5 doesn't know about '--allow-depending-on-private-libs'.
      , configAllowDependingOnPrivateLibs = NoFlag
504 505
        -- Cabal < 2.5 doesn't know about '--enable/disable-executable-static'.
      , configFullyStaticExe = NoFlag
506 507 508
      }

    flags_2_1_0 = flags_2_5_0 {
509
      -- Cabal < 2.1 doesn't know about -v +timestamp modifier
Moritz Angermann's avatar
Moritz Angermann committed
510 511 512
        configVerbosity   = fmap verboseNoTimestamp (configVerbosity flags_latest)
      -- Cabal < 2.1 doesn't know about --<enable|disable>-static
      , configStaticLib   = NoFlag
Ben Gamari's avatar
Ben Gamari committed
513
      , configSplitSections = NoFlag
514 515 516
      }

    flags_1_25_0 = flags_2_1_0 {
517 518 519
      -- Cabal < 1.25.0 doesn't know about --dynlibdir.
      configInstallDirs = configInstallDirs_1_25_0,
      -- Cabal < 1.25 doesn't have extended verbosity syntax
520
      configVerbosity   = fmap verboseNoFlags (configVerbosity flags_2_1_0),
521 522
      -- Cabal < 1.25 doesn't support --deterministic
      configDeterministic = mempty
523
      }
524 525 526 527 528 529 530
    configInstallDirs_1_25_0 = let dirs = configInstallDirs flags in
        dirs { dynlibdir = NoFlag
             , libexecsubdir = NoFlag
             , libexecdir = maybeToFlag $
                 combinePathTemplate <$> flagToMaybe (libexecdir dirs)
                                     <*> flagToMaybe (libexecsubdir dirs)
             }
531
    -- Cabal < 1.23 doesn't know about '--profiling-detail'.
532 533 534
    -- Cabal < 1.23 has a hacked up version of 'enable-profiling'
    -- which we shouldn't use.
    (tryLibProfiling, tryExeProfiling) = computeEffectiveProfiling flags
Christiaan Baaij's avatar
Christiaan Baaij committed
535
    flags_1_23_0 = flags_1_25_0 { configProfDetail    = NoFlag
536
                                , configProfLibDetail = NoFlag
537
                                , configIPID          = NoFlag
Mikhail Glushenkov's avatar
Mikhail Glushenkov committed
538 539 540
                                , configProf          = NoFlag
                                , configProfExe       = Flag tryExeProfiling
                                , configProfLib       = Flag tryLibProfiling
541
                                }
542

543 544 545 546 547 548
    -- Cabal == 1.22.0.* had a discontinuity (see #5946 or e9a8d48a3adce34d)
    -- due to temporary amnesia of the --*-executable-profiling flags
    flags_1_22_1 = flags_1_23_0 { configDebugInfo = NoFlag
                                , configProfExe   = NoFlag
                                }

549
    -- Cabal < 1.22 doesn't know about '--disable-debug-info'.
550
    flags_1_22_0 = flags_1_23_0 { configDebugInfo = NoFlag }
551

552
    -- Cabal < 1.21.1 doesn't know about 'disable-relocatable'
553
    -- Cabal < 1.21.1 doesn't know about 'enable-profiling'
554
    -- (but we already dealt with it in flags_1_23_0)
555 556
    flags_1_21_1 =
      flags_1_22_0 { configRelocatable = NoFlag
557 558
                   , configCoverage = NoFlag
                   , configLibCoverage = configCoverage flags
559
                   }
560 561
    -- Cabal < 1.19.2 doesn't know about '--exact-configuration' and
    -- '--enable-library-stripping'.
562
    flags_1_19_2 = flags_1_21_1 { configExactConfiguration = NoFlag
563
                                , configStripLibs = NoFlag }
564
    -- Cabal < 1.19.1 uses '--constraint' instead of '--dependency'.
565
    flags_1_19_1 = flags_1_19_2 { configDependencies = []
566
                                , configConstraints  = configConstraints flags }
567
    -- Cabal < 1.18.0 doesn't know about --extra-prog-path and --sysconfdir.
568
    flags_1_18_0 = flags_1_19_1 { configProgramPathExtra = toNubList []
569
                                , configInstallDirs = configInstallDirs_1_18_0}
Christiaan Baaij's avatar
Christiaan Baaij committed
570
    configInstallDirs_1_18_0 = (configInstallDirs flags_1_19_1) { sysconfdir = NoFlag }
571
    -- Cabal < 1.14.0 doesn't know about '--disable-benchmarks'.
572
    flags_1_14_0 = flags_1_18_0 { configBenchmarks  = NoFlag }
573 574 575 576
    -- Cabal < 1.12.0 doesn't know about '--enable/disable-executable-dynamic'
    -- and '--enable/disable-library-coverage'.
    flags_1_12_0 = flags_1_14_0 { configLibCoverage = NoFlag
                                , configDynExe      = NoFlag }
577
    -- Cabal < 1.10.0 doesn't know about '--disable-tests'.
578
    flags_1_10_0 = flags_1_12_0 { configTests       = NoFlag }
579
    -- Cabal < 1.3.10 does not grok the '--constraints' flag.
580
    flags_1_3_10 = flags_1_10_0 { configConstraints = [] }
581

582 583
-- | Get the package database settings from 'ConfigFlags', accounting for
-- @--package-db@ and @--user@ flags.
584 585 586 587 588 589
configPackageDB' :: ConfigFlags -> PackageDBStack
configPackageDB' cfg =
    interpretPackageDbFlags userInstall (configPackageDBs cfg)
  where
    userInstall = Cabal.fromFlagOrDefault True (configUserInstall cfg)

590
-- | Configure the compiler, but reduce verbosity during this step.
591 592 593 594 595 596
configCompilerAux' :: ConfigFlags -> IO (Compiler, Platform, ProgramDb)
configCompilerAux' configFlags =
  configCompilerAuxEx configFlags
    --FIXME: make configCompilerAux use a sensible verbosity
    { configVerbosity = fmap lessVerbose (configVerbosity configFlags) }

597 598 599 600 601 602 603
-- ------------------------------------------------------------
-- * Config extra flags
-- ------------------------------------------------------------

-- | cabal configure takes some extra flags beyond runghc Setup configure
--
data ConfigExFlags = ConfigExFlags {
604 605 606 607 608 609 610 611
    configCabalVersion  :: Flag Version,
    configExConstraints :: [(UserConstraint, ConstraintSource)],
    configPreferences   :: [PackageVersionConstraint],
    configSolver        :: Flag PreSolver,
    configAllowNewer    :: Maybe AllowNewer,
    configAllowOlder    :: Maybe AllowOlder,
    configWriteGhcEnvironmentFilesPolicy
      :: Flag WriteGhcEnvironmentFilesPolicy
612
  }
613
  deriving (Eq, Show, Generic)
614 615

defaultConfigExFlags :: ConfigExFlags
616
defaultConfigExFlags = mempty { configSolver     = Flag defaultSolver }
617 618 619 620 621

configureExCommand :: CommandUI (ConfigFlags, ConfigExFlags)
configureExCommand = configureCommand {
    commandDefaultFlags = (mempty, defaultConfigExFlags),
    commandOptions      = \showOrParseArgs ->
622
         liftOptions fst setFst
623
         (filter ((`notElem` ["constraint", "dependency", "exact-configuration"])
624
                  . optionName) $ configureOptions  showOrParseArgs)
625 626
      ++ liftOptions snd setSnd
         (configureExOptions showOrParseArgs ConstraintSourceCommandlineFlag)
627 628 629 630 631
  }
  where
    setFst a (_,b) = (a,b)
    setSnd b (a,_) = (a,b)

632 633 634 635
configureExOptions :: ShowOrParseArgs
                   -> ConstraintSource
                   -> [OptionField ConfigExFlags]
configureExOptions _showOrParseArgs src =
636 637 638 639
  [ option [] ["cabal-lib-version"]
      ("Select which version of the Cabal lib to use to build packages "
      ++ "(useful for testing).")
      configCabalVersion (\v flags -> flags { configCabalVersion = v })
640 641 642
      (reqArg "VERSION" (parsecToReadE ("Cannot parse cabal lib version: "++)
                                    (fmap toFlag parsec))
                        (map prettyShow. flagToList))
643 644 645 646
  , option [] ["constraint"]
      "Specify constraints on a package (version, installed/source, flags)"
      configExConstraints (\v flags -> flags { configExConstraints = v })
      (reqArg "CONSTRAINT"
647
              ((\x -> [(x, src)]) `fmap` ReadE readUserConstraint)
648
              (map $ prettyShow . fst))
649 650 651 652

  , option [] ["preference"]
      "Specify preferences (soft constraints) on the version of a package"
      configPreferences (\v flags -> flags { configPreferences = v })
653
      (reqArg "CONSTRAINT"
654 655 656
              (parsecToReadE (const "dependency expected")
                          (fmap (\x -> [x]) parsec))
              (map prettyShow))
657 658

  , optionSolver configSolver (\v flags -> flags { configSolver = v })
659

660
  , option [] ["allow-older"]
661
    ("Ignore lower bounds in all dependencies or DEPS")
662 663 664
    (fmap unAllowOlder . configAllowOlder)
    (\v flags -> flags { configAllowOlder = fmap AllowOlder v})
    (optArg "DEPS"
665
     (parsecToReadE ("Cannot parse the list of packages: " ++) relaxDepsParser)
666 667 668 669 670 671 672
     (Just RelaxDepsAll) relaxDepsPrinter)

  , option [] ["allow-newer"]
    ("Ignore upper bounds in all dependencies or DEPS")
    (fmap unAllowNewer . configAllowNewer)
    (\v flags -> flags { configAllowNewer = fmap AllowNewer v})
    (optArg "DEPS"
673
     (parsecToReadE ("Cannot parse the list of packages: " ++) relaxDepsParser)
674 675
     (Just RelaxDepsAll) relaxDepsPrinter)

676 677 678 679 680 681 682 683
  , option [] ["write-ghc-environment-files"]
    ("Whether to create a .ghc.environment file after a successful build"
      ++ " (v2-build only)")
    configWriteGhcEnvironmentFilesPolicy
    (\v flags -> flags { configWriteGhcEnvironmentFilesPolicy = v})
    (reqArg "always|never|ghc8.4.4+"
     writeGhcEnvironmentFilesPolicyParser
     writeGhcEnvironmentFilesPolicyPrinter)
684 685
  ]

686

687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703
writeGhcEnvironmentFilesPolicyParser :: ReadE (Flag WriteGhcEnvironmentFilesPolicy)
writeGhcEnvironmentFilesPolicyParser = ReadE $ \case
  "always"    -> Right $ Flag AlwaysWriteGhcEnvironmentFiles
  "never"     -> Right $ Flag NeverWriteGhcEnvironmentFiles
  "ghc8.4.4+" -> Right $ Flag WriteGhcEnvironmentFilesOnlyForGhc844AndNewer
  policy      -> Left  $ "Cannot parse the GHC environment file write policy '"
                 <> policy <> "'"

writeGhcEnvironmentFilesPolicyPrinter
  :: Flag WriteGhcEnvironmentFilesPolicy -> [String]
writeGhcEnvironmentFilesPolicyPrinter = \case
  (Flag AlwaysWriteGhcEnvironmentFiles)                -> ["always"]
  (Flag NeverWriteGhcEnvironmentFiles)                 -> ["never"]
  (Flag WriteGhcEnvironmentFilesOnlyForGhc844AndNewer) -> ["ghc8.4.4+"]
  NoFlag                                               -> []


704
relaxDepsParser :: CabalParsing m => m (Maybe RelaxDeps)
705
relaxDepsParser =
706
  (Just . RelaxDepsSome . toList) `fmap` P.sepByNonEmpty parsec (P.char ',')
707 708 709 710

relaxDepsPrinter :: (Maybe RelaxDeps) -> [Maybe String]
relaxDepsPrinter Nothing                     = []
relaxDepsPrinter (Just RelaxDepsAll)         = [Nothing]
711
relaxDepsPrinter (Just (RelaxDepsSome pkgs)) = map (Just . prettyShow) $ pkgs
712 713


714
instance Monoid ConfigExFlags where
715
  mempty = gmempty
716 717 718
  mappend = (<>)

instance Semigroup ConfigExFlags where
719
  (<>) = gmappend
720

ttuegel's avatar
ttuegel committed
721 722 723 724 725 726
reconfigureCommand :: CommandUI (ConfigFlags, ConfigExFlags)
reconfigureCommand
  = configureExCommand
    { commandName         = "reconfigure"
    , commandSynopsis     = "Reconfigure the package if necessary."
    , commandDescription  = Just $ \pname -> wrapText $
727 728
         "Run `configure` with the most recently used flags, or append FLAGS "
         ++ "to the most recently used configuration. "
729
         ++ "Accepts the same flags as `" ++ pname ++ " v1-configure'. "
730 731 732 733
         ++ "If the package has never been configured, the default flags are "
         ++ "used."
    , commandNotes        = Just $ \pname ->
        "Examples:\n"
734
        ++ "  " ++ pname ++ " v1-reconfigure\n"
735
        ++ "    Configure with the most recently used flags.\n"
736
        ++ "  " ++ pname ++ " v1-reconfigure -w PATH\n"
737 738
        ++ "    Reconfigure with the most recently used flags,\n"
        ++ "    but use the compiler at PATH.\n\n"
739
    , commandUsage        = usageAlternatives "v1-reconfigure" [ "[FLAGS]" ]
ttuegel's avatar
ttuegel committed
740 741 742
    , commandDefaultFlags = mempty
    }

743 744 745 746
-- ------------------------------------------------------------
-- * Build flags
-- ------------------------------------------------------------

Oleg Grenrus's avatar
Oleg Grenrus committed
747
buildCommand :: CommandUI BuildFlags
748
buildCommand = parent {
749 750 751 752 753
    commandName = "build",
    commandDescription  = Just $ \_ -> wrapText $
      "Components encompass executables, tests, and benchmarks.\n"
        ++ "\n"
        ++ "Affected by configuration options, see `v1-configure`.\n",
Oleg Grenrus's avatar
Oleg Grenrus committed
754
    commandDefaultFlags = commandDefaultFlags parent,
755 756
    commandUsage        = usageAlternatives "v1-build" $
      [ "[FLAGS]", "COMPONENTS [FLAGS]" ],
Oleg Grenrus's avatar
Oleg Grenrus committed
757 758
    commandOptions      = commandOptions parent
    , commandNotes      = Just $ \pname ->
759 760 761 762 763 764
      "Examples:\n"
        ++ "  " ++ pname ++ " v1-build           "
        ++ "    All the components in the package\n"
        ++ "  " ++ pname ++ " v1-build foo       "
        ++ "    A component (i.e. lib, exe, test suite)\n\n"
        ++ Cabal.programFlagsDescription defaultProgramDb
765 766
  }
  where
767
    parent = Cabal.buildCommand defaultProgramDb
768

Josh Meredith's avatar
Josh Meredith committed
769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799
-- ------------------------------------------------------------
-- * Test flags
-- ------------------------------------------------------------

-- | Given some 'TestFlags' for the version of Cabal that
-- cabal-install was built with, and a target older 'Version' of
-- Cabal that we want to pass these flags to, convert the
-- flags into a form that will be accepted by the older
-- Setup script.  Generally speaking, this just means filtering
-- out flags that the old Cabal library doesn't understand, but
-- in some cases it may also mean "emulating" a feature using
-- some more legacy flags.
filterTestFlags :: TestFlags -> Version -> TestFlags
filterTestFlags flags cabalLibVersion
  -- NB: we expect the latest version to be the most common case,
  -- so test it first.
  | cabalLibVersion >= mkVersion [3,0,0] = flags_latest
  -- The naming convention is that flags_version gives flags with
  -- all flags *introduced* in version eliminated.
  -- It is NOT the latest version of Cabal library that
  -- these flags work for; version of introduction is a more
  -- natural metric.
  | cabalLibVersion <  mkVersion [3,0,0] = flags_3_0_0
  | otherwise = error "the impossible just happened" -- see first guard
  where
    flags_latest = flags
    flags_3_0_0  = flags_latest {
      -- Cabal < 3.0 doesn't know about --test-wrapper
      Cabal.testWrapper = NoFlag
      }

800
-- ------------------------------------------------------------
801 802 803
-- * Repl command
-- ------------------------------------------------------------

Oleg Grenrus's avatar
Oleg Grenrus committed
804
replCommand :: CommandUI ReplFlags
805
replCommand = parent {
806 807 808
    commandName = "repl",
    commandDescription  = Just $ \pname -> wrapText $
         "If the current directory contains no package, ignores COMPONENT "
Oleg Grenrus's avatar
Oleg Grenrus committed
809
      ++ "parameters and opens an interactive interpreter session;\n"
810 811 812 813 814 815 816 817 818 819 820 821 822 823 824
      ++ "\n"
      ++ "Otherwise, (re)configures with the given or default flags, and "
      ++ "loads the interpreter with the relevant modules. For executables, "
      ++ "tests and benchmarks, loads the main module (and its "
      ++ "dependencies); for libraries all exposed/other modules.\n"
      ++ "\n"
      ++ "The default component is the library itself, or the executable "
      ++ "if that is the only component.\n"
      ++ "\n"
      ++ "Support for loading specific modules is planned but not "
      ++ "implemented yet. For certain scenarios, `" ++ pname
      ++ " v1-exec -- ghci :l Foo` may be used instead. Note that `v1-exec` will "
      ++ "not (re)configure and you will have to specify the location of "
      ++ "other modules, if required.\n",
    commandUsage =  \pname -> "Usage: " ++ pname ++ " v1-repl [COMPONENT] [FLAGS]\n",
Oleg Grenrus's avatar
Oleg Grenrus committed
825 826
    commandDefaultFlags = commandDefaultFlags parent,
    commandOptions      = commandOptions parent,
827 828 829 830 831 832 833 834
    commandNotes        = Just $ \pname ->
      "Examples:\n"
    ++ "  " ++ pname ++ " v1-repl           "
    ++ "    The first component in the package\n"
    ++ "  " ++ pname ++ " v1-repl foo       "
    ++ "    A named component (i.e. lib, exe, test suite)\n"
    ++ "  " ++ pname ++ " v1-repl --ghc-options=\"-lstdc++\""
    ++ "  Specifying flags for interpreter\n"
835 836
  }
  where
837
    parent = Cabal.replCommand defaultProgramDb
838

839 840 841 842
-- ------------------------------------------------------------
-- * Test command
-- ------------------------------------------------------------

Oleg Grenrus's avatar
Oleg Grenrus committed
843
testCommand :: CommandUI (BuildFlags, TestFlags)
844
testCommand = parent {
845 846 847 848 849 850 851 852 853 854 855 856 857
  commandName = "test",
  commandDescription  = Just $ \pname -> wrapText $
         "If necessary (re)configures with `--enable-tests` flag and builds"
      ++ " the test suite.\n"
      ++ "\n"
      ++ "Remember that the tests' dependencies must be installed if there"
      ++ " are additional ones; e.g. with `" ++ pname
      ++ " v1-install --only-dependencies --enable-tests`.\n"
      ++ "\n"
      ++ "By defining UserHooks in a custom Setup.hs, the package can"
      ++ " define actions to be executed before and after running tests.\n",
  commandUsage = usageAlternatives "v1-test"
      [ "[FLAGS]", "TESTCOMPONENTS [FLAGS]" ],
Oleg Grenrus's avatar
Oleg Grenrus committed
858
  commandDefaultFlags = (Cabal.defaultBuildFlags, commandDefaultFlags parent),
859
  commandOptions      =
860
    \showOrParseArgs -> liftOptions get1 set1
Mikhail Glushenkov's avatar
Mikhail Glushenkov committed
861
                        (Cabal.buildOptions progDb showOrParseArgs)
862
                        ++
Oleg Grenrus's avatar
Oleg Grenrus committed
863 864
                        liftOptions get2 set2
                        (commandOptions parent showOrParseArgs)
865 866
  }
  where
Oleg Grenrus's avatar
Oleg Grenrus committed
867 868
    get1 (a,_) = a; set1 a (_,b) = (a,b)
    get2 (_,b) = b; set2 b (a,_) = (a,b)
869

Mikhail Glushenkov's avatar
Mikhail Glushenkov committed
870 871
    parent = Cabal.testCommand
    progDb = defaultProgramDb
872 873 874 875 876

-- ------------------------------------------------------------
-- * Bench command
-- ------------------------------------------------------------

Oleg Grenrus's avatar
Oleg Grenrus committed
877
benchmarkCommand :: CommandUI (BuildFlags, BenchmarkFlags)
878
benchmarkCommand = parent {
879 880 881 882 883 884 885 886 887 888 889 890 891 892
  commandName = "bench",
  commandUsage = usageAlternatives "v1-bench"
      [ "[FLAGS]", "BENCHCOMPONENTS [FLAGS]" ],
  commandDescription  = Just $ \pname -> wrapText $
         "If necessary (re)configures with `--enable-benchmarks` flag and"
      ++ " builds the benchmarks.\n"
      ++ "\n"
      ++ "Remember that the benchmarks' dependencies must be installed if"
      ++ " there are additional ones; e.g. with `" ++ pname
      ++ " v1-install --only-dependencies --enable-benchmarks`.\n"
      ++ "\n"
      ++ "By defining UserHooks in a custom Setup.hs, the package can"
      ++ " define actions to be executed before and after running"
      ++ " benchmarks.\n",
Oleg Grenrus's avatar
Oleg Grenrus committed
893
  commandDefaultFlags = (Cabal.defaultBuildFlags, commandDefaultFlags parent),
894
  commandOptions      =
895
    \showOrParseArgs -> liftOptions get1 set1
Mikhail Glushenkov's avatar
Mikhail Glushenkov committed
896
                        (Cabal.buildOptions progDb showOrParseArgs)
897
                        ++
Oleg Grenrus's avatar
Oleg Grenrus committed
898 899
                        liftOptions get2 set2
                        (commandOptions parent showOrParseArgs)
900
  }
901
  where
Oleg Grenrus's avatar
Oleg Grenrus committed
902 903
    get1 (a,_) = a; set1 a (_,b) = (a,b)
    get2 (_,b) = b; set2 b (a,_) = (a,b)
904

Mikhail Glushenkov's avatar
Mikhail Glushenkov committed
905 906
    parent = Cabal.benchmarkCommand
    progDb = defaultProgramDb
907

908
-- ------------------------------------------------------------
909
-- * Fetch command
910
-- ------------------------------------------------------------
911

912 913 914 915
data FetchFlags = FetchFlags {
--    fetchOutput    :: Flag FilePath,
      fetchDeps      :: Flag Bool,
      fetchDryRun    :: Flag Bool,
916
      fetchSolver           :: Flag PreSolver,
917
      fetchMaxBackjumps     :: Flag Int,
918
      fetchReorderGoals     :: Flag ReorderGoals,
919
      fetchCountConflicts   :: Flag CountConflicts,
920
      fetchFineGrainedConflicts :: Flag FineGrainedConflicts,
921
      fetchMinimizeConflictSet :: Flag MinimizeConflictSet,
922 923 924
      fetchIndependentGoals :: Flag IndependentGoals,
      fetchShadowPkgs       :: Flag ShadowPkgs,
      fetchStrongFlags      :: Flag StrongFlags,
925
      fetchAllowBootLibInstalls :: Flag AllowBootLibInstalls,
926
      fetchOnlyConstrained  :: Flag OnlyConstrained,
927 928
      fetchTests            :: Flag Bool,
      fetchBenchmarks       :: Flag Bool,
929 930 931 932 933 934 935 936
      fetchVerbosity :: Flag Verbosity
    }

defaultFetchFlags :: FetchFlags
defaultFetchFlags = FetchFlags {
--  fetchOutput    = mempty,
    fetchDeps      = toFlag True,
    fetchDryRun    = toFlag False,
937 938
    fetchSolver           = Flag defaultSolver,
    fetchMaxBackjumps     = Flag defaultMaxBackjumps,
939
    fetchReorderGoals     = Flag (ReorderGoals False),
940
    fetchCountConflicts   = Flag (CountConflicts True),
941
    fetchFineGrainedConflicts = Flag (FineGrainedConflicts True),
942
    fetchMinimizeConflictSet = Flag (MinimizeConflictSet False),
943 944 945
    fetchIndependentGoals = Flag (IndependentGoals False),
    fetchShadowPkgs       = Flag (ShadowPkgs False),
    fetchStrongFlags      = Flag (StrongFlags False),
946
    fetchAllowBootLibInstalls = Flag (AllowBootLibInstalls False),
947
    fetchOnlyConstrained  = Flag OnlyConstrainedNone,
948 949
    fetchTests            = toFlag False,
    fetchBenchmarks       = toFlag False,
950 951 952 953
    fetchVerbosity = toFlag normal
   }

fetchCommand :: CommandUI FetchFlags
954 955
fetchCommand = CommandUI {
    commandName         = "fetch",
956
    commandSynopsis     = "Downloads packages for later installation.",
957 958 959 960 961
    commandUsage        = usageAlternatives "fetch" [ "[FLAGS] PACKAGES"
                                                    ],
    commandDescription  = Just $ \_ ->
          "Note that it currently is not possible to fetch the dependencies for a\n"
       ++ "package in the current directory.\n",
962
    commandNotes        = Nothing,
963
    commandDefaultFlags = defaultFetchFlags,
964
    commandOptions      = \ showOrParseArgs -> [
965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985
         optionVerbosity fetchVerbosity (\v flags -> flags { fetchVerbosity = v })

--     , option "o" ["output"]
--         "Put the package(s) somewhere specific rather than the usual cache."
--         fetchOutput (\v flags -> flags { fetchOutput = v })
--         (reqArgFlag "PATH")

       , option [] ["dependencies", "deps"]
           "Resolve and fetch dependencies (default)"
           fetchDeps (\v flags -> flags { fetchDeps = v })
           trueArg

       , option [] ["no-dependencies", "no-deps"]
           "Ignore dependencies"
           fetchDeps (\v flags -> flags { fetchDeps = v })
           falseArg

       , option [] ["dry-run"]
           "Do not install anything, only print what would be installed."
           fetchDryRun (\v flags -> flags { fetchDryRun = v })
           trueArg
986

987 988 989 990 991 992 993 994 995 996
      , option "" ["tests"]
         "dependency checking and compilation for test suites listed in the package description file."
         fetchTests (\v flags -> flags { fetchTests = v })
         (boolOpt [] [])

      , option "" ["benchmarks"]
         "dependency checking and compilation for benchmarks listed in the package description file."
         fetchBenchmarks (\v flags -> flags { fetchBenchmarks = v })
         (boolOpt [] [])

997 998 999
       ] ++

       optionSolver      fetchSolver           (\v flags -> flags { fetchSolver           = v }) :
1000 1001
       optionSolverFlags showOrParseArgs
                         fetchMaxBackjumps     (\v flags -> flags { fetchMaxBackjumps     = v })
1002
                         fetchReorderGoals     (\v flags -> flags { fetchReorderGoals     = v })
1003
                         fetchCountConflicts   (\v flags -> flags { fetchCountConflicts   = v })
1004
                         fetchFineGrainedConflicts (\v flags -> flags { fetchFineGrainedConflicts = v })
1005
                         fetchMinimizeConflictSet (\v flags -> flags { fetchMinimizeConflictSet = v })
1006
                         fetchIndependentGoals (\v flags -> flags { fetchIndependentGoals = v })
1007
                         fetchShadowPkgs       (\v flags -> flags { fetchShadowPkgs       = v })
1008
                         fetchStrongFlags      (\v flags -> flags { fetchStrongFlags      = v })
1009
                         fetchAllowBootLibInstalls (\v flags -> flags { fetchAllowBootLibInstalls = v })
1010
                         fetchOnlyConstrained  (\v flags -> flags { fetchOnlyConstrained  = v })
1011

1012 1013
  }

1014 1015 1016 1017 1018 1019
-- ------------------------------------------------------------
-- * Freeze command
-- ------------------------------------------------------------

data FreezeFlags = FreezeFlags {
      freezeDryRun           :: Flag Bool,
1020 1021
      freezeTests            :: Flag Bool,
      freezeBenchmarks       :: Flag Bool,
1022 1023
      freezeSolver           :: Flag PreSolver,
      freezeMaxBackjumps     :: Flag Int,
1024
      freezeReorderGoals     :: Flag ReorderGoals,
1025
      freezeCountConflicts   :: Flag CountConflicts,
1026
      freezeFineGrainedConflicts :: Flag FineGrainedConflicts,
1027
      freezeMinimizeConflictSet :: Flag MinimizeConflictSet,
1028 1029 1030
      freezeIndependentGoals :: Flag IndependentGoals,
      freezeShadowPkgs       :: Flag ShadowPkgs,
      freezeStrongFlags      :: Flag StrongFlags,
1031
      freezeAllowBootLibInstalls :: Flag AllowBootLibInstalls,
1032
      freezeOnlyConstrained  :: Flag OnlyConstrained,
1033 1034 1035 1036 1037 1038
      freezeVerbosity        :: Flag Verbosity
    }

defaultFreezeFlags :: FreezeFlags
defaultFreezeFlags = FreezeFlags {
    freezeDryRun           = toFlag False,
1039 1040
    freezeTests            = toFlag False,
    freezeBenchmarks       = toFlag False,
1041 1042
    freezeSolver           = Flag defaultSolver,
    freezeMaxBackjumps     = Flag defaultMaxBackjumps,
1043
    freezeReorderGoals     = Flag (ReorderGoals False),
1044
    freezeCountConflicts   = Flag (CountConflicts True),
1045
    freezeFineGrainedConflicts = Flag (FineGrainedConflicts True),
1046
    freezeMinimizeConflictSet = Flag (MinimizeConflictSet False),
1047 1048 1049
    freezeIndependentGoals = Flag (IndependentGoals False),
    freezeShadowPkgs       = Flag (ShadowPkgs False),
    freezeStrongFlags      = Flag (StrongFlags False),
1050
    freezeAllowBootLibInstalls = Flag (AllowBootLibInstalls False),
1051
    freezeOnlyConstrained  = Flag OnlyConstrainedNone,
1052 1053 1054 1055 1056 1057 1058
    freezeVerbosity        = toFlag normal
   }

freezeCommand :: CommandUI FreezeFlags
freezeCommand = CommandUI {
    commandName         = "freeze",
    commandSynopsis     = "Freeze dependencies.",
1059 1060 1061 1062 1063 1064 1065 1066
    commandDescription  = Just $ \_ -> wrapText $
         "Calculates a valid set of dependencies and their exact versions. "