Skip to content

Commit 83ef876

Browse files
committed
Configure the compiler ProgramDb once per project
1 parent 9c13a3e commit 83ef876

5 files changed

Lines changed: 88 additions & 30 deletions

File tree

Cabal/src/Distribution/Simple/Program/Db.hs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ module Distribution.Simple.Program.Db
3333
-- ** Query and manipulate the program db
3434
, addKnownProgram
3535
, addKnownPrograms
36+
, clearUnconfiguredPrograms
3637
, prependProgramSearchPath
3738
, prependProgramSearchPathNoLogging
3839
, lookupKnownProgram
@@ -201,6 +202,14 @@ addKnownProgram prog =
201202
addKnownPrograms :: [Program] -> ProgramDb -> ProgramDb
202203
addKnownPrograms progs progdb = foldl' (flip addKnownProgram) progdb progs
203204

205+
-- | Drop all unconfigured programs from a 'ProgramDb', retaining only
206+
-- configured programs, the search path, and environment overrides.
207+
--
208+
-- This mirrors round-tripping via the @'Binary' 'ProgramDb'@ instance, which
209+
-- drops unconfigured programs.
210+
clearUnconfiguredPrograms :: ProgramDb -> ProgramDb
211+
clearUnconfiguredPrograms progdb = progdb{unconfiguredProgs = Map.empty}
212+
204213
lookupKnownProgram :: String -> ProgramDb -> Maybe Program
205214
lookupKnownProgram name =
206215
fmap (\(p, _, _) -> p) . Map.lookup name . unconfiguredProgs

cabal-install/src/Distribution/Client/ProjectPlanning.hs

Lines changed: 15 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -564,11 +564,14 @@ configureCompiler
564564
monitorFiles (programsMonitorFiles progdb')
565565
return result
566566

567-
-- Now, **outside** of the caching logic of 'rerunIfChanged', add on
568-
-- auxiliary unconfigured programs to the ProgramDb (e.g. hc-pkg, haddock, ar, ld...).
567+
-- Now, **outside** of the caching logic of 'rerunIfChanged':
568+
--
569+
-- 1. Call 'clearUnconfiguredPrograms' to ensure the first run (in-memory)
570+
-- situation and the "deserialise from cache" get the same input.
571+
-- 2. Add on auxiliary unconfigured programs to the ProgramDb (e.g. hc-pkg, haddock, ar, ld...).
569572
--
570573
-- See Note [Caching the result of configuring the compiler]
571-
finalProgDb <- liftIO $ Cabal.configCompilerProgDb verbosity hc hcProgDb hcPkg
574+
finalProgDb <- liftIO $ Cabal.configCompilerProgDb verbosity hc (clearUnconfiguredPrograms hcProgDb) hcPkg
572575
return (hc, plat, finalProgDb)
573576
where
574577
hcFlavor = flagToMaybe projectConfigHcFlavor
@@ -597,6 +600,9 @@ To solve this, we cache the ProgramDb containing the compiler (which will be
597600
a configured program, hence properly serialised/deserialised), and then
598601
re-compute any attendant unconfigured programs (such as hc-pkg, haddock or build
599602
tools such as ar, ld) using 'configCompilerProgDb'.
603+
We also call 'clearUnconfiguredPrograms' on the ProgramDb returned by
604+
'rerunIfChanged', so that the first-run (in-memory) result behaves the same as
605+
the cache hit result: always drop unconfigured programs.
600606
601607
Another idea would be to simply eagerly configure all unconfigured programs,
602608
as was originally attempted. But this doesn't work, for a couple of reasons:
@@ -891,7 +897,7 @@ rebuildInstallPlan
891897
, projectConfigSpecificPackage
892898
, projectConfigBuildOnly
893899
}
894-
(compiler, platform, progdb)
900+
(compiler, platform, compilerprogdb)
895901
pkgConfigDB
896902
solverPlan
897903
localPackages = do
@@ -906,13 +912,16 @@ rebuildInstallPlan
906912

