3 -----------------------------------------------------------------------------
5 -----------------------------------------------------------------------------
8 -- Module : Distribution.Client.Install
9 -- Copyright : (c) 2005 David Himmelstrup
10 -- 2007 Bjorn Bringert
11 -- 2007-2010 Duncan Coutts
14 -- Maintainer : cabal-devel@haskell.org
15 -- Stability : provisional
16 -- Portability : portable
18 -- High level interface to package installation.
19 module Distribution
.Client
.Install
20 ( -- * High-level interface
23 -- * Lower-level interface that allows to manipulate the install plan
30 -- * Prune certain packages from the install plan
34 import Distribution
.Client
.Compat
.Prelude
35 import Distribution
.Utils
.Generic
(safeLast
)
38 import Control
.Exception
as Exception
44 import qualified Data
.List
.NonEmpty
as NE
45 import qualified Data
.Map
as Map
46 import System
.Directory
47 ( createDirectoryIfMissing
50 , getDirectoryContents
51 , getTemporaryDirectory
55 import System
.FilePath
66 import System
.IO.Error
71 import Distribution
.Client
.BuildReports
.Anonymous
(showBuildReport
)
72 import qualified Distribution
.Client
.BuildReports
.Anonymous
as BuildReports
73 import qualified Distribution
.Client
.BuildReports
.Storage
as BuildReports
79 import Distribution
.Client
.BuildReports
.Types
82 import Distribution
.Client
.Config
86 import Distribution
.Client
.Configure
89 , configureSetupScript
91 import Distribution
.Client
.Dependency
92 import Distribution
.Client
.FetchUtils
93 import qualified Distribution
.Client
.Haddock
as Haddock
(regenerateHaddockIndex
)
94 import Distribution
.Client
.HttpUtils
97 import Distribution
.Client
.IndexUtils
as IndexUtils
98 ( getInstalledPackages
99 , getSourcePackagesAtIndexState
101 import Distribution
.Client
.InstallPlan
(InstallPlan
)
102 import qualified Distribution
.Client
.InstallPlan
as InstallPlan
103 import qualified Distribution
.Client
.InstallSymlink
as InstallSymlink
106 import Distribution
.Client
.JobControl
107 import Distribution
.Client
.Setup
114 , filterConfigureFlags
117 import Distribution
.Client
.SetupWrapper
118 ( SetupScriptOptions
(..)
119 , defaultSetupScriptOptions
122 import Distribution
.Client
.SolverInstallPlan
(SolverInstallPlan
)
123 import qualified Distribution
.Client
.SolverInstallPlan
as SolverInstallPlan
124 import Distribution
.Client
.Tar
(extractTarGzFile
)
125 import Distribution
.Client
.Targets
126 import Distribution
.Client
.Types
as Source
127 import Distribution
.Client
.Types
.OverwritePolicy
(OverwritePolicy
(..))
128 import qualified Distribution
.Client
.Win32SelfUpgrade
as Win32SelfUpgrade
129 import qualified Distribution
.InstalledPackageInfo
as Installed
130 import Distribution
.Solver
.Types
.PackageFixedDeps
132 import qualified Distribution
.Solver
.Types
.ComponentDeps
as CD
133 import Distribution
.Solver
.Types
.ConstraintSource
134 import Distribution
.Solver
.Types
.LabeledPackageConstraint
135 import Distribution
.Solver
.Types
.OptionalStanza
136 import qualified Distribution
.Solver
.Types
.PackageIndex
as SourcePackageIndex
137 import Distribution
.Solver
.Types
.PkgConfigDb
141 import Distribution
.Solver
.Types
.Settings
142 import Distribution
.Solver
.Types
.SourcePackage
as SourcePackage
144 import Distribution
.Client
.Utils
152 import Distribution
.Package
153 ( HasMungedPackageId
(..)
157 , PackageIdentifier
(..)
162 import Distribution
.PackageDescription
163 ( GenericPackageDescription
(..)
166 import qualified Distribution
.PackageDescription
as PackageDescription
167 import Distribution
.PackageDescription
.Configuration
170 import Distribution
.Simple
.BuildPaths
(exeExtension
)
171 import Distribution
.Simple
.Compiler
172 ( Compiler
(compilerId
)
180 import Distribution
.Simple
.Configure
(interpretPackageDbFlags
)
181 import Distribution
.Simple
.Errors
182 import Distribution
.Simple
.InstallDirs
as InstallDirs
185 , initialPathTemplateEnv
186 , installDirsTemplateEnv
190 import qualified Distribution
.Simple
.InstallDirs
as InstallDirs
191 import Distribution
.Simple
.PackageIndex
(InstalledPackageIndex
)
192 import qualified Distribution
.Simple
.PackageIndex
as PackageIndex
193 import Distribution
.Simple
.Program
(ProgramDb
)
194 import Distribution
.Simple
.Register
(defaultRegisterOptions
, registerPackage
)
195 import Distribution
.Simple
.Setup
209 import qualified Distribution
.Simple
.Setup
as Cabal
220 import Distribution
.Simple
.Utils
222 , createDirectoryIfMissingVerbose
225 import Distribution
.Simple
.Utils
as Utils
234 import Distribution
.System
240 import Distribution
.Types
.Flag
248 import Distribution
.Types
.GivenComponent
249 ( GivenComponent
(..)
251 import Distribution
.Types
.MungedPackageId
252 import Distribution
.Types
.PackageVersionConstraint
253 ( PackageVersionConstraint
(..)
254 , thisPackageVersionConstraint
256 import Distribution
.Utils
.NubList
257 import Distribution
.Verbosity
as Verbosity
262 import Distribution
.Version
268 import qualified Data
.ByteString
as BS
269 import Distribution
.Client
.Errors
273 -- * assign flags to packages individually
275 -- * complain about flags that do not apply to any package given as target
276 -- so flags do not apply to dependencies, only listed, can use flag
277 -- constraints for dependencies
279 -- * allow flag constraints
281 -- * allow installed constraints
283 -- * allow flag and installed preferences
285 -- * allow persistent configure flags for each package individually
287 -- ------------------------------------------------------------
289 -- * Top level user actions
291 -- ------------------------------------------------------------
293 -- | Installs the packages needed to satisfy a list of dependencies.
325 unless (installRootCmd installFlags
== Cabal
.NoFlag
) $
327 "--root-cmd is no longer supported, "
328 ++ "see https://github.com/haskell/cabal/issues/3353"
329 ++ " (if you didn't type --root-cmd, comment out root-cmd"
330 ++ " in your ~/.config/cabal/config file)"
331 let userOrSandbox
= fromFlag
(configUserInstall configFlags
)
332 unless userOrSandbox
$
334 "the --global flag is deprecated -- "
335 ++ "it is generally considered a bad idea to install packages "
336 ++ "into the global store"
338 installContext
<- makeInstallContext verbosity args
(Just userTargets0
)
340 foldProgress logMsg
(return . Left
) (return . Right
)
341 =<< makeInstallPlan verbosity args installContext
345 reportPlanningFailure verbosity args installContext message
346 die
'' $ ReportPlanningFailure message
348 processInstallPlan verbosity args installContext installPlan
366 die
'' = dieWithException verbosity
368 logMsg message rest
= debugNoWrap verbosity message
>> rest
370 -- TODO: Make InstallContext a proper data type with documented fields.
372 -- | Common context for makeInstallPlan and processInstallPlan.
373 type InstallContext
=
374 ( InstalledPackageIndex
378 , [PackageSpecifier UnresolvedSourcePackage
]
382 -- TODO: Make InstallArgs a proper data type with documented fields or just get
383 -- rid of it completely.
385 -- | Initial arguments given to 'install' or 'makeInstallContext'.
401 -- | Make an install context given install arguments.
405 -> Maybe [UserTarget
]
423 let idxState
= flagToMaybe
(installIndexState installFlags
)
425 installedPkgIndex
<- getInstalledPackages verbosity comp packageDBs progdb
426 (sourcePkgDb
, _
, _
) <- getSourcePackagesAtIndexState verbosity repoCtxt idxState Nothing
427 pkgConfigDb
<- readPkgConfigDb verbosity progdb
432 (packageIndex sourcePkgDb
)
434 transport
<- repoContextGetTransport repoCtxt
436 (userTargets
, pkgSpecifiers
) <- case mUserTargets
of
438 -- We want to distinguish between the case where the user has given an
439 -- empty list of targets on the command-line and the case where we
440 -- specifically want to have an empty list of targets.
442 Just userTargets0
-> do
443 -- For install, if no target is given it means we use the current
444 -- directory as the single target.
446 |
null userTargets0
= [UserTargetLocalDir
"."]
447 |
otherwise = userTargets0
453 (packageIndex sourcePkgDb
)
455 return (userTargets
, pkgSpecifiers
)
466 -- | Make an install plan given install context and install arguments.
471 -> IO (Progress
String String SolverInstallPlan
)
494 notice verbosity
"Resolving dependencies..."
508 -- | Given an install plan, perform the actual installations.
517 args
@(_
, _
, _
, _
, _
, _
, configFlags
, _
, installFlags
, _
, _
, _
)
534 unless (dryRun || nothingToInstall
) $ do
541 postInstallActions verbosity args userTargets installPlan buildOutcomes
543 installPlan
= InstallPlan
.configureInstallPlan configFlags installPlan0
544 dryRun
= fromFlag
(installDryRun installFlags
)
545 nothingToInstall
= null (fst (InstallPlan
.ready installPlan
))
547 -- ------------------------------------------------------------
549 -- * Installation planning
551 -- ------------------------------------------------------------
560 -> InstalledPackageIndex
563 -> [PackageSpecifier UnresolvedSourcePackage
]
564 -> Progress
String String SolverInstallPlan
581 >>= if onlyDeps
then pruneInstallPlan pkgSpecifiers
else return
585 ( if maxBackjumps
< 0
587 else Just maxBackjumps
589 . setIndependentGoals independentGoals
590 . setReorderGoals reorderGoals
591 . setCountConflicts countConflicts
592 . setFineGrainedConflicts fineGrainedConflicts
593 . setMinimizeConflictSet minimizeConflictSet
594 . setAvoidReinstalls avoidReinstalls
595 . setShadowPkgs shadowPkgs
596 . setStrongFlags strongFlags
597 . setAllowBootLibInstalls allowBootLibInstalls
598 . setOnlyConstrained onlyConstrained
599 . setSolverVerbosity verbosity
600 . setPreferenceDefault
603 else PreferLatestForSelected
605 . removeLowerBounds allowOlder
606 . removeUpperBounds allowNewer
608 -- preferences from the config file or command line
609 [ PackageVersionPreference name ver
610 | PackageVersionConstraint name ver
<- configPreferences configExFlags
613 -- version constraints from the config file or command line
614 [ LabeledPackageConstraint
(userToPackageConstraint pc
) src
615 |
(pc
, src
) <- configExConstraints configExFlags
618 -- FIXME: this just applies all flags to all targets which
619 -- is silly. We should check if the flags are appropriate
622 (scopeToplevel
$ pkgSpecifierTarget pkgSpecifier
)
623 (PackagePropertyFlags flags
)
624 in LabeledPackageConstraint pc ConstraintSourceConfigFlagOrTarget
625 |
let flags
= configConfigurationsFlags configFlags
626 , not (nullFlagAssignment flags
)
627 , pkgSpecifier
<- pkgSpecifiers
632 (scopeToplevel
$ pkgSpecifierTarget pkgSpecifier
)
633 (PackagePropertyStanzas stanzas
)
634 in LabeledPackageConstraint pc ConstraintSourceConfigFlagOrTarget
635 | pkgSpecifier
<- pkgSpecifiers
637 . (if reinstall
then reinstallTargets
else id)
638 -- Don't solve for executables, the legacy install codepath
639 -- doesn't understand how to install them
640 . setSolveExecutables
(SolveExecutables
False)
641 $ standardInstallPolicy
647 [TestStanzas | testsEnabled
]
648 ++ [BenchStanzas | benchmarksEnabled
]
649 testsEnabled
= fromFlagOrDefault
False $ configTests configFlags
650 benchmarksEnabled
= fromFlagOrDefault
False $ configBenchmarks configFlags
653 fromFlag
(installOverrideReinstall installFlags
)
654 || fromFlag
(installReinstall installFlags
)
655 reorderGoals
= fromFlag
(installReorderGoals installFlags
)
656 countConflicts
= fromFlag
(installCountConflicts installFlags
)
657 fineGrainedConflicts
= fromFlag
(installFineGrainedConflicts installFlags
)
658 minimizeConflictSet
= fromFlag
(installMinimizeConflictSet installFlags
)
659 independentGoals
= fromFlag
(installIndependentGoals installFlags
)
660 avoidReinstalls
= fromFlag
(installAvoidReinstalls installFlags
)
661 shadowPkgs
= fromFlag
(installShadowPkgs installFlags
)
662 strongFlags
= fromFlag
(installStrongFlags installFlags
)
663 maxBackjumps
= fromFlag
(installMaxBackjumps installFlags
)
664 allowBootLibInstalls
= fromFlag
(installAllowBootLibInstalls installFlags
)
665 onlyConstrained
= fromFlag
(installOnlyConstrained installFlags
)
666 upgradeDeps
= fromFlag
(installUpgradeDeps installFlags
)
667 onlyDeps
= fromFlag
(installOnlyDeps installFlags
)
672 (configAllowOlder configExFlags
)
676 (configAllowNewer configExFlags
)
678 -- | Remove the provided targets from the install plan.
681 => [PackageSpecifier targetpkg
]
683 -> Progress
String String SolverInstallPlan
684 pruneInstallPlan pkgSpecifiers
=
685 -- TODO: this is a general feature and should be moved to D.C.Dependency
686 -- Also, the InstallPlan.remove should return info more precise to the
687 -- problem, rather than the very general PlanProblem type.
688 either (Fail
. explain
) Done
689 . SolverInstallPlan
.remove
(\pkg
-> packageName pkg `
elem` targetnames
)
691 explain
:: [SolverInstallPlan
.SolverPlanProblem
] -> String
693 "Cannot select only the dependencies (as requested by the "
694 ++ "'--only-dependencies' flag), "
696 [pkgid
] -> "the package " ++ prettyShow pkgid
++ " is "
699 ++ intercalate
", " (map prettyShow pkgids
)
702 ++ "required by a dependency of one of the other targets."
707 | SolverInstallPlan
.PackageMissingDeps _ depids
<- problems
709 , packageName depid `
elem` targetnames
712 targetnames
= map pkgSpecifierTarget pkgSpecifiers
714 -- ------------------------------------------------------------
716 -- * Informational messages
718 -- ------------------------------------------------------------
720 -- | Perform post-solver checks of the install plan and print it if
721 -- either requested or needed.
724 -> InstalledPackageIndex
728 -> [PackageSpecifier UnresolvedSourcePackage
]
737 -- User targets that are already installed.
738 let preExistingTargets
=
739 [ p |
let tgts
= map pkgSpecifierTarget pkgSpecifiers
, InstallPlan
.PreExisting p
<- InstallPlan
.toList installPlan
, packageName p `
elem` tgts
742 -- If there's nothing to install, we print the already existing
743 -- target packages as an explanation.
744 when nothingToInstall
$
747 "All the requested packages are already installed:"
748 : map (prettyShow
. packageId
) preExistingTargets
749 ++ ["Use --reinstall if you want to reinstall anyway."]
753 | pkg
<- InstallPlan
.executionOrder installPlan
754 , let status
= packageStatus installed pkg
756 -- Are any packages classified as reinstalls?
757 let reinstalledPkgs
=
759 |
(_pkg
, status
) <- lPlan
760 , ipkg
<- extractReinstalls status
762 -- Packages that are already broken.
764 map Installed
.installedUnitId
765 . PackageIndex
.reverseDependencyClosure installed
766 . map (Installed
.installedUnitId
. fst)
767 . PackageIndex
.brokenPackages
769 let excluded
= reinstalledPkgs
++ oldBrokenPkgs
770 -- Packages that are reverse dependencies of replaced packages are very
771 -- likely to be broken. We exclude packages that are already broken.
774 (\p
-> not (Installed
.installedUnitId p `
elem` excluded
))
775 (PackageIndex
.reverseDependencyClosure installed reinstalledPkgs
)
776 let containsReinstalls
= not (null reinstalledPkgs
)
777 let breaksPkgs
= not (null newBrokenPkgs
)
781 , not overrideReinstall
=
782 modifyVerbosity
(max verbose
) verbosity
783 |
otherwise = verbosity
785 -- We print the install plan if we are in a dry-run or if we are confronted
786 -- with a dangerous install plan.
787 when (dryRun || containsReinstalls
&& not overrideReinstall
) $
789 (dryRun || breaksPkgs
&& not overrideReinstall
)
794 -- If the install plan is dangerous, we print various warning messages. In
795 -- particular, if we can see that packages are likely to be broken, we even
796 -- bail out (unless installation has been forced with --force-reinstalls).
797 when containsReinstalls
$ do
800 "The following packages are likely to be broken by the reinstalls:"
801 : map (prettyShow
. mungedId
) newBrokenPkgs
802 ++ if overrideReinstall
807 [ "Continuing even though "
808 ++ "the plan contains dangerous reinstalls."
810 else ["Use --force-reinstalls if you want to install anyway."]
813 ( if dryRun || overrideReinstall
814 then warn verbosity errorStr
815 else dieWithException verbosity
$ BrokenException errorStr
821 "Note that reinstalls are always dangerous. Continuing anyway..."
823 -- If we are explicitly told to not download anything, check that all packages
824 -- are already fetched.
825 let offline
= fromFlagOrDefault
False (installOfflineMode installFlags
)
829 | InstallPlan
.Configured cpkg
<- InstallPlan
.toList installPlan
833 . filterM (fmap isNothing . checkFetched
. srcpkgSource
)
835 unless (null notFetched
) $
836 dieWithException verbosity
$
837 Can
'tDownloadPackagesOffline
(map prettyShow notFetched
)
839 nothingToInstall
= null (fst (InstallPlan
.ready installPlan
))
841 dryRun
= fromFlag
(installDryRun installFlags
)
842 overrideReinstall
= fromFlag
(installOverrideReinstall installFlags
)
846 | NewVersion
[Version
]
847 | Reinstall
[UnitId
] [PackageChange
]
849 type PackageChange
= MergeResult MungedPackageId MungedPackageId
851 extractReinstalls
:: PackageStatus
-> [UnitId
]
852 extractReinstalls
(Reinstall ipids _
) = ipids
853 extractReinstalls _
= []
856 :: InstalledPackageIndex
859 packageStatus installedPkgIndex cpkg
=
860 case PackageIndex
.lookupPackageName
862 (packageName cpkg
) of
868 (concatMap snd ps
) of
869 [] -> NewVersion
(map fst ps
)
872 (map Installed
.installedUnitId pkgs
)
876 :: Installed
.InstalledPackageInfo
879 changes pkg
(ReadyPackage pkg
') =
882 (comparing mungedName
)
883 -- deps of installed pkg
884 (resolveInstalledIds
$ Installed
.depends pkg
)
885 -- deps of configured pkg
886 (resolveInstalledIds
$ CD
.nonSetupDeps
(depends pkg
'))
888 -- convert to source pkg ids via index
889 resolveInstalledIds
:: [UnitId
] -> [MungedPackageId
]
890 resolveInstalledIds
=
894 . mapMaybe (PackageIndex
.lookupUnitId installedPkgIndex
)
896 changed
(InBoth pkgid pkgid
') = pkgid
/= pkgid
'
900 :: Bool -- is dry run
902 -> [(ReadyPackage
, PackageStatus
)]
905 printPlan dryRun verbosity plan sourcePkgDb
= case plan
of
908 | verbosity
>= Verbosity
.verbose
->
911 ("In order, the following " ++ wouldWill
++ " be installed:")
912 : map showPkgAndReason pkgs
916 ( "In order, the following "
918 ++ " be installed (use -v for more details):"
927 prettyShow
(packageId pkg
)
930 showPkgAndReason
(ReadyPackage pkg
', pr
) =
932 [ prettyShow
(packageId pkg
')
934 , showFlagAssignment
(nonDefaultFlags pkg
')
935 , showStanzas
(confPkgStanzas pkg
')
938 NewPackage
-> "(new package)"
939 NewVersion _
-> "(new version)"
941 "(reinstall)" ++ case cs
of
945 ++ intercalate
", " (map change diff
)
949 showLatest
:: Package srcpkg
=> srcpkg
-> String
950 showLatest pkg
= case mLatestVersion
of
951 Just latestVersion
->
952 if packageVersion pkg
< latestVersion
953 then ("(latest: " ++ prettyShow latestVersion
++ ")")
957 mLatestVersion
:: Maybe Version
959 fmap packageVersion
$
961 SourcePackageIndex
.lookupPackageName
962 (packageIndex sourcePkgDb
)
965 toFlagAssignment
:: [PackageFlag
] -> FlagAssignment
966 toFlagAssignment
= mkFlagAssignment
. map (\f -> (flagName f
, flagDefault f
))
968 nonDefaultFlags
:: ConfiguredPackage loc
-> FlagAssignment
969 nonDefaultFlags cpkg
=
970 let defaultAssignment
=
973 ( SourcePackage
.srcpkgDescription
$
977 in confPkgFlags cpkg `diffFlagAssignment` defaultAssignment
979 change
(OnlyInLeft pkgid
) = prettyShow pkgid
++ " removed"
980 change
(InBoth pkgid pkgid
') =
983 ++ prettyShow
(mungedVersion pkgid
')
984 change
(OnlyInRight pkgid
') = prettyShow pkgid
' ++ " added"
987 | Just rdeps
<- Map
.lookup (packageId pkg
) revDeps
=
988 " (via: " ++ unwords (map prettyShow rdeps
) ++ ")"
991 revDepGraphEdges
:: [(PackageId
, PackageId
)]
993 [ (rpid
, packageId cpkg
)
994 |
(ReadyPackage cpkg
, _
) <- plan
998 ( PackageDescription
.CLibName
999 PackageDescription
.LMainLibName
1003 CD
.flatDeps
(confPkgDeps cpkg
)
1006 revDeps
:: Map
.Map PackageId
[PackageId
]
1007 revDeps
= Map
.fromListWith
(++) (map (fmap (: [])) revDepGraphEdges
)
1009 -- ------------------------------------------------------------
1011 -- * Post installation stuff
1013 -- ------------------------------------------------------------
1015 -- | Report a solver failure. This works slightly differently to
1016 -- 'postInstallActions', as (by definition) we don't have an install plan.
1017 reportPlanningFailure
1023 reportPlanningFailure
1038 (_
, sourcePkgDb
, _
, _
, pkgSpecifiers
, _
)
1040 when reportFailure
$ do
1041 -- Only create reports for explicitly named packages
1044 (SourcePackageIndex
.elemByPackageId
(packageIndex sourcePkgDb
))
1045 $ mapMaybe theSpecifiedPackage pkgSpecifiers
1048 BuildReports
.fromPlanningFailure
1052 (configConfigurationsFlags configFlags
)
1054 unless (null buildReports
) $
1056 "Solver failure will be reported for "
1057 ++ intercalate
"," (map prettyShow pkgids
)
1060 BuildReports
.storeLocal
1062 (fromNubList
$ installSummaryFile installFlags
)
1068 Nothing
-> return ()
1069 Just template
-> for_ pkgids
$ \pkgid
->
1071 initialPathTemplateEnv
1076 path
= fromPathTemplate
$ substPathTemplate env template
1077 in writeFile path message
1079 reportFailure
= fromFlag
(installReportPlanningFailure installFlags
)
1080 logFile
= flagToMaybe
(installLogFile installFlags
)
1082 -- A IPID is calculated from the transitive closure of
1083 -- dependencies, but when the solver fails we don't have that.
1085 dummyIpid
= error "reportPlanningFailure: installed package ID not available"
1087 -- | If a 'PackageSpecifier' refers to a single package, return Just that
1089 theSpecifiedPackage
:: Package pkg
=> PackageSpecifier pkg
-> Maybe PackageId
1090 theSpecifiedPackage pkgSpec
=
1092 NamedPackage name
[PackagePropertyVersion version
] ->
1093 PackageIdentifier name
<$> trivialRange version
1094 NamedPackage _ _
-> Nothing
1095 SpecificSourcePackage pkg
-> Just
$ packageId pkg
1097 -- \| If a range includes only a single version, return Just that version.
1098 trivialRange
:: VersionRange
-> Maybe Version
1108 -- | Various stuff we do after successful or unsuccessfully installing a bunch
1109 -- of packages. This includes:
1111 -- * build reporting, local and remote
1112 -- * symlinking binaries
1113 -- * updating indexes
1114 -- * error reporting
1141 BuildReports
.fromInstallPlan
1146 BuildReports
.storeLocal
1148 (fromNubList
$ installSummaryFile installFlags
)
1151 when (reportingLevel
>= AnonymousReports
) $
1152 BuildReports
.storeAnonymous buildReports
1153 when (reportingLevel
== DetailedReports
) $
1154 storeDetailedBuildReports verbosity logsDir buildReports
1156 regenerateHaddockIndex
1175 printBuildFailures verbosity buildOutcomes
1177 reportingLevel
= fromFlag
(installBuildReports installFlags
)
1178 logsDir
= fromFlag
(globalLogsDir globalFlags
)
1180 storeDetailedBuildReports
1183 -> [(BuildReports
.BuildReport
, Maybe Repo
)]
1185 storeDetailedBuildReports verbosity logsDir reports
=
1188 allReportsDir
<- defaultReportsDir
1189 let logFileName
= prettyShow
(BuildReports
.package report
) <.> "log"
1190 logFile
= logsDir
</> logFileName
1191 reportsDir
= allReportsDir
</> unRepoName
(remoteRepoName remoteRepo
)
1192 reportFile
= reportsDir
</> logFileName
1194 handleMissingLogFile
$ do
1195 buildLog
<- readFile logFile
1196 createDirectoryIfMissing
True reportsDir
-- FIXME
1197 writeFile reportFile
(show (showBuildReport report
, buildLog
))
1198 |
(report
, Just repo
) <- reports
1199 , Just remoteRepo
<- [maybeRepoRemote repo
]
1200 , isLikelyToHaveLogFile
(BuildReports
.installOutcome report
)
1203 isLikelyToHaveLogFile BuildReports
.ConfigureFailed
{} = True
1204 isLikelyToHaveLogFile BuildReports
.BuildFailed
{} = True
1205 isLikelyToHaveLogFile BuildReports
.InstallFailed
{} = True
1206 isLikelyToHaveLogFile BuildReports
.InstallOk
{} = True
1207 isLikelyToHaveLogFile _
= False
1209 handleMissingLogFile
= Exception
.handleJust missingFile
$ \ioe
->
1211 "Missing log file for build report: "
1212 ++ fromMaybe "" (ioeGetFileName ioe
)
1215 |
isDoesNotExistError ioe
= Just ioe
1216 missingFile _
= Nothing
1218 regenerateHaddockIndex
1228 regenerateHaddockIndex
1237 | haddockIndexFileIsRequested
&& shouldRegenerateHaddockIndex
= do
1239 InstallDirs
.defaultInstallDirs
1240 (compilerFlavor comp
)
1241 (fromFlag
(configUserInstall configFlags
))
1243 let indexFileTemplate
= fromFlag
(installHaddockIndex installFlags
)
1244 indexFile
= substHaddockIndexFileName defaultDirs indexFileTemplate
1247 "Updating documentation index " ++ indexFile
1249 -- TODO: might be nice if the install plan gave us the new InstalledPackageInfo
1250 installedPkgIndex
<- getInstalledPackages verbosity comp packageDBs progdb
1251 Haddock
.regenerateHaddockIndex verbosity installedPkgIndex progdb indexFile
1252 |
otherwise = return ()
1254 haddockIndexFileIsRequested
=
1255 fromFlag
(installDocumentation installFlags
)
1256 && isJust (flagToMaybe
(installHaddockIndex installFlags
))
1258 -- We want to regenerate the index if some new documentation was actually
1259 -- installed. Since the index can be only per-user or per-sandbox (see
1260 -- #1337), we don't do it for global installs or special cases where we're
1261 -- installing into a specific db.
1262 shouldRegenerateHaddockIndex
= normalUserInstall
&& someDocsWereInstalled buildOutcomes
1264 someDocsWereInstalled
= any installedDocs
. Map
.elems
1265 installedDocs
(Right
(BuildResult DocsOk _ _
)) = True
1266 installedDocs _
= False
1269 (UserPackageDB `
elem` packageDBs
)
1270 && all (not . isSpecificPackageDB
) packageDBs
1271 isSpecificPackageDB
(SpecificPackageDB _
) = True
1272 isSpecificPackageDB _
= False
1274 substHaddockIndexFileName defaultDirs
=
1276 . substPathTemplate env
1278 env
= env0
++ installDirsTemplateEnv absoluteDirs
1280 InstallDirs
.compilerTemplateEnv
(compilerInfo comp
)
1281 ++ InstallDirs
.platformTemplateEnv platform
1282 ++ InstallDirs
.abiTemplateEnv
(compilerInfo comp
) platform
1284 InstallDirs
.substituteInstallDirTemplates
1288 InstallDirs
.combineInstallDirs
1291 (configInstallDirs configFlags
)
1311 InstallSymlink
.symlinkBinaries
1323 "could not create a symlink in "
1327 ++ " because the file exists there already but is not "
1328 ++ "managed by cabal. You can create a symlink for this executable "
1329 ++ "manually if you wish. The executable file has been installed at "
1333 "could not create symlinks in "
1336 ++ intercalate
", " [prettyShow exe |
(_
, exe
, _
) <- exes
]
1337 ++ " because the files exist there already and are not "
1338 ++ "managed by cabal. You can create symlinks for these executables "
1339 ++ "manually if you wish. The executable files have been installed at "
1340 ++ intercalate
", " [path |
(_
, _
, path
) <- exes
]
1342 bindir
= fromFlag
(installSymlinkBinDir installFlags
)
1344 printBuildFailures
:: Verbosity
-> BuildOutcomes
-> IO ()
1345 printBuildFailures verbosity buildOutcomes
=
1346 case [ (pkgid
, failure
)
1347 |
(pkgid
, Left failure
) <- Map
.toList buildOutcomes
1351 dieWithException verbosity
$
1352 SomePackagesFailedToInstall
$
1353 map (\(pkgid
, reason
) -> (prettyShow pkgid
, printFailureReason reason
)) failed
1355 printFailureReason reason
= case reason
of
1356 GracefulFailure msg
-> msg
1357 DependentFailed pkgid
->
1360 ++ " which failed to install."
1362 " failed while downloading the package."
1365 " failed while unpacking the package."
1367 ConfigureFailed e
->
1368 " failed during the configure step."
1371 " failed during the building phase."
1374 " failed during the tests phase."
1377 " failed during the final install step."
1379 -- This will never happen, but we include it for completeness
1380 PlanningFailed
-> " failed during the planning phase."
1382 showException e
= " The exception was:\n " ++ show e
++ maybeOOM e
1383 #ifdef mingw32_HOST_OS
1386 maybeOOM e
= maybe "" onExitFailure
(fromException e
)
1387 onExitFailure
(ExitFailure n
)
1388 | n
== 9 || n
== -9 =
1389 "\nThis may be due to an out-of-memory condition."
1390 onExitFailure _
= ""
1393 -- ------------------------------------------------------------
1395 -- * Actually do the installations
1397 -- ------------------------------------------------------------
1399 data InstallMisc
= InstallMisc
1400 { libVersion
:: Maybe Version
1403 -- | If logging is enabled, contains location of the log file and the verbosity
1404 -- level for logging.
1405 type UseLogFile
= Maybe (PackageIdentifier
-> UnitId
-> FilePath, Verbosity
)
1407 performInstallations
1410 -> InstalledPackageIndex
1413 performInstallations
1430 info verbosity
$ "Number of threads used: " ++ (show numJobs
) ++ "."
1434 then newParallelJobControl numJobs
1435 else newSerialJobControl
1436 fetchLimit
<- newJobLimit
(min numJobs numFetchJobs
)
1437 installLock
<- newLock
-- serialise installation
1438 cacheLock
<- newLock
-- serialise access to setup exe cache
1451 $ \configFlags
' src pkg pkgoverride
->
1452 fetchSourcePackage verbosity repoCtxt fetchLimit src
$ \src
' ->
1453 installLocalPackage verbosity
(packageId pkg
) src
' distPref
$ \mpath
->
1454 installUnpackedPackage
1458 ( setupScriptOptions
1476 cinfo
= compilerInfo comp
1478 numJobs
= determineNumJobs
(installNumJobs installFlags
)
1480 parallelInstall
= numJobs
>= 2
1481 keepGoing
= fromFlag
(installKeepGoing installFlags
)
1484 (useDistPref defaultSetupScriptOptions
)
1485 (configDistPref configFlags
)
1487 setupScriptOptions
index lock rpkg
=
1488 configureSetupScript
1494 (chooseCabalVersion configExFlags
(libVersion miscOptions
))
1500 reportingLevel
= fromFlag
(installBuildReports installFlags
)
1501 logsDir
= fromFlag
(globalLogsDir globalFlags
)
1503 -- Should the build output be written to a log file instead of stdout?
1504 useLogFile
:: UseLogFile
1507 ((\f -> (f
, loggingVerbosity
)) . substLogFileName
)
1510 installLogFile
' = flagToMaybe
$ installLogFile installFlags
1513 logsDir
</> "$compiler" </> "$libname" <.> "log"
1515 -- If the user has specified --remote-build-reporting=detailed, use the
1516 -- default log file location. If the --build-log option is set, use the
1517 -- provided location. Otherwise don't use logging, unless building in
1518 -- parallel (in which case the default location is used).
1519 logFileTemplate
:: Maybe PathTemplate
1521 | useDefaultTemplate
= Just defaultTemplate
1522 |
otherwise = installLogFile
'
1524 -- If the user has specified --remote-build-reporting=detailed or
1525 -- --build-log, use more verbose logging.
1526 loggingVerbosity
:: Verbosity
1528 | overrideVerbosity
= modifyVerbosity
(max verbose
) verbosity
1529 |
otherwise = verbosity
1531 useDefaultTemplate
:: Bool
1533 | reportingLevel
== DetailedReports
= True
1534 |
isJust installLogFile
' = False
1535 | parallelInstall
= True
1538 overrideVerbosity
:: Bool
1540 | reportingLevel
== DetailedReports
= True
1541 |
isJust installLogFile
' = True
1542 | parallelInstall
= False
1545 substLogFileName
:: PathTemplate
-> PackageIdentifier
-> UnitId
-> FilePath
1546 substLogFileName template pkg uid
=
1548 . substPathTemplate env
1552 initialPathTemplateEnv
1560 { libVersion
= flagToMaybe
(configCabalVersion configExFlags
)
1565 -> JobControl
IO (UnitId
, BuildOutcome
)
1569 -> (ReadyPackage
-> IO BuildOutcome
)
1571 executeInstallPlan verbosity jobCtl keepGoing useLogFile plan0 installPkg
=
1578 buildOutcome
<- installPkg pkg
1579 printBuildResult
(packageId pkg
) (installedUnitId pkg
) buildOutcome
1582 depsFailure
= DependentFailed
. packageId
1584 -- Print build log if something went wrong, and 'Installed $PKGID'
1586 printBuildResult
:: PackageId
-> UnitId
-> BuildOutcome
-> IO ()
1587 printBuildResult pkgid uid buildOutcome
= case buildOutcome
of
1588 (Right _
) -> progressMessage verbosity ProgressCompleted
(prettyShow pkgid
)
1590 notice verbosity
$ "Failed to install " ++ prettyShow pkgid
1591 when (verbosity
>= normal
) $
1593 Nothing
-> return ()
1594 Just
(mkLogFileName
, _
) -> do
1595 let logName
= mkLogFileName pkgid uid
1596 putStr $ "Build log ( " ++ logName
++ " ):\n"
1599 printFile
:: FilePath -> IO ()
1600 printFile path
= readFile path
>>= putStr
1602 -- | Call an installer for an 'SourcePackage' but override the configure
1603 -- flags with the ones given by the 'ReadyPackage'. In particular the
1604 -- 'ReadyPackage' specifies an exact 'FlagAssignment' and exactly
1605 -- versioned package dependencies. So we ignore any previous partial flag
1606 -- assignment or dependency constraints and use the new ones.
1608 -- NB: when updating this function, don't forget to also update
1609 -- 'configurePackage' in D.C.Configure.
1617 -> PackageDescription
1618 -> PackageDescriptionOverride
1629 (SourcePackage _ gpkg source pkgoverride
)
1638 { configIPID
= toFlag
(prettyShow ipid
)
1639 , configConfigurationsFlags
= flags
1640 , -- We generate the legacy constraints as well as the new style precise deps.
1641 -- In the end only one set gets passed to Setup.hs configure, depending on
1642 -- the Cabal version we are talking to.
1644 [ thisPackageVersionConstraint srcid
1648 ( PackageDescription
.CLibName
1649 PackageDescription
.LMainLibName
1653 CD
.nonSetupDeps deps
1655 , configDependencies
=
1656 [ GivenComponent
(packageName srcid
) cname dep_ipid
1657 | ConfiguredId srcid
(Just
(PackageDescription
.CLibName cname
)) dep_ipid
<-
1658 CD
.nonSetupDeps deps
1660 , -- Use '--exact-configuration' if supported.
1661 configExactConfiguration
= toFlag
True
1662 , configBenchmarks
= toFlag
False
1663 , configTests
= toFlag
(TestStanzas `optStanzaSetMember` stanzas
)
1669 pkg
= case finalizePD
1671 (enableStanzas stanzas
)
1677 Left _
-> error "finalizePD ReadyPackage failed"
1678 Right
(desc
, _
) -> desc
1685 -> (ResolvedPkgLoc
-> IO BuildOutcome
)
1687 fetchSourcePackage verbosity repoCtxt fetchLimit src installPkg
= do
1688 fetched
<- checkFetched src
1690 Just src
' -> installPkg src
'
1691 Nothing
-> onFailure DownloadFailed
$ do
1693 withJobLimit fetchLimit
$
1694 fetchPackage verbosity repoCtxt src
1699 -> PackageIdentifier
1702 -> (Maybe FilePath -> IO BuildOutcome
)
1704 installLocalPackage verbosity pkgid location distPref installPkg
=
1706 LocalUnpackedPackage dir
->
1707 installPkg
(Just dir
)
1708 RemoteSourceRepoPackage _repo dir
->
1709 installPkg
(Just dir
)
1710 LocalTarballPackage tarballPath
->
1711 installLocalTarballPackage
1717 RemoteTarballPackage _ tarballPath
->
1718 installLocalTarballPackage
1724 RepoTarballPackage _ _ tarballPath
->
1725 installLocalTarballPackage
1732 installLocalTarballPackage
1734 -> PackageIdentifier
1737 -> (Maybe FilePath -> IO BuildOutcome
)
1739 installLocalTarballPackage
1745 tmp
<- getTemporaryDirectory
1746 withTempDirectory verbosity tmp
"cabal-tmp" $ \tmpDirPath
->
1747 onFailure UnpackFailed
$ do
1748 let relUnpackedPath
= prettyShow pkgid
1749 absUnpackedPath
= tmpDirPath
</> relUnpackedPath
1752 </> prettyShow
(packageName pkgid
)
1760 extractTarGzFile tmpDirPath relUnpackedPath tarballPath
1761 exists
<- doesFileExist descFilePath
1763 dieWithException verbosity
$
1764 PackageDotCabalFileNotFound descFilePath
1765 maybeRenameDistDir absUnpackedPath
1766 installPkg
(Just absUnpackedPath
)
1768 -- 'cabal sdist' puts pre-generated files in the 'dist'
1769 -- directory. This fails when a nonstandard build directory name
1770 -- is used (as is the case with sandboxes), so we need to rename
1771 -- the 'dist' dir here.
1773 -- TODO: 'cabal get happy && cd sandbox && cabal install ../happy' still
1774 -- fails even with this workaround. We probably can live with that.
1775 maybeRenameDistDir
:: FilePath -> IO ()
1776 maybeRenameDistDir absUnpackedPath
= do
1777 let distDirPath
= absUnpackedPath
</> defaultDistPref
1778 distDirPathTmp
= absUnpackedPath
</> (defaultDistPref
++ "-tmp")
1779 distDirPathNew
= absUnpackedPath
</> distPref
1780 distDirExists
<- doesDirectoryExist distDirPath
1783 && not (distDirPath `equalFilePath` distDirPathNew
)
1786 -- NB: we need to handle the case when 'distDirPathNew' is a
1787 -- subdirectory of 'distDirPath' (e.g. the former is
1788 -- 'dist/dist-sandbox-3688fbc2' and the latter is 'dist').
1795 renameDirectory distDirPath distDirPathTmp
1796 when (distDirPath `
isPrefixOf` distDirPathNew
) $
1797 createDirectoryIfMissingVerbose verbosity
False distDirPath
1804 renameDirectory distDirPathTmp distDirPathNew
1806 installUnpackedPackage
1810 -> SetupScriptOptions
1818 -> PackageDescription
1820 -> PackageDescriptionOverride
1822 -- ^ Directory to change to before starting the installation.
1824 -- ^ File to log output to (if any)
1826 installUnpackedPackage
1843 -- Override the .cabal file if necessary
1845 Nothing
-> return ()
1848 fromMaybe "." workingDir
1849 </> prettyShow
(packageName pkgid
)
1853 ++ prettyShow
(packageName pkgid
) <.> "cabal"
1854 ++ " with the latest revision from the index."
1855 writeFileAtomic descFilePath pkgtxt
1857 -- Make sure that we pass --libsubdir etc to 'setup configure' (necessary if
1858 -- the setup script was compiled against an old version of the Cabal lib).
1859 configFlags
' <- addDefaultInstallDirs configFlags
1860 -- Filter out flags not supported by the old versions of the Cabal lib.
1861 let configureFlags
:: Version
-> ConfigFlags
1863 filterConfigureFlags
1865 { configVerbosity
= toFlag verbosity
'
1868 -- Path to the optional log file.
1869 mLogPath
<- maybeLogPath
1871 logDirChange
(maybe (const (return ())) appendFile mLogPath
) workingDir
$ do
1873 onFailure ConfigureFailed
$ do
1874 noticeProgress ProgressStarting
1875 setup configureCommand configureFlags mLogPath
1878 onFailure BuildFailed
$ do
1879 noticeProgress ProgressBuilding
1880 setup buildCommand
' buildFlags mLogPath
1882 -- Doc generation phase
1887 setup haddockCommand haddockFlags
' mLogPath
1890 `catchIO`
(\_
-> return DocsFailed
)
1891 `catchExit`
(\_
-> return DocsFailed
)
1892 else return DocsNotTried
1895 onFailure TestsFailed
$ do
1896 when (testsEnabled
&& PackageDescription
.hasTests pkg
) $
1897 setup Cabal
.testCommand testFlags
' mLogPath
1900 | testsEnabled
= TestsOk
1901 |
otherwise = TestsNotTried
1904 onFailure InstallFailed
$ criticalSection installLock
$ do
1905 -- Actual installation
1906 withWin32SelfUpgrade
1914 setup Cabal
.copyCommand copyFlags mLogPath
1916 -- Capture installed package configuration file, so that
1917 -- it can be incorporated into the final InstallPlan
1918 ipkgs
<- genPkgConfs mLogPath
1919 let ipkgs
' = case ipkgs
of
1920 [ipkg
] -> [ipkg
{Installed
.installedUnitId
= uid
}]
1923 interpretPackageDbFlags
1924 (fromFlag
(configUserInstall configFlags
))
1925 (configPackageDBs configFlags
)
1926 for_ ipkgs
' $ \ipkg
' ->
1933 defaultRegisterOptions
1935 return (Right
(BuildResult docsResult testsResult
(find ((== uid
) . installedUnitId
) ipkgs
')))
1937 pkgid
= packageId pkg
1938 uid
= installedUnitId rpkg
1939 cinfo
= compilerInfo comp
1940 buildCommand
' = buildCommand progdb
1941 dispname
= prettyShow pkgid
1942 isParallelBuild
= numJobs
>= 2
1944 noticeProgress
phase =
1945 when isParallelBuild
$
1946 progressMessage verbosity
phase dispname
1950 { buildDistPref
= configDistPref configFlags
1951 , buildVerbosity
= toFlag verbosity
'
1953 shouldHaddock
= fromFlag
(installDocumentation installFlags
)
1956 { haddockVerbosity
= toFlag verbosity
'
1957 , haddockDistPref
= configDistPref configFlags
1960 fromFlag
(configTests configFlags
)
1961 && fromFlagOrDefault
False (installRunTests installFlags
)
1965 { Cabal
.testDistPref
= configDistPref configFlags
1968 Cabal
.emptyCopyFlags
1969 { Cabal
.copyDistPref
= configDistPref configFlags
1970 , Cabal
.copyDest
= toFlag InstallDirs
.NoCopyDest
1971 , Cabal
.copyVerbosity
= toFlag verbosity
'
1973 shouldRegister
= PackageDescription
.hasLibs pkg
1975 Cabal
.emptyRegisterFlags
1976 { Cabal
.regDistPref
= configDistPref configFlags
1977 , Cabal
.regVerbosity
= toFlag verbosity
'
1979 verbosity
' = maybe verbosity
snd useLogFile
1980 tempTemplate name
= name
++ "-" ++ prettyShow pkgid
1982 addDefaultInstallDirs
:: ConfigFlags
-> IO ConfigFlags
1983 addDefaultInstallDirs configFlags
' = do
1984 defInstallDirs
<- InstallDirs
.defaultInstallDirs flavor userInstall
False
1987 { configInstallDirs
=
1989 . InstallDirs
.substituteInstallDirTemplates env
1990 $ InstallDirs
.combineInstallDirs
1993 (configInstallDirs configFlags
)
1996 CompilerId flavor _
= compilerInfoId cinfo
1997 env
= initialPathTemplateEnv pkgid uid cinfo platform
2001 (configUserInstall configFlags
')
2005 -> IO [Installed
.InstalledPackageInfo
]
2006 genPkgConfs mLogPath
=
2009 tmp
<- getTemporaryDirectory
2010 withTempDirectory verbosity tmp
(tempTemplate
"pkgConf") $ \dir
-> do
2011 let pkgConfDest
= dir
</> "pkgConf"
2012 registerFlags
' version
=
2013 (registerFlags version
)
2014 { Cabal
.regGenPkgConf
= toFlag
(Just pkgConfDest
)
2016 setup Cabal
.registerCommand registerFlags
' mLogPath
2017 is_dir
<- doesDirectoryExist pkgConfDest
2018 let notHidden
= not . isHidden
2019 isHidden name
= "." `
isPrefixOf` name
2021 then -- Sort so that each prefix of the package
2022 -- configurations is well formed
2024 traverse
(readPkgConf pkgConfDest
) . sort . filter notHidden
2025 =<< getDirectoryContents pkgConfDest
2026 else fmap (: []) $ readPkgConf
"." pkgConfDest
2032 -> IO Installed
.InstalledPackageInfo
2033 readPkgConf pkgConfDir pkgConfFile
= do
2034 pkgConfText
<- BS
.readFile (pkgConfDir
</> pkgConfFile
)
2035 case Installed
.parseInstalledPackageInfo pkgConfText
of
2036 Left perrors
-> pkgConfParseFailed
$ unlines $ NE
.toList perrors
2037 Right
(warns
, pkgConf
) -> do
2038 unless (null warns
) $
2043 pkgConfParseFailed
:: String -> IO a
2044 pkgConfParseFailed perror
=
2045 dieWithException verbosity
$ PkgConfParsedFailed perror
2047 maybeLogPath
:: IO (Maybe FilePath)
2050 Nothing
-> return Nothing
2051 Just
(mkLogFileName
, _
) -> do
2052 let logFileName
= mkLogFileName
(packageId pkg
) uid
2053 logDir
= takeDirectory logFileName
2054 unless (null logDir
) $ createDirectoryIfMissing
True logDir
2055 logFileExists
<- doesFileExist logFileName
2056 when logFileExists
$ removeFile logFileName
2057 return (Just logFileName
)
2059 setup cmd flags mLogPath
=
2061 (traverse
(\path
-> openFile path AppendMode
) mLogPath
)
2067 { useLoggingHandle
= logFileHandle
2068 , useWorkingDir
= workingDir
2077 onFailure
:: (SomeException
-> BuildFailure
) -> IO BuildOutcome
-> IO BuildOutcome
2078 onFailure result action
=
2080 `catches`
[ Handler
$ \ioe
-> handler
(ioe
:: IOException
)
2081 , Handler
$ \cabalexe
-> handler
(cabalexe
:: VerboseException CabalException
)
2082 , Handler
$ \exit
-> handler
(exit
:: ExitCode)
2085 handler
:: Exception e
=> e
-> IO BuildOutcome
2086 handler
= return . Left
. result
. toException
2088 -- ------------------------------------------------------------
2090 -- * Weird windows hacks
2092 -- ------------------------------------------------------------
2094 withWin32SelfUpgrade
2100 -> PackageDescription
2103 withWin32SelfUpgrade _ _ _ _ _ _ action | buildOS
/= Windows
= action
2104 withWin32SelfUpgrade verbosity uid configFlags cinfo platform pkg action
= do
2106 InstallDirs
.defaultInstallDirs
2108 (fromFlag
(configUserInstall configFlags
))
2109 (PackageDescription
.hasLibs pkg
)
2111 Win32SelfUpgrade
.possibleSelfUpgrade
2113 (exeInstallPaths defaultDirs
)
2116 pkgid
= packageId pkg
2117 (CompilerId compFlavor _
) = compilerInfoId cinfo
2119 exeInstallPaths defaultDirs
=
2120 [ InstallDirs
.bindir absoluteDirs
</> exeName
<.> exeExtension buildPlatform
2121 | exe
<- PackageDescription
.executables pkg
2122 , PackageDescription
.buildable
(PackageDescription
.buildInfo exe
)
2123 , let exeName
= prefix
++ prettyShow
(PackageDescription
.exeName exe
) ++ suffix
2124 prefix
= substTemplate prefixTemplate
2125 suffix
= substTemplate suffixTemplate
2128 fromFlagTemplate
= fromFlagOrDefault
(InstallDirs
.toPathTemplate
"")
2129 prefixTemplate
= fromFlagTemplate
(configProgPrefix configFlags
)
2130 suffixTemplate
= fromFlagTemplate
(configProgSuffix configFlags
)
2132 InstallDirs
.combineInstallDirs
2135 (configInstallDirs configFlags
)
2137 InstallDirs
.absoluteInstallDirs
2141 InstallDirs
.NoCopyDest
2145 InstallDirs
.fromPathTemplate
2146 . InstallDirs
.substPathTemplate env
2149 InstallDirs
.initialPathTemplateEnv