2 {-# LANGUAGE DataKinds #-}
4 -----------------------------------------------------------------------------
6 -----------------------------------------------------------------------------
9 -- Module : Distribution.Client.Install
10 -- Copyright : (c) 2005 David Himmelstrup
11 -- 2007 Bjorn Bringert
12 -- 2007-2010 Duncan Coutts
15 -- Maintainer : cabal-devel@haskell.org
16 -- Stability : provisional
17 -- Portability : portable
19 -- High level interface to package installation.
20 module Distribution
.Client
.Install
21 ( -- * High-level interface
24 -- * Lower-level interface that allows to manipulate the install plan
31 -- * Prune certain packages from the install plan
35 import Distribution
.Client
.Compat
.Prelude
36 import Distribution
.Utils
.Generic
(safeLast
)
39 import Control
.Exception
as Exception
45 import qualified Data
.List
.NonEmpty
as NE
46 import qualified Data
.Map
as Map
47 import System
.Directory
48 ( createDirectoryIfMissing
51 , getDirectoryContents
52 , getTemporaryDirectory
56 import System
.FilePath
67 import System
.IO.Error
72 import Distribution
.Client
.BuildReports
.Anonymous
(showBuildReport
)
73 import qualified Distribution
.Client
.BuildReports
.Anonymous
as BuildReports
74 import qualified Distribution
.Client
.BuildReports
.Storage
as BuildReports
80 import Distribution
.Client
.BuildReports
.Types
83 import Distribution
.Client
.Config
87 import Distribution
.Client
.Configure
90 , configureSetupScript
92 import Distribution
.Client
.Dependency
93 import Distribution
.Client
.FetchUtils
94 import qualified Distribution
.Client
.Haddock
as Haddock
(regenerateHaddockIndex
)
95 import Distribution
.Client
.HttpUtils
98 import Distribution
.Client
.IndexUtils
as IndexUtils
99 ( getInstalledPackages
100 , getSourcePackagesAtIndexState
102 import Distribution
.Client
.InstallPlan
(InstallPlan
)
103 import qualified Distribution
.Client
.InstallPlan
as InstallPlan
104 import qualified Distribution
.Client
.InstallSymlink
as InstallSymlink
107 import Distribution
.Client
.JobControl
108 import Distribution
.Client
.Setup
116 , filterConfigureFlags
119 import Distribution
.Client
.SetupWrapper
120 ( SetupScriptOptions
(..)
121 , defaultSetupScriptOptions
124 import Distribution
.Client
.SolverInstallPlan
(SolverInstallPlan
)
125 import qualified Distribution
.Client
.SolverInstallPlan
as SolverInstallPlan
126 import Distribution
.Client
.Tar
(extractTarGzFile
)
127 import Distribution
.Client
.Targets
128 import Distribution
.Client
.Types
as Source
129 import Distribution
.Client
.Types
.OverwritePolicy
(OverwritePolicy
(..))
130 import qualified Distribution
.Client
.Win32SelfUpgrade
as Win32SelfUpgrade
131 import qualified Distribution
.InstalledPackageInfo
as Installed
132 import Distribution
.Solver
.Types
.PackageFixedDeps
134 import qualified Distribution
.Solver
.Types
.ComponentDeps
as CD
135 import Distribution
.Solver
.Types
.ConstraintSource
136 import Distribution
.Solver
.Types
.LabeledPackageConstraint
137 import Distribution
.Solver
.Types
.OptionalStanza
138 import qualified Distribution
.Solver
.Types
.PackageIndex
as SourcePackageIndex
139 import Distribution
.Solver
.Types
.PkgConfigDb
143 import Distribution
.Solver
.Types
.Settings
144 import Distribution
.Solver
.Types
.SourcePackage
as SourcePackage
146 import Distribution
.Client
.Utils
154 import Distribution
.Package
155 ( HasMungedPackageId
(..)
159 , PackageIdentifier
(..)
164 import Distribution
.PackageDescription
165 ( GenericPackageDescription
(..)
168 import qualified Distribution
.PackageDescription
as PackageDescription
169 import Distribution
.PackageDescription
.Configuration
172 import Distribution
.Simple
.BuildPaths
(exeExtension
)
173 import Distribution
.Simple
.Compiler
174 ( Compiler
(compilerId
)
182 import Distribution
.Simple
.Configure
(interpretPackageDbFlags
)
183 import Distribution
.Simple
.Errors
184 import Distribution
.Simple
.InstallDirs
as InstallDirs
187 , initialPathTemplateEnv
188 , installDirsTemplateEnv
192 import qualified Distribution
.Simple
.InstallDirs
as InstallDirs
193 import Distribution
.Simple
.PackageIndex
(InstalledPackageIndex
)
194 import qualified Distribution
.Simple
.PackageIndex
as PackageIndex
195 import Distribution
.Simple
.Program
(ProgramDb
)
196 import Distribution
.Simple
.Register
(defaultRegisterOptions
, registerPackage
)
197 import Distribution
.Simple
.Setup
198 ( BenchmarkFlags
(..)
200 , CommonSetupFlags
(..)
207 , defaultCommonSetupFlags
215 , registerCommonFlags
222 import qualified Distribution
.Simple
.Setup
as Cabal
223 import Distribution
.Utils
.Path
hiding
228 import Distribution
.Simple
.Utils
230 , createDirectoryIfMissingVerbose
233 import Distribution
.Simple
.Utils
as Utils
242 import Distribution
.System
248 import Distribution
.Types
.Flag
256 import Distribution
.Types
.GivenComponent
257 ( GivenComponent
(..)
259 import Distribution
.Types
.MungedPackageId
260 import Distribution
.Types
.PackageVersionConstraint
261 ( PackageVersionConstraint
(..)
262 , thisPackageVersionConstraint
264 import Distribution
.Utils
.NubList
265 import Distribution
.Verbosity
as Verbosity
270 import Distribution
.Version
276 import qualified Data
.ByteString
as BS
277 import Distribution
.Client
.Errors
281 -- * assign flags to packages individually
283 -- * complain about flags that do not apply to any package given as target
284 -- so flags do not apply to dependencies, only listed, can use flag
285 -- constraints for dependencies
287 -- * allow flag constraints
289 -- * allow installed constraints
291 -- * allow flag and installed preferences
293 -- * allow persistent configure flags for each package individually
295 -- ------------------------------------------------------------
297 -- * Top level user actions
299 -- ------------------------------------------------------------
301 -- | Installs the packages needed to satisfy a list of dependencies.
333 unless (installRootCmd installFlags
== Cabal
.NoFlag
) $
335 "--root-cmd is no longer supported, "
336 ++ "see https://github.com/haskell/cabal/issues/3353"
337 ++ " (if you didn't type --root-cmd, comment out root-cmd"
338 ++ " in your ~/.config/cabal/config file)"
339 let userOrSandbox
= fromFlag
(configUserInstall configFlags
)
340 unless userOrSandbox
$
342 "the --global flag is deprecated -- "
343 ++ "it is generally considered a bad idea to install packages "
344 ++ "into the global store"
346 installContext
<- makeInstallContext verbosity args
(Just userTargets0
)
348 foldProgress logMsg
(return . Left
) (return . Right
)
349 =<< makeInstallPlan verbosity args installContext
353 reportPlanningFailure verbosity args installContext message
354 die
'' $ ReportPlanningFailure message
356 processInstallPlan verbosity args installContext installPlan
374 die
'' = dieWithException verbosity
376 logMsg message rest
= debugNoWrap verbosity message
>> rest
378 -- TODO: Make InstallContext a proper data type with documented fields.
380 -- | Common context for makeInstallPlan and processInstallPlan.
381 type InstallContext
=
382 ( InstalledPackageIndex
386 , [PackageSpecifier UnresolvedSourcePackage
]
390 -- TODO: Make InstallArgs a proper data type with documented fields or just get
391 -- rid of it completely.
393 -- | Initial arguments given to 'install' or 'makeInstallContext'.
409 -- | Make an install context given install arguments.
413 -> Maybe [UserTarget
]
431 let idxState
= flagToMaybe
(installIndexState installFlags
)
433 installedPkgIndex
<- getInstalledPackages verbosity comp packageDBs progdb
434 (sourcePkgDb
, _
, _
) <- getSourcePackagesAtIndexState verbosity repoCtxt idxState Nothing
435 pkgConfigDb
<- readPkgConfigDb verbosity progdb
440 (packageIndex sourcePkgDb
)
442 transport
<- repoContextGetTransport repoCtxt
444 (userTargets
, pkgSpecifiers
) <- case mUserTargets
of
446 -- We want to distinguish between the case where the user has given an
447 -- empty list of targets on the command-line and the case where we
448 -- specifically want to have an empty list of targets.
450 Just userTargets0
-> do
451 -- For install, if no target is given it means we use the current
452 -- directory as the single target.
454 |
null userTargets0
= [UserTargetLocalDir
"."]
455 |
otherwise = userTargets0
461 (packageIndex sourcePkgDb
)
463 return (userTargets
, pkgSpecifiers
)
474 -- | Make an install plan given install context and install arguments.
479 -> IO (Progress
String String SolverInstallPlan
)
502 notice verbosity
"Resolving dependencies..."
516 -- | Given an install plan, perform the actual installations.
525 args
@(_
, _
, _
, _
, _
, _
, configFlags
, _
, installFlags
, _
, _
, _
)
542 unless (dryRun || nothingToInstall
) $ do
549 postInstallActions verbosity args userTargets installPlan buildOutcomes
551 installPlan
= InstallPlan
.configureInstallPlan configFlags installPlan0
552 dryRun
= fromFlag
(installDryRun installFlags
)
553 nothingToInstall
= null (fst (InstallPlan
.ready installPlan
))
555 -- ------------------------------------------------------------
557 -- * Installation planning
559 -- ------------------------------------------------------------
568 -> InstalledPackageIndex
571 -> [PackageSpecifier UnresolvedSourcePackage
]
572 -> Progress
String String SolverInstallPlan
589 >>= if onlyDeps
then pruneInstallPlan pkgSpecifiers
else return
593 ( if maxBackjumps
< 0
595 else Just maxBackjumps
597 . setIndependentGoals independentGoals
598 . setReorderGoals reorderGoals
599 . setCountConflicts countConflicts
600 . setFineGrainedConflicts fineGrainedConflicts
601 . setMinimizeConflictSet minimizeConflictSet
602 . setAvoidReinstalls avoidReinstalls
603 . setShadowPkgs shadowPkgs
604 . setStrongFlags strongFlags
605 . setAllowBootLibInstalls allowBootLibInstalls
606 . setOnlyConstrained onlyConstrained
607 . setSolverVerbosity verbosity
608 . setPreferenceDefault
611 else PreferLatestForSelected
613 . removeLowerBounds allowOlder
614 . removeUpperBounds allowNewer
616 -- preferences from the config file or command line
617 [ PackageVersionPreference name ver
618 | PackageVersionConstraint name ver
<- configPreferences configExFlags
621 -- version constraints from the config file or command line
622 [ LabeledPackageConstraint
(userToPackageConstraint pc
) src
623 |
(pc
, src
) <- configExConstraints configExFlags
626 -- FIXME: this just applies all flags to all targets which
627 -- is silly. We should check if the flags are appropriate
630 (scopeToplevel
$ pkgSpecifierTarget pkgSpecifier
)
631 (PackagePropertyFlags flags
)
632 in LabeledPackageConstraint pc ConstraintSourceConfigFlagOrTarget
633 |
let flags
= configConfigurationsFlags configFlags
634 , not (nullFlagAssignment flags
)
635 , pkgSpecifier
<- pkgSpecifiers
640 (scopeToplevel
$ pkgSpecifierTarget pkgSpecifier
)
641 (PackagePropertyStanzas stanzas
)
642 in LabeledPackageConstraint pc ConstraintSourceConfigFlagOrTarget
643 | pkgSpecifier
<- pkgSpecifiers
645 . (if reinstall
then reinstallTargets
else id)
646 -- Don't solve for executables, the legacy install codepath
647 -- doesn't understand how to install them
648 . setSolveExecutables
(SolveExecutables
False)
649 $ standardInstallPolicy
655 [TestStanzas | testsEnabled
]
656 ++ [BenchStanzas | benchmarksEnabled
]
657 testsEnabled
= fromFlagOrDefault
False $ configTests configFlags
658 benchmarksEnabled
= fromFlagOrDefault
False $ configBenchmarks configFlags
661 fromFlag
(installOverrideReinstall installFlags
)
662 || fromFlag
(installReinstall installFlags
)
663 reorderGoals
= fromFlag
(installReorderGoals installFlags
)
664 countConflicts
= fromFlag
(installCountConflicts installFlags
)
665 fineGrainedConflicts
= fromFlag
(installFineGrainedConflicts installFlags
)
666 minimizeConflictSet
= fromFlag
(installMinimizeConflictSet installFlags
)
667 independentGoals
= fromFlag
(installIndependentGoals installFlags
)
668 avoidReinstalls
= fromFlag
(installAvoidReinstalls installFlags
)
669 shadowPkgs
= fromFlag
(installShadowPkgs installFlags
)
670 strongFlags
= fromFlag
(installStrongFlags installFlags
)
671 maxBackjumps
= fromFlag
(installMaxBackjumps installFlags
)
672 allowBootLibInstalls
= fromFlag
(installAllowBootLibInstalls installFlags
)
673 onlyConstrained
= fromFlag
(installOnlyConstrained installFlags
)
674 upgradeDeps
= fromFlag
(installUpgradeDeps installFlags
)
675 onlyDeps
= fromFlag
(installOnlyDeps installFlags
)
680 (configAllowOlder configExFlags
)
684 (configAllowNewer configExFlags
)
686 -- | Remove the provided targets from the install plan.
689 => [PackageSpecifier targetpkg
]
691 -> Progress
String String SolverInstallPlan
692 pruneInstallPlan pkgSpecifiers
=
693 -- TODO: this is a general feature and should be moved to D.C.Dependency
694 -- Also, the InstallPlan.remove should return info more precise to the
695 -- problem, rather than the very general PlanProblem type.
696 either (Fail
. explain
) Done
697 . SolverInstallPlan
.remove
(\pkg
-> packageName pkg `
elem` targetnames
)
699 explain
:: [SolverInstallPlan
.SolverPlanProblem
] -> String
701 "Cannot select only the dependencies (as requested by the "
702 ++ "'--only-dependencies' flag), "
704 [pkgid
] -> "the package " ++ prettyShow pkgid
++ " is "
707 ++ intercalate
", " (map prettyShow pkgids
)
710 ++ "required by a dependency of one of the other targets."
715 | SolverInstallPlan
.PackageMissingDeps _ depids
<- problems
717 , packageName depid `
elem` targetnames
720 targetnames
= map pkgSpecifierTarget pkgSpecifiers
722 -- ------------------------------------------------------------
724 -- * Informational messages
726 -- ------------------------------------------------------------
728 -- | Perform post-solver checks of the install plan and print it if
729 -- either requested or needed.
732 -> InstalledPackageIndex
736 -> [PackageSpecifier UnresolvedSourcePackage
]
745 -- User targets that are already installed.
746 let preExistingTargets
=
747 [ p |
let tgts
= map pkgSpecifierTarget pkgSpecifiers
, InstallPlan
.PreExisting p
<- InstallPlan
.toList installPlan
, packageName p `
elem` tgts
750 -- If there's nothing to install, we print the already existing
751 -- target packages as an explanation.
752 when nothingToInstall
$
755 "All the requested packages are already installed:"
756 : map (prettyShow
. packageId
) preExistingTargets
757 ++ ["Use --reinstall if you want to reinstall anyway."]
761 | pkg
<- InstallPlan
.executionOrder installPlan
762 , let status
= packageStatus installed pkg
764 -- Are any packages classified as reinstalls?
765 let reinstalledPkgs
=
767 |
(_pkg
, status
) <- lPlan
768 , ipkg
<- extractReinstalls status
770 -- Packages that are already broken.
772 map Installed
.installedUnitId
773 . PackageIndex
.reverseDependencyClosure installed
774 . map (Installed
.installedUnitId
. fst)
775 . PackageIndex
.brokenPackages
777 let excluded
= reinstalledPkgs
++ oldBrokenPkgs
778 -- Packages that are reverse dependencies of replaced packages are very
779 -- likely to be broken. We exclude packages that are already broken.
782 (\p
-> not (Installed
.installedUnitId p `
elem` excluded
))
783 (PackageIndex
.reverseDependencyClosure installed reinstalledPkgs
)
784 let containsReinstalls
= not (null reinstalledPkgs
)
785 let breaksPkgs
= not (null newBrokenPkgs
)
789 , not overrideReinstall
=
790 modifyVerbosity
(max verbose
) verbosity
791 |
otherwise = verbosity
793 -- We print the install plan if we are in a dry-run or if we are confronted
794 -- with a dangerous install plan.
795 when (dryRun || containsReinstalls
&& not overrideReinstall
) $
797 (dryRun || breaksPkgs
&& not overrideReinstall
)
802 -- If the install plan is dangerous, we print various warning messages. In
803 -- particular, if we can see that packages are likely to be broken, we even
804 -- bail out (unless installation has been forced with --force-reinstalls).
805 when containsReinstalls
$ do
808 "The following packages are likely to be broken by the reinstalls:"
809 : map (prettyShow
. mungedId
) newBrokenPkgs
810 ++ if overrideReinstall
815 [ "Continuing even though "
816 ++ "the plan contains dangerous reinstalls."
818 else ["Use --force-reinstalls if you want to install anyway."]
821 ( if dryRun || overrideReinstall
822 then warn verbosity errorStr
823 else dieWithException verbosity
$ BrokenException errorStr
829 "Note that reinstalls are always dangerous. Continuing anyway..."
831 -- If we are explicitly told to not download anything, check that all packages
832 -- are already fetched.
833 let offline
= fromFlagOrDefault
False (installOfflineMode installFlags
)
837 | InstallPlan
.Configured cpkg
<- InstallPlan
.toList installPlan
841 . filterM (fmap isNothing . checkFetched
. srcpkgSource
)
843 unless (null notFetched
) $
844 dieWithException verbosity
$
845 Can
'tDownloadPackagesOffline
(map prettyShow notFetched
)
847 nothingToInstall
= null (fst (InstallPlan
.ready installPlan
))
849 dryRun
= fromFlag
(installDryRun installFlags
)
850 overrideReinstall
= fromFlag
(installOverrideReinstall installFlags
)
854 | NewVersion
[Version
]
855 | Reinstall
[UnitId
] [PackageChange
]
857 type PackageChange
= MergeResult MungedPackageId MungedPackageId
859 extractReinstalls
:: PackageStatus
-> [UnitId
]
860 extractReinstalls
(Reinstall ipids _
) = ipids
861 extractReinstalls _
= []
864 :: InstalledPackageIndex
867 packageStatus installedPkgIndex cpkg
=
868 case PackageIndex
.lookupPackageName
870 (packageName cpkg
) of
876 (concatMap snd ps
) of
877 [] -> NewVersion
(map fst ps
)
880 (map Installed
.installedUnitId pkgs
)
884 :: Installed
.InstalledPackageInfo
887 changes pkg
(ReadyPackage pkg
') =
890 (comparing mungedName
)
891 -- deps of installed pkg
892 (resolveInstalledIds
$ Installed
.depends pkg
)
893 -- deps of configured pkg
894 (resolveInstalledIds
$ CD
.nonSetupDeps
(depends pkg
'))
896 -- convert to source pkg ids via index
897 resolveInstalledIds
:: [UnitId
] -> [MungedPackageId
]
898 resolveInstalledIds
=
902 . mapMaybe (PackageIndex
.lookupUnitId installedPkgIndex
)
904 changed
(InBoth pkgid pkgid
') = pkgid
/= pkgid
'
908 :: Bool -- is dry run
910 -> [(ReadyPackage
, PackageStatus
)]
913 printPlan dryRun verbosity plan sourcePkgDb
= case plan
of
916 | verbosity
>= Verbosity
.verbose
->
919 ("In order, the following " ++ wouldWill
++ " be installed:")
920 : map showPkgAndReason pkgs
924 ( "In order, the following "
926 ++ " be installed (use -v for more details):"
935 prettyShow
(packageId pkg
)
938 showPkgAndReason
(ReadyPackage pkg
', pr
) =
940 [ prettyShow
(packageId pkg
')
942 , showFlagAssignment
(nonDefaultFlags pkg
')
943 , showStanzas
(confPkgStanzas pkg
')
946 NewPackage
-> "(new package)"
947 NewVersion _
-> "(new version)"
949 "(reinstall)" ++ case cs
of
953 ++ intercalate
", " (map change diff
)
957 showLatest
:: Package srcpkg
=> srcpkg
-> String
958 showLatest pkg
= case mLatestVersion
of
959 Just latestVersion
->
960 if packageVersion pkg
< latestVersion
961 then ("(latest: " ++ prettyShow latestVersion
++ ")")
965 mLatestVersion
:: Maybe Version
967 fmap packageVersion
$
969 SourcePackageIndex
.lookupPackageName
970 (packageIndex sourcePkgDb
)
973 toFlagAssignment
:: [PackageFlag
] -> FlagAssignment
974 toFlagAssignment
= mkFlagAssignment
. map (\f -> (flagName f
, flagDefault f
))
976 nonDefaultFlags
:: ConfiguredPackage loc
-> FlagAssignment
977 nonDefaultFlags cpkg
=
978 let defaultAssignment
=
981 ( SourcePackage
.srcpkgDescription
$
985 in confPkgFlags cpkg `diffFlagAssignment` defaultAssignment
987 change
(OnlyInLeft pkgid
) = prettyShow pkgid
++ " removed"
988 change
(InBoth pkgid pkgid
') =
991 ++ prettyShow
(mungedVersion pkgid
')
992 change
(OnlyInRight pkgid
') = prettyShow pkgid
' ++ " added"
995 | Just rdeps
<- Map
.lookup (packageId pkg
) revDeps
=
996 " (via: " ++ unwords (map prettyShow rdeps
) ++ ")"
999 revDepGraphEdges
:: [(PackageId
, PackageId
)]
1001 [ (rpid
, packageId cpkg
)
1002 |
(ReadyPackage cpkg
, _
) <- plan
1006 ( PackageDescription
.CLibName
1007 PackageDescription
.LMainLibName
1011 CD
.flatDeps
(confPkgDeps cpkg
)
1014 revDeps
:: Map
.Map PackageId
[PackageId
]
1015 revDeps
= Map
.fromListWith
(++) (map (fmap (: [])) revDepGraphEdges
)
1017 -- ------------------------------------------------------------
1019 -- * Post installation stuff
1021 -- ------------------------------------------------------------
1023 -- | Report a solver failure. This works slightly differently to
1024 -- 'postInstallActions', as (by definition) we don't have an install plan.
1025 reportPlanningFailure
1031 reportPlanningFailure
1046 (_
, sourcePkgDb
, _
, _
, pkgSpecifiers
, _
)
1048 when reportFailure
$ do
1049 -- Only create reports for explicitly named packages
1052 (SourcePackageIndex
.elemByPackageId
(packageIndex sourcePkgDb
))
1053 $ mapMaybe theSpecifiedPackage pkgSpecifiers
1056 BuildReports
.fromPlanningFailure
1060 (configConfigurationsFlags configFlags
)
1062 unless (null buildReports
) $
1064 "Solver failure will be reported for "
1065 ++ intercalate
"," (map prettyShow pkgids
)
1068 BuildReports
.storeLocal
1070 (fromNubList
$ installSummaryFile installFlags
)
1076 Nothing
-> return ()
1077 Just template
-> for_ pkgids
$ \pkgid
->
1079 initialPathTemplateEnv
1084 path
= fromPathTemplate
$ substPathTemplate env template
1085 in writeFile path message
1087 reportFailure
= fromFlag
(installReportPlanningFailure installFlags
)
1088 logFile
= flagToMaybe
(installLogFile installFlags
)
1090 -- A IPID is calculated from the transitive closure of
1091 -- dependencies, but when the solver fails we don't have that.
1093 dummyIpid
= error "reportPlanningFailure: installed package ID not available"
1095 -- | If a 'PackageSpecifier' refers to a single package, return Just that
1097 theSpecifiedPackage
:: Package pkg
=> PackageSpecifier pkg
-> Maybe PackageId
1098 theSpecifiedPackage pkgSpec
=
1100 NamedPackage name
[PackagePropertyVersion version
] ->
1101 PackageIdentifier name
<$> trivialRange version
1102 NamedPackage _ _
-> Nothing
1103 SpecificSourcePackage pkg
-> Just
$ packageId pkg
1105 -- \| If a range includes only a single version, return Just that version.
1106 trivialRange
:: VersionRange
-> Maybe Version
1116 -- | Various stuff we do after successful or unsuccessfully installing a bunch
1117 -- of packages. This includes:
1119 -- * build reporting, local and remote
1120 -- * symlinking binaries
1121 -- * updating indexes
1122 -- * error reporting
1149 BuildReports
.fromInstallPlan
1154 BuildReports
.storeLocal
1156 (fromNubList
$ installSummaryFile installFlags
)
1159 when (reportingLevel
>= AnonymousReports
) $
1160 BuildReports
.storeAnonymous buildReports
1161 when (reportingLevel
== DetailedReports
) $
1162 storeDetailedBuildReports verbosity logsDir buildReports
1164 regenerateHaddockIndex
1183 printBuildFailures verbosity buildOutcomes
1185 reportingLevel
= fromFlag
(installBuildReports installFlags
)
1186 logsDir
= fromFlag
(globalLogsDir globalFlags
)
1188 storeDetailedBuildReports
1191 -> [(BuildReports
.BuildReport
, Maybe Repo
)]
1193 storeDetailedBuildReports verbosity logsDir reports
=
1196 allReportsDir
<- defaultReportsDir
1197 let logFileName
= prettyShow
(BuildReports
.package report
) <.> "log"
1198 logFile
= logsDir
</> logFileName
1199 reportsDir
= allReportsDir
</> unRepoName
(remoteRepoName remoteRepo
)
1200 reportFile
= reportsDir
</> logFileName
1202 handleMissingLogFile
$ do
1203 buildLog
<- readFile logFile
1204 createDirectoryIfMissing
True reportsDir
-- FIXME
1205 writeFile reportFile
(show (showBuildReport report
, buildLog
))
1206 |
(report
, Just repo
) <- reports
1207 , Just remoteRepo
<- [maybeRepoRemote repo
]
1208 , isLikelyToHaveLogFile
(BuildReports
.installOutcome report
)
1211 isLikelyToHaveLogFile BuildReports
.ConfigureFailed
{} = True
1212 isLikelyToHaveLogFile BuildReports
.BuildFailed
{} = True
1213 isLikelyToHaveLogFile BuildReports
.InstallFailed
{} = True
1214 isLikelyToHaveLogFile BuildReports
.InstallOk
{} = True
1215 isLikelyToHaveLogFile _
= False
1217 handleMissingLogFile
= Exception
.handleJust missingFile
$ \ioe
->
1219 "Missing log file for build report: "
1220 ++ fromMaybe "" (ioeGetFileName ioe
)
1223 |
isDoesNotExistError ioe
= Just ioe
1224 missingFile _
= Nothing
1226 regenerateHaddockIndex
1236 regenerateHaddockIndex
1245 | haddockIndexFileIsRequested
&& shouldRegenerateHaddockIndex
= do
1247 InstallDirs
.defaultInstallDirs
1248 (compilerFlavor comp
)
1249 (fromFlag
(configUserInstall configFlags
))
1251 let indexFileTemplate
= fromFlag
(installHaddockIndex installFlags
)
1252 indexFile
= substHaddockIndexFileName defaultDirs indexFileTemplate
1255 "Updating documentation index " ++ indexFile
1257 -- TODO: might be nice if the install plan gave us the new InstalledPackageInfo
1258 installedPkgIndex
<- getInstalledPackages verbosity comp packageDBs progdb
1259 Haddock
.regenerateHaddockIndex verbosity installedPkgIndex progdb indexFile
1260 |
otherwise = return ()
1262 haddockIndexFileIsRequested
=
1263 fromFlag
(installDocumentation installFlags
)
1264 && isJust (flagToMaybe
(installHaddockIndex installFlags
))
1266 -- We want to regenerate the index if some new documentation was actually
1267 -- installed. Since the index can be only per-user or per-sandbox (see
1268 -- #1337), we don't do it for global installs or special cases where we're
1269 -- installing into a specific db.
1270 shouldRegenerateHaddockIndex
= normalUserInstall
&& someDocsWereInstalled buildOutcomes
1272 someDocsWereInstalled
= any installedDocs
. Map
.elems
1273 installedDocs
(Right
(BuildResult DocsOk _ _
)) = True
1274 installedDocs _
= False
1277 (UserPackageDB `
elem` packageDBs
)
1278 && all (not . isSpecificPackageDB
) packageDBs
1279 isSpecificPackageDB
(SpecificPackageDB _
) = True
1280 isSpecificPackageDB _
= False
1282 substHaddockIndexFileName defaultDirs
=
1284 . substPathTemplate env
1286 env
= env0
++ installDirsTemplateEnv absoluteDirs
1288 InstallDirs
.compilerTemplateEnv
(compilerInfo comp
)
1289 ++ InstallDirs
.platformTemplateEnv platform
1290 ++ InstallDirs
.abiTemplateEnv
(compilerInfo comp
) platform
1292 InstallDirs
.substituteInstallDirTemplates
1296 InstallDirs
.combineInstallDirs
1299 (configInstallDirs configFlags
)
1319 InstallSymlink
.symlinkBinaries
1331 "could not create a symlink in "
1335 ++ " because the file exists there already but is not "
1336 ++ "managed by cabal. You can create a symlink for this executable "
1337 ++ "manually if you wish. The executable file has been installed at "
1341 "could not create symlinks in "
1344 ++ intercalate
", " [prettyShow exe |
(_
, exe
, _
) <- exes
]
1345 ++ " because the files exist there already and are not "
1346 ++ "managed by cabal. You can create symlinks for these executables "
1347 ++ "manually if you wish. The executable files have been installed at "
1348 ++ intercalate
", " [path |
(_
, _
, path
) <- exes
]
1350 bindir
= fromFlag
(installSymlinkBinDir installFlags
)
1352 printBuildFailures
:: Verbosity
-> BuildOutcomes
-> IO ()
1353 printBuildFailures verbosity buildOutcomes
=
1354 case [ (pkgid
, failure
)
1355 |
(pkgid
, Left failure
) <- Map
.toList buildOutcomes
1359 dieWithException verbosity
$
1360 SomePackagesFailedToInstall
$
1361 map (\(pkgid
, reason
) -> (prettyShow pkgid
, printFailureReason reason
)) failed
1363 printFailureReason reason
= case reason
of
1364 GracefulFailure msg
-> msg
1365 DependentFailed pkgid
->
1368 ++ " which failed to install."
1370 " failed while downloading the package."
1373 " failed while unpacking the package."
1375 ConfigureFailed e
->
1376 " failed during the configure step."
1379 " failed during the building phase."
1382 " failed during the tests phase."
1385 " failed during the final install step."
1387 -- This will never happen, but we include it for completeness
1388 PlanningFailed
-> " failed during the planning phase."
1390 showException e
= " The exception was:\n " ++ show e
++ maybeOOM e
1391 #ifdef mingw32_HOST_OS
1394 maybeOOM e
= maybe "" onExitFailure
(fromException e
)
1395 onExitFailure
(ExitFailure n
)
1396 | n
== 9 || n
== -9 =
1397 "\nThis may be due to an out-of-memory condition."
1398 onExitFailure _
= ""
1401 -- ------------------------------------------------------------
1403 -- * Actually do the installations
1405 -- ------------------------------------------------------------
1407 data InstallMisc
= InstallMisc
1408 { libVersion
:: Maybe Version
1411 -- | If logging is enabled, contains location of the log file and the verbosity
1412 -- level for logging.
1413 type UseLogFile
= Maybe (PackageIdentifier
-> UnitId
-> FilePath, Verbosity
)
1415 performInstallations
1418 -> InstalledPackageIndex
1421 performInstallations
1438 info verbosity
$ "Number of threads used: " ++ (show numJobs
) ++ "."
1442 then newParallelJobControl numJobs
1443 else newSerialJobControl
1444 fetchLimit
<- newJobLimit
(min numJobs numFetchJobs
)
1445 installLock
<- newLock
-- serialise installation
1446 cacheLock
<- newLock
-- serialise access to setup exe cache
1459 $ \configFlags
' src pkg pkgoverride
->
1460 fetchSourcePackage verbosity repoCtxt fetchLimit src
$ \src
' ->
1461 installLocalPackage verbosity
(packageId pkg
) src
' distPref
$ \mpath
->
1462 installUnpackedPackage
1466 ( setupScriptOptions
1484 cinfo
= compilerInfo comp
1486 numJobs
= determineNumJobs
(installNumJobs installFlags
)
1488 parallelInstall
= numJobs
>= 2
1489 keepGoing
= fromFlag
(installKeepGoing installFlags
)
1492 (useDistPref defaultSetupScriptOptions
)
1493 (setupDistPref
$ configCommonFlags configFlags
)
1495 setupScriptOptions
index lock rpkg
=
1496 configureSetupScript
1502 (chooseCabalVersion configExFlags
(libVersion miscOptions
))
1508 reportingLevel
= fromFlag
(installBuildReports installFlags
)
1509 logsDir
= fromFlag
(globalLogsDir globalFlags
)
1511 -- Should the build output be written to a log file instead of stdout?
1512 useLogFile
:: UseLogFile
1515 ((\f -> (f
, loggingVerbosity
)) . substLogFileName
)
1518 installLogFile
' = flagToMaybe
$ installLogFile installFlags
1521 logsDir
</> "$compiler" </> "$libname" <.> "log"
1523 -- If the user has specified --remote-build-reporting=detailed, use the
1524 -- default log file location. If the --build-log option is set, use the
1525 -- provided location. Otherwise don't use logging, unless building in
1526 -- parallel (in which case the default location is used).
1527 logFileTemplate
:: Maybe PathTemplate
1529 | useDefaultTemplate
= Just defaultTemplate
1530 |
otherwise = installLogFile
'
1532 -- If the user has specified --remote-build-reporting=detailed or
1533 -- --build-log, use more verbose logging.
1534 loggingVerbosity
:: Verbosity
1536 | overrideVerbosity
= modifyVerbosity
(max verbose
) verbosity
1537 |
otherwise = verbosity
1539 useDefaultTemplate
:: Bool
1541 | reportingLevel
== DetailedReports
= True
1542 |
isJust installLogFile
' = False
1543 | parallelInstall
= True
1546 overrideVerbosity
:: Bool
1548 | reportingLevel
== DetailedReports
= True
1549 |
isJust installLogFile
' = True
1550 | parallelInstall
= False
1553 substLogFileName
:: PathTemplate
-> PackageIdentifier
-> UnitId
-> FilePath
1554 substLogFileName template pkg uid
=
1556 . substPathTemplate env
1560 initialPathTemplateEnv
1568 { libVersion
= flagToMaybe
(configCabalVersion configExFlags
)
1573 -> JobControl
IO (UnitId
, BuildOutcome
)
1577 -> (ReadyPackage
-> IO BuildOutcome
)
1579 executeInstallPlan verbosity jobCtl keepGoing useLogFile plan0 installPkg
=
1586 buildOutcome
<- installPkg pkg
1587 printBuildResult
(packageId pkg
) (installedUnitId pkg
) buildOutcome
1590 depsFailure
= DependentFailed
. packageId
1592 -- Print build log if something went wrong, and 'Installed $PKGID'
1594 printBuildResult
:: PackageId
-> UnitId
-> BuildOutcome
-> IO ()
1595 printBuildResult pkgid uid buildOutcome
= case buildOutcome
of
1596 (Right _
) -> progressMessage verbosity ProgressCompleted
(prettyShow pkgid
)
1598 notice verbosity
$ "Failed to install " ++ prettyShow pkgid
1599 when (verbosity
>= normal
) $
1601 Nothing
-> return ()
1602 Just
(mkLogFileName
, _
) -> do
1603 let logName
= mkLogFileName pkgid uid
1604 putStr $ "Build log ( " ++ logName
++ " ):\n"
1607 printFile
:: FilePath -> IO ()
1608 printFile path
= readFile path
>>= putStr
1610 -- | Call an installer for an 'SourcePackage' but override the configure
1611 -- flags with the ones given by the 'ReadyPackage'. In particular the
1612 -- 'ReadyPackage' specifies an exact 'FlagAssignment' and exactly
1613 -- versioned package dependencies. So we ignore any previous partial flag
1614 -- assignment or dependency constraints and use the new ones.
1616 -- NB: when updating this function, don't forget to also update
1617 -- 'configurePackage' in D.C.Configure.
1625 -> PackageDescription
1626 -> PackageDescriptionOverride
1637 (SourcePackage _ gpkg source pkgoverride
)
1646 { configIPID
= toFlag
(prettyShow ipid
)
1647 , configConfigurationsFlags
= flags
1648 , -- We generate the legacy constraints as well as the new style precise deps.
1649 -- In the end only one set gets passed to Setup.hs configure, depending on
1650 -- the Cabal version we are talking to.
1652 [ thisPackageVersionConstraint srcid
1656 ( PackageDescription
.CLibName
1657 PackageDescription
.LMainLibName
1661 CD
.nonSetupDeps deps
1663 , configDependencies
=
1664 [ GivenComponent
(packageName srcid
) cname dep_ipid
1665 | ConfiguredId srcid
(Just
(PackageDescription
.CLibName cname
)) dep_ipid
<-
1666 CD
.nonSetupDeps deps
1668 , -- Use '--exact-configuration' if supported.
1669 configExactConfiguration
= toFlag
True
1670 , configBenchmarks
= toFlag
False
1671 , configTests
= toFlag
(TestStanzas `optStanzaSetMember` stanzas
)
1677 pkg
= case finalizePD
1679 (enableStanzas stanzas
)
1685 Left _
-> error "finalizePD ReadyPackage failed"
1686 Right
(desc
, _
) -> desc
1693 -> (ResolvedPkgLoc
-> IO BuildOutcome
)
1695 fetchSourcePackage verbosity repoCtxt fetchLimit src installPkg
= do
1696 fetched
<- checkFetched src
1698 Just src
' -> installPkg src
'
1699 Nothing
-> onFailure DownloadFailed
$ do
1701 withJobLimit fetchLimit
$
1702 fetchPackage verbosity repoCtxt src
1707 -> PackageIdentifier
1709 -> SymbolicPath Pkg
(Dir Dist
)
1710 -> (Maybe FilePath -> IO BuildOutcome
)
1712 installLocalPackage verbosity pkgid location distPref installPkg
=
1714 LocalUnpackedPackage dir
->
1715 installPkg
(Just dir
)
1716 RemoteSourceRepoPackage _repo dir
->
1717 installPkg
(Just dir
)
1718 LocalTarballPackage tarballPath
->
1719 installLocalTarballPackage
1725 RemoteTarballPackage _ tarballPath
->
1726 installLocalTarballPackage
1732 RepoTarballPackage _ _ tarballPath
->
1733 installLocalTarballPackage
1740 installLocalTarballPackage
1742 -> PackageIdentifier
1744 -> SymbolicPath Pkg
(Dir Dist
)
1745 -> (Maybe FilePath -> IO BuildOutcome
)
1747 installLocalTarballPackage
1753 tmp
<- getTemporaryDirectory
1754 withTempDirectory verbosity tmp
"cabal-tmp" $ \tmpDirPath
->
1755 onFailure UnpackFailed
$ do
1756 let relUnpackedPath
= prettyShow pkgid
1757 absUnpackedPath
= tmpDirPath
</> relUnpackedPath
1760 </> prettyShow
(packageName pkgid
)
1768 extractTarGzFile tmpDirPath relUnpackedPath tarballPath
1769 exists
<- doesFileExist descFilePath
1771 dieWithException verbosity
$
1772 PackageDotCabalFileNotFound descFilePath
1773 maybeRenameDistDir absUnpackedPath
1774 installPkg
(Just absUnpackedPath
)
1776 -- 'cabal sdist' puts pre-generated files in the 'dist'
1777 -- directory. This fails when a nonstandard build directory name
1778 -- is used (as is the case with sandboxes), so we need to rename
1779 -- the 'dist' dir here.
1781 -- TODO: 'cabal get happy && cd sandbox && cabal install ../happy' still
1782 -- fails even with this workaround. We probably can live with that.
1783 maybeRenameDistDir
:: FilePath -> IO ()
1784 maybeRenameDistDir absUnpackedPath
= do
1785 let distDirPath
= absUnpackedPath
</> getSymbolicPath defaultDistPref
1786 distDirPathTmp
= absUnpackedPath
</> (getSymbolicPath defaultDistPref
++ "-tmp")
1787 distDirPathNew
= absUnpackedPath
</> getSymbolicPath distPref
1788 distDirExists
<- doesDirectoryExist distDirPath
1791 && not (distDirPath `equalFilePath` distDirPathNew
)
1794 -- NB: we need to handle the case when 'distDirPathNew' is a
1795 -- subdirectory of 'distDirPath' (e.g. the former is
1796 -- 'dist/dist-sandbox-3688fbc2' and the latter is 'dist').
1803 renameDirectory distDirPath distDirPathTmp
1804 when (distDirPath `
isPrefixOf` distDirPathNew
) $
1805 createDirectoryIfMissingVerbose verbosity
False distDirPath
1812 renameDirectory distDirPathTmp distDirPathNew
1814 installUnpackedPackage
1818 -> SetupScriptOptions
1826 -> PackageDescription
1828 -> PackageDescriptionOverride
1830 -- ^ Directory to change to before starting the installation.
1832 -- ^ File to log output to (if any)
1834 installUnpackedPackage
1851 -- Override the .cabal file if necessary
1853 Nothing
-> return ()
1856 fromMaybe "." workingDir
1857 </> prettyShow
(packageName pkgid
)
1861 ++ prettyShow
(packageName pkgid
) <.> "cabal"
1862 ++ " with the latest revision from the index."
1863 writeFileAtomic descFilePath pkgtxt
1865 let mbWorkDir
= fmap makeSymbolicPath workingDir
1867 (`filterCommonFlags` ver
) $
1868 defaultCommonSetupFlags
1869 { setupDistPref
= setupDistPref
$ configCommonFlags configFlags
1870 , setupVerbosity
= toFlag verbosity
'
1871 , setupWorkingDir
= maybeToFlag mbWorkDir
1874 -- Make sure that we pass --libsubdir etc to 'setup configure' (necessary if
1875 -- the setup script was compiled against an old version of the Cabal lib).
1876 configFlags
' <- addDefaultInstallDirs configFlags
1877 -- Filter out flags not supported by the old versions of the Cabal lib.
1878 let configureFlags
:: Version
-> ConfigFlags
1880 filterConfigureFlags
1882 { configCommonFlags
=
1883 (configCommonFlags
(configFlags
'))
1884 { setupVerbosity
= toFlag verbosity
'
1889 emptyBuildFlags
{buildCommonFlags
= commonFlags vers
}
1890 shouldHaddock
= fromFlag
(installDocumentation installFlags
)
1891 haddockFlags
' vers
=
1892 haddockFlags
{haddockCommonFlags
= commonFlags vers
}
1894 fromFlag
(configTests configFlags
)
1895 && fromFlagOrDefault
False (installRunTests installFlags
)
1897 (`filterTestFlags` vers
) $
1898 testFlags
{testCommonFlags
= commonFlags vers
}
1900 Cabal
.emptyCopyFlags
1901 { Cabal
.copyDest
= toFlag InstallDirs
.NoCopyDest
1902 , copyCommonFlags
= commonFlags vers
1904 shouldRegister
= PackageDescription
.hasLibs pkg
1905 registerFlags vers
=
1906 Cabal
.emptyRegisterFlags
1907 { registerCommonFlags
= commonFlags vers
1910 -- Path to the optional log file.
1911 mLogPath
<- maybeLogPath
1913 logDirChange
(maybe (const (return ())) appendFile mLogPath
) workingDir
$ do
1915 onFailure ConfigureFailed
$ do
1916 noticeProgress ProgressStarting
1917 setup configureCommand configCommonFlags configureFlags mLogPath
1920 onFailure BuildFailed
$ do
1921 noticeProgress ProgressBuilding
1922 setup buildCommand
' buildCommonFlags buildFlags mLogPath
1924 -- Doc generation phase
1929 setup haddockCommand haddockCommonFlags haddockFlags
' mLogPath
1932 `catchIO`
(\_
-> return DocsFailed
)
1933 `catchExit`
(\_
-> return DocsFailed
)
1934 else return DocsNotTried
1937 onFailure TestsFailed
$ do
1938 when (testsEnabled
&& PackageDescription
.hasTests pkg
) $
1939 setup Cabal
.testCommand testCommonFlags testFlags
' mLogPath
1942 | testsEnabled
= TestsOk
1943 |
otherwise = TestsNotTried
1946 onFailure InstallFailed
$ criticalSection installLock
$ do
1947 -- Actual installation
1948 withWin32SelfUpgrade
1956 setup Cabal
.copyCommand copyCommonFlags copyFlags mLogPath
1958 -- Capture installed package configuration file, so that
1959 -- it can be incorporated into the final InstallPlan
1962 then genPkgConfs registerFlags mLogPath
1964 let ipkgs
' = case ipkgs
of
1965 [ipkg
] -> [ipkg
{Installed
.installedUnitId
= uid
}]
1968 interpretPackageDbFlags
1969 (fromFlag
(configUserInstall configFlags
))
1970 (configPackageDBs configFlags
)
1971 for_ ipkgs
' $ \ipkg
' ->
1979 defaultRegisterOptions
1981 return (Right
(BuildResult docsResult testsResult
(find ((== uid
) . installedUnitId
) ipkgs
')))
1983 pkgid
= packageId pkg
1984 uid
= installedUnitId rpkg
1985 cinfo
= compilerInfo comp
1986 buildCommand
' = buildCommand progdb
1987 dispname
= prettyShow pkgid
1988 isParallelBuild
= numJobs
>= 2
1990 noticeProgress
phase =
1991 when isParallelBuild
$
1992 progressMessage verbosity
phase dispname
1993 verbosity
' = maybe verbosity
snd useLogFile
1994 tempTemplate name
= name
++ "-" ++ prettyShow pkgid
1996 addDefaultInstallDirs
:: ConfigFlags
-> IO ConfigFlags
1997 addDefaultInstallDirs configFlags
' = do
1998 defInstallDirs
<- InstallDirs
.defaultInstallDirs flavor userInstall
False
2001 { configInstallDirs
=
2003 . InstallDirs
.substituteInstallDirTemplates env
2004 $ InstallDirs
.combineInstallDirs
2007 (configInstallDirs configFlags
)
2010 CompilerId flavor _
= compilerInfoId cinfo
2011 env
= initialPathTemplateEnv pkgid uid cinfo platform
2015 (configUserInstall configFlags
')
2018 :: (Version
-> Cabal
.RegisterFlags
)
2020 -> IO [Installed
.InstalledPackageInfo
]
2021 genPkgConfs flags mLogPath
= do
2022 tmp
<- getTemporaryDirectory
2023 withTempDirectory verbosity tmp
(tempTemplate
"pkgConf") $ \dir
-> do
2024 let pkgConfDest
= dir
</> "pkgConf"
2025 registerFlags
' version
=
2027 { Cabal
.regGenPkgConf
= toFlag
(Just pkgConfDest
)
2030 Cabal
.registerCommand
2034 is_dir
<- doesDirectoryExist pkgConfDest
2035 let notHidden
= not . isHidden
2036 isHidden name
= "." `
isPrefixOf` name
2038 then -- Sort so that each prefix of the package
2039 -- configurations is well formed
2041 traverse
(readPkgConf pkgConfDest
) . sort . filter notHidden
2042 =<< getDirectoryContents pkgConfDest
2043 else fmap (: []) $ readPkgConf
"." pkgConfDest
2048 -> IO Installed
.InstalledPackageInfo
2049 readPkgConf pkgConfDir pkgConfFile
= do
2050 pkgConfText
<- BS
.readFile (pkgConfDir
</> pkgConfFile
)
2051 case Installed
.parseInstalledPackageInfo pkgConfText
of
2052 Left perrors
-> pkgConfParseFailed
$ unlines $ NE
.toList perrors
2053 Right
(warns
, pkgConf
) -> do
2054 unless (null warns
) $
2059 pkgConfParseFailed
:: String -> IO a
2060 pkgConfParseFailed perror
=
2061 dieWithException verbosity
$ PkgConfParsedFailed perror
2063 maybeLogPath
:: IO (Maybe FilePath)
2066 Nothing
-> return Nothing
2067 Just
(mkLogFileName
, _
) -> do
2068 let logFileName
= mkLogFileName
(packageId pkg
) uid
2069 logDir
= takeDirectory logFileName
2070 unless (null logDir
) $ createDirectoryIfMissing
True logDir
2071 logFileExists
<- doesFileExist logFileName
2072 when logFileExists
$ removeFile logFileName
2073 return (Just logFileName
)
2075 setup cmd getCommonFlags flags mLogPath
=
2077 (traverse
(\path
-> openFile path AppendMode
) mLogPath
)
2083 { useLoggingHandle
= logFileHandle
2084 , useWorkingDir
= makeSymbolicPath
<$> workingDir
2094 onFailure
:: (SomeException
-> BuildFailure
) -> IO BuildOutcome
-> IO BuildOutcome
2095 onFailure result action
=
2097 `catches`
[ Handler
$ \ioe
-> handler
(ioe
:: IOException
)
2098 , Handler
$ \cabalexe
-> handler
(cabalexe
:: VerboseException CabalException
)
2099 , Handler
$ \exit
-> handler
(exit
:: ExitCode)
2102 handler
:: Exception e
=> e
-> IO BuildOutcome
2103 handler
= return . Left
. result
. toException
2105 -- ------------------------------------------------------------
2107 -- * Weird windows hacks
2109 -- ------------------------------------------------------------
2111 withWin32SelfUpgrade
2117 -> PackageDescription
2120 withWin32SelfUpgrade _ _ _ _ _ _ action | buildOS
/= Windows
= action
2121 withWin32SelfUpgrade verbosity uid configFlags cinfo platform pkg action
= do
2123 InstallDirs
.defaultInstallDirs
2125 (fromFlag
(configUserInstall configFlags
))
2126 (PackageDescription
.hasLibs pkg
)
2128 Win32SelfUpgrade
.possibleSelfUpgrade
2130 (exeInstallPaths defaultDirs
)
2133 pkgid
= packageId pkg
2134 (CompilerId compFlavor _
) = compilerInfoId cinfo
2136 exeInstallPaths defaultDirs
=
2137 [ InstallDirs
.bindir absoluteDirs
</> exeName
<.> exeExtension buildPlatform
2138 | exe
<- PackageDescription
.executables pkg
2139 , PackageDescription
.buildable
(PackageDescription
.buildInfo exe
)
2140 , let exeName
= prefix
++ prettyShow
(PackageDescription
.exeName exe
) ++ suffix
2141 prefix
= substTemplate prefixTemplate
2142 suffix
= substTemplate suffixTemplate
2145 fromFlagTemplate
= fromFlagOrDefault
(InstallDirs
.toPathTemplate
"")
2146 prefixTemplate
= fromFlagTemplate
(configProgPrefix configFlags
)
2147 suffixTemplate
= fromFlagTemplate
(configProgSuffix configFlags
)
2149 InstallDirs
.combineInstallDirs
2152 (configInstallDirs configFlags
)
2154 InstallDirs
.absoluteInstallDirs
2158 InstallDirs
.NoCopyDest
2162 InstallDirs
.fromPathTemplate
2163 . InstallDirs
.substPathTemplate env
2166 InstallDirs
.initialPathTemplateEnv