907913
defaultInstallDirs <- liftIO $ userInstallDirTemplates compiler
908914
let installDirs = fmap Cabal.fromFlag $ (fmap Flag defaultInstallDirs) <> (projectConfigInstallDirs projectConfigShared)
915+
-- Configure the compiler ProgramDb now (once for the entire project),
916+
-- to avoid repeatedly doing this once per package.
917+
cfgedcompilerprogdb <- liftIO $ configureAllKnownPrograms verbosity compilerprogdb
909918
(elaboratedPlan, elaboratedShared) <-
910919
liftIO . runLogProgress verbosity $
911920
elaborateInstallPlan
912921
verbosity
913922
platform
914923
compiler
915-
progdb
924+
cfgedcompilerprogdb
916925
pkgConfigDB
917926
distDirLayout
918927
cabalStoreDirLayout
@@ -1631,6 +1640,7 @@ elaborateInstallPlan
16311640
-> Platform
16321641
-> Compiler
16331642
-> ProgramDb
1643+
-- ^ **Configured** compiler program database (ghc, ghc-pkg, haddock, ld, etc)
16341644
-> Maybe PkgConfigDb
16351645
-> DistDirLayout
16361646
-> StoreDirLayout

cabal-install/src/Distribution/Client/ProjectPlanning/Types.hs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -188,9 +188,10 @@ data ElaboratedSharedConfig = ElaboratedSharedConfig
188188
{ pkgConfigPlatform :: Platform
189189
, pkgConfigCompiler :: Compiler -- TODO: [code cleanup] replace with CompilerInfo
190190
, pkgConfigCompilerProgs :: ProgramDb
191-
-- ^ The programs that the compiler configured (e.g. for GHC, the progs
192-
-- ghc & ghc-pkg). Once constructed, only the 'configuredPrograms' are
193-
-- used.
191+
-- ^ All known programs configured once for the project: the compiler
192+
-- (e.g. ghc & ghc-pkg) plus associated tools (hsc2hs, haddock, hpc,
193+
-- runghc) and toolchain programs (ar, ld, strip). Once constructed,
194+
-- only the 'configuredPrograms' are used.
194195
, pkgConfigReplOptions :: ReplOptions
195196
}
196197
deriving (Show, Generic)

cabal-install/src/Distribution/Client/SetupWrapper.hs

Lines changed: 43 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -612,8 +612,8 @@ setupWrapper
612612
-> IO (SetupRunnerRes setupSpec)
613613
setupWrapper verbosity options mpkg cmd getCommonFlags getFlags getExtraArgs wrapperArgs = do
614614
let allowInLibrary = case wrapperArgs of
615-
NotInLibrary -> Don'tAllowInLibrary
616615
InLibraryArgs {} -> AllowInLibrary
616+
NotInLibrary -> Don'tAllowInLibrary
617617
ASetup (setup :: Setup kind) <- getSetup verbosity options mpkg allowInLibrary
618618
let version = setupVersion setup
619619
flags <- getFlags version
@@ -643,21 +643,31 @@ setupWrapper verbosity options mpkg cmd getCommonFlags getFlags getExtraArgs wra
643643
InLibraryArgs libArgs ->
644644
case libArgs of
645645
InLibraryConfigureArgs elabSharedConfig elabReadyPkg -> do
646-
-- See (1)(a) in Note [Constructing the ProgramDb]
646+
-- Start from the pre-configured compiler ProgramDb, augmented
647+
-- with all builtin programs (restored as unconfigured).
648+
-- This ensures:
649+
-- (a) configureAllKnownPrograms inside configureFinal skips
650+
-- compiler programs (already configured at project level),
651+
-- (b) builtin preprocessors like alex and happy are present as
652+
-- unconfigured programs, so configureFinal's
653+
-- configureAllKnownPrograms can find them using the
654+
-- per-package search path (respecting extra-prog-path).
655+
-- See (1) in Note [Constructing the ProgramDb].
656+
657+
-- Apply per-package user-supplied program args/paths.
658+
-- See (2)(a) in Note [Constructing the ProgramDb]
647659
baseProgDb <-
648-
prependProgramSearchPath verbosity
649-
(useExtraPathEnv options)
650-
(useExtraEnvOverrides options) =<<
651-
mkProgramDb verbHandles flags -- Passes user-supplied arguments to e.g. GHC
652-
(restoreProgramDb builtinPrograms $
653-
useProgramDb options) -- Recall that 'useProgramDb' is set to 'pkgConfigCompilerProgs'
654-
-- See (2) in Note [Constructing the ProgramDb]
660+
mkProgramDb verbHandles flags
661+
(restoreProgramDb builtinPrograms $
662+
pkgConfigCompilerProgs elabSharedConfig)
655663
setupProgDb <-
656-
configCompilerProgDb
657-
verbosity
658-
(pkgConfigCompiler elabSharedConfig)
659-
baseProgDb
660-
Nothing -- we use configProgramPaths instead
664+
if null (useExtraPathEnv options)
665+
then return baseProgDb
666+
else
667+
prependProgramSearchPath verbosity
668+
(useExtraPathEnv options)
669+
(useExtraEnvOverrides options)
670+
baseProgDb
661671
lbi0 <-
662672
InLibrary.configure
663673
(InLibrary.libraryConfigureInputsFromElabPackage
@@ -670,7 +680,7 @@ setupWrapper verbosity options mpkg cmd getCommonFlags getFlags getExtraArgs wra
670680
)
671681
flags
672682
let progs0 = LBI.withPrograms lbi0
673-
-- See (1)(b) in Note [Constructing the ProgramDb]
683+
-- See (2)(b) in Note [Constructing the ProgramDb]
674684
progs1 <- updatePathProgDb verbosity progs0
675685
let
676686
lbi =
@@ -715,7 +725,24 @@ includes the call to 'configCompilerEx'.
715725
To obtain a program database with all the required information, we do a few
716726
things:
717727
718-
(1)
728+
(1) We retrieve the pre-configured compiler program database (typically
729+
containing ghc, ghc-pkg, haddock, and toolchain programs such as ar, ld),
730+
and restore all builtin programs (alex, happy, hsc2hs, ...) as unconfigured
731+
entries on top of it.
732+
733+
This serves two purposes:
734+
735+
(a) The compiler programs (ghc, ghc-pkg, haddock, hsc2hs, ...) that were
736+
already configured at the project level appear in 'configuredProgs'.
737+
The 'configureAllKnownPrograms' call inside the Cabal per-package
738+
'configureFinal' skips them, saving redundant work.
739+
740+
(b) Builtin preprocessors (e.g. alex, happy) are NOT configured at the
741+
project level; restoring them here means the call to
742+
'configureAllKnownPrograms' in 'configureFinal' can find them using
743+
the per-package search path (including 'extra-prog-path').
744+
745+
(2)
719746
(a) When building a package with internal build tools, we must ensure that
720747
these build tools are available in PATH, with appropriate environment
721748
variable overrides for their data directory. To do this, we call
@@ -724,12 +751,6 @@ things:
724751
(b) Moreover, these programs must be available in the search paths for the
725752
compiler itself, in case they are run at compile-time (e.g. with a Template
726753
Haskell splice). We achieve this using 'updatePathProgDb'.
727-
728-
(2) Given the compiler, we must compute the ProgramDb of programs that are
729-
specified alongside the compiler, such as ghc-pkg, haddock, and toolchain
730-
programs such as ar, ld.
731-
732-
We do this using the function 'configCompilerProgDb'.
733754
-}
734755

735756
-- ------------------------------------------------------------

changelog.d/conf-compiler-progs.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
---
2+
synopsis: Pre-configure compiler program database
3+
packages: [Cabal, cabal-install]
4+
prs: 11768
5+
---
6+
7+
The compiler program database, containing `ghc`, `ghc-pkg`, `haddock` and various
8+
toolchain programs (such as `ar`, `ld`) is now configured ahead of time within
9+
`cabal-install`, so that we don't have to re-configure all of those programs
10+
once for every package.
11+
12+
See the pre-existing Note [Caching the result of configuring the compiler] in
13+
Distribution.Client.ProjectPlanning and Note [Constructing the ProgramDb]
14+
in Distribution.Client.SetupWrapper for additional details.
15+
16+
This required a tiny change to `Cabal` to define and expose
17+
`clearUnconfiguredPrograms :: ProgramDb -> ProgramDb` for use in `cabal-install`.

0 commit comments

Comments
 (0)