Skip to content

Commit 94615d6

Browse files
authored
Merge pull request #8726 from mpickering/wip/no-configure
Add support for loading multiple components into one repl session
2 parents ccc09de + e61b658 commit 94615d6

File tree

87 files changed

+1663
-377
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

87 files changed

+1663
-377
lines changed

Cabal-tests/tests/UnitTests/Distribution/Utils/Structured.hs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ tests = testGroup "Distribution.Utils.Structured"
2929
, testCase "GenericPackageDescription" $
3030
md5Check (Proxy :: Proxy GenericPackageDescription) 0xa3e9433662ecf0c7a3c26f6d75a53ba1
3131
, testCase "LocalBuildInfo" $
32-
md5Check (Proxy :: Proxy LocalBuildInfo) 0x91ffcd61bbd83525e8edba877435a031
32+
md5Check (Proxy :: Proxy LocalBuildInfo) 0x30ebb8fffa1af2aefa9432ff4028eef8
3333
#endif
3434
]
3535

Cabal/src/Distribution/Backpack/Configure.hs

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ import Distribution.Verbosity
4646
import qualified Distribution.Compat.Graph as Graph
4747
import Distribution.Compat.Graph (Graph, IsNode(..))
4848
import Distribution.Utils.LogProgress
49+
import Distribution.Backpack.ModuleShape
4950

5051
import Data.Either
5152
( lefts )
@@ -66,15 +67,15 @@ configureComponentLocalBuildInfos
6667
-> Flag String -- configIPID
6768
-> Flag ComponentId -- configCID
6869
-> PackageDescription
69-
-> [PreExistingComponent]
70+
-> ([PreExistingComponent], [PromisedComponent])
7071
-> FlagAssignment -- configConfigurationsFlags
7172
-> [(ModuleName, Module)] -- configInstantiateWith
7273
-> InstalledPackageIndex
7374
-> Compiler
7475
-> LogProgress ([ComponentLocalBuildInfo], InstalledPackageIndex)
7576
configureComponentLocalBuildInfos
7677
verbosity use_external_internal_deps enabled deterministic ipid_flag cid_flag pkg_descr
77-
prePkgDeps flagAssignment instantiate_with installedPackageSet comp = do
78+
(prePkgDeps, promisedPkgDeps) flagAssignment instantiate_with installedPackageSet comp = do
7879
-- NB: In single component mode, this returns a *single* component.
7980
-- In this graph, the graph is NOT closed.
8081
graph0 <- case mkComponentsGraph enabled pkg_descr of
@@ -92,6 +93,10 @@ configureComponentLocalBuildInfos
9293
ann_cname = pc_compname pkg
9394
}))
9495
| pkg <- prePkgDeps]
96+
`Map.union`
97+
Map.fromListWith Map.union
98+
[ (pkg, Map.singleton (ann_cname aid) aid)
99+
| PromisedComponent pkg aid <- promisedPkgDeps]
95100
graph1 <- toConfiguredComponents use_external_internal_deps
96101
flagAssignment
97102
deterministic ipid_flag cid_flag pkg_descr
@@ -102,13 +107,19 @@ configureComponentLocalBuildInfos
102107
let shape_pkg_map = Map.fromList
103108
[ (pc_cid pkg, (pc_open_uid pkg, pc_shape pkg))
104109
| pkg <- prePkgDeps]
110+
`Map.union`
111+
Map.fromList
112+
[ (ann_id aid, (DefiniteUnitId (unsafeMkDefUnitId
113+
(mkUnitId (unComponentId (ann_id aid) )))
114+
, emptyModuleShape))
115+
| PromisedComponent _ aid <- promisedPkgDeps]
105116
uid_lookup def_uid
106117
| Just pkg <- PackageIndex.lookupUnitId installedPackageSet uid
107118
= FullUnitId (Installed.installedComponentId pkg)
108119
(Map.fromList (Installed.instantiatedWith pkg))
109120
| otherwise = error ("uid_lookup: " ++ prettyShow uid)
110121
where uid = unDefUnitId def_uid
111-
graph2 <- toLinkedComponents verbosity uid_lookup
122+
graph2 <- toLinkedComponents verbosity (not (null promisedPkgDeps)) uid_lookup
112123
(package pkg_descr) shape_pkg_map graph1
113124

114125
infoProgress $
@@ -129,7 +140,7 @@ configureComponentLocalBuildInfos
129140
infoProgress $ hang (text "Ready component graph:") 4
130141
(vcat (map dispReadyComponent graph4))
131142

132-
toComponentLocalBuildInfos comp installedPackageSet pkg_descr prePkgDeps graph4
143+
toComponentLocalBuildInfos comp installedPackageSet promisedPkgDeps pkg_descr prePkgDeps graph4
133144

134145
------------------------------------------------------------------------------
135146
-- ComponentLocalBuildInfo
@@ -138,13 +149,14 @@ configureComponentLocalBuildInfos
138149
toComponentLocalBuildInfos
139150
:: Compiler
140151
-> InstalledPackageIndex -- FULL set
152+
-> [PromisedComponent]
141153
-> PackageDescription
142154
-> [PreExistingComponent] -- external package deps
143155
-> [ReadyComponent]
144156
-> LogProgress ([ComponentLocalBuildInfo],
145157
InstalledPackageIndex) -- only relevant packages
146158
toComponentLocalBuildInfos
147-
comp installedPackageSet pkg_descr externalPkgDeps graph = do
159+
comp installedPackageSet promisedPkgDeps pkg_descr externalPkgDeps graph = do
148160
-- Check and make sure that every instantiated component exists.
149161
-- We have to do this now, because prior to linking/instantiating
150162
-- we don't actually know what the full set of 'UnitId's we need
@@ -178,9 +190,15 @@ toComponentLocalBuildInfos
178190
--
179191
packageDependsIndex = PackageIndex.fromList (lefts local_graph)
180192
fullIndex = Graph.fromDistinctList local_graph
193+
181194
case Graph.broken fullIndex of
182195
[] -> return ()
183-
broken ->
196+
-- If there are promised dependencies, we don't know what the dependencies
197+
-- of these are and that can easily lead to a broken graph. So assume that
198+
-- any promised package is not broken (ie all its dependencies, transitively,
199+
-- will be there). That's a promise.
200+
broken | not (null promisedPkgDeps) -> return ()
201+
| otherwise ->
184202
-- TODO: ppr this
185203
dieProgress . text $
186204
"The following packages are broken because other"

Cabal/src/Distribution/Backpack/ConfiguredComponent.hs

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -177,22 +177,22 @@ toConfiguredComponent pkg_descr this_cid lib_dep_map exe_dep_map component = do
177177
if newPackageDepsBehaviour pkg_descr
178178
then fmap concat $ forM (targetBuildDepends bi) $
179179
\(Dependency name _ sublibs) -> do
180-
pkg <- case Map.lookup name lib_dep_map of
180+
case Map.lookup name lib_dep_map of
181181
Nothing ->
182182
dieProgress $
183183
text "Dependency on unbuildable" <+>
184184
text "package" <+> pretty name
185-
Just p -> return p
186-
-- Return all library components
187-
forM (NonEmptySet.toList sublibs) $ \lib ->
188-
let comp = CLibName lib in
189-
case Map.lookup comp pkg of
190-
Nothing ->
191-
dieProgress $
192-
text "Dependency on unbuildable" <+>
193-
text (showLibraryName lib) <+>
194-
text "from" <+> pretty name
195-
Just v -> return v
185+
Just pkg -> do
186+
-- Return all library components
187+
forM (NonEmptySet.toList sublibs) $ \lib ->
188+
let comp = CLibName lib in
189+
case Map.lookup comp pkg of
190+
Nothing ->
191+
dieProgress $
192+
text "Dependency on unbuildable" <+>
193+
text (showLibraryName lib) <+>
194+
text "from" <+> pretty name
195+
Just v -> return v
196196
else return old_style_lib_deps
197197
mkConfiguredComponent
198198
pkg_descr this_cid

Cabal/src/Distribution/Backpack/LinkedComponent.hs

Lines changed: 34 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -114,12 +114,13 @@ instance Package LinkedComponent where
114114

115115
toLinkedComponent
116116
:: Verbosity
117+
-> Bool -- ^ Whether there are any "promised" package dependencies which we won't find already installed.
117118
-> FullDb
118119
-> PackageId
119120
-> LinkedComponentMap
120121
-> ConfiguredComponent
121122
-> LogProgress LinkedComponent
122-
toLinkedComponent verbosity db this_pid pkg_map ConfiguredComponent {
123+
toLinkedComponent verbosity anyPromised db this_pid pkg_map ConfiguredComponent {
123124
cc_ann_id = aid@AnnotatedId { ann_id = this_cid },
124125
cc_component = component,
125126
cc_exe_deps = exe_deps,
@@ -276,9 +277,14 @@ toLinkedComponent verbosity db this_pid pkg_map ConfiguredComponent {
276277
case filter (\x' -> unWithSource x /= unWithSource x') xs of
277278
[] -> return ()
278279
_ -> Left $ ambiguousReexportMsg reex x xs
279-
return (to, unWithSource x)
280+
return (to, Just (unWithSource x))
280281
_ ->
281-
Left (brokenReexportMsg reex)
282+
-- Can't resolve it right now.. carry on with the assumption it will be resolved
283+
-- dynamically later by an in-memory package which hasn't been installed yet.
284+
if anyPromised
285+
then return (to, Nothing)
286+
-- But if nothing is promised, eagerly report an error, as we already know everything.
287+
else Left (brokenReexportMsg reex)
282288

283289
-- TODO: maybe check this earlier; it's syntactically obvious.
284290
let build_reexports m (k, v)
@@ -289,8 +295,27 @@ toLinkedComponent verbosity db this_pid pkg_map ConfiguredComponent {
289295
provs <- foldM build_reexports Map.empty $
290296
-- TODO: doublecheck we have checked for
291297
-- src_provs duplicates already!
292-
[ (mod_name, OpenModule this_uid mod_name) | mod_name <- src_provs ] ++
293-
reexports_list
298+
-- These are normal module exports.
299+
[ (mod_name, (OpenModule this_uid mod_name)) | mod_name <- src_provs ]
300+
++
301+
-- These are reexports, which we managed to resolve to something in an external package.
302+
[(mn_new, om) | (mn_new, Just om) <- reexports_list ]
303+
++
304+
-- These ones.. we didn't resolve but also we might not have to
305+
-- resolve them because they could come from a promised unit,
306+
-- which we don't know anything about yet. GHC will resolve
307+
-- these itself when it is dealing with the multi-session.
308+
-- These ones will not be built, registered and put
309+
-- into a package database, we only need them to make it as far
310+
-- as generating GHC options where the info will be used to
311+
-- pass the reexported-module option to GHC.
312+
313+
-- We also know that in the case there are promised units that
314+
-- we will not be doing anything to do with backpack like
315+
-- unification etc..
316+
[ (mod_name, OpenModule (DefiniteUnitId (unsafeMkDefUnitId
317+
(mkUnitId "fake"))) mod_name)
318+
| (mod_name, Nothing) <- reexports_list ]
294319

295320
let final_linked_shape = ModuleShape provs (Map.keysSet (modScopeRequires linked_shape))
296321

@@ -337,20 +362,22 @@ toLinkedComponent verbosity db this_pid pkg_map ConfiguredComponent {
337362
-- every ComponentId gets converted into a UnitId by way of SimpleUnitId.
338363
toLinkedComponents
339364
:: Verbosity
365+
-> Bool -- ^ Whether there are any "promised" package dependencies which we won't
366+
-- find already installed.
340367
-> FullDb
341368
-> PackageId
342369
-> LinkedComponentMap
343370
-> [ConfiguredComponent]
344371
-> LogProgress [LinkedComponent]
345-
toLinkedComponents verbosity db this_pid lc_map0 comps
372+
toLinkedComponents verbosity anyPromised db this_pid lc_map0 comps
346373
= fmap snd (mapAccumM go lc_map0 comps)
347374
where
348375
go :: Map ComponentId (OpenUnitId, ModuleShape)
349376
-> ConfiguredComponent
350377
-> LogProgress (Map ComponentId (OpenUnitId, ModuleShape), LinkedComponent)
351378
go lc_map cc = do
352379
lc <- addProgressCtx (text "In the stanza" <+> text (componentNameStanza (cc_name cc))) $
353-
toLinkedComponent verbosity db this_pid lc_map cc
380+
toLinkedComponent verbosity anyPromised db this_pid lc_map cc
354381
return (extendLinkedComponentMap lc lc_map, lc)
355382

356383
type LinkedComponentMap = Map ComponentId (OpenUnitId, ModuleShape)

Cabal/src/Distribution/Backpack/PreExistingComponent.hs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
-- | See <https://github.com/ezyang/ghc-proposals/blob/backpack/proposals/0000-backpack.rst>
22
module Distribution.Backpack.PreExistingComponent (
33
PreExistingComponent(..),
4+
PromisedComponent(..),
45
ipiToPreExistingComponent,
56
) where
67

@@ -20,6 +21,21 @@ import Distribution.Package
2021
import qualified Data.Map as Map
2122
import qualified Distribution.InstalledPackageInfo as Installed
2223
import Distribution.InstalledPackageInfo (InstalledPackageInfo)
24+
import Distribution.Types.AnnotatedId
25+
26+
-- | A /promised/ component.
27+
--
28+
-- These components are promised to @configure@ but are not yet built.
29+
--
30+
-- In other words this is 'PreExistingComponent' which doesn't yet exist.
31+
--
32+
data PromisedComponent = PromisedComponent
33+
{ pr_pkgname :: PackageName
34+
, pr_cid :: AnnotatedId ComponentId
35+
}
36+
37+
instance Package PromisedComponent where
38+
packageId = packageId . pr_cid
2339

2440
-- | Stripped down version of 'LinkedComponent' for things
2541
-- we don't need to know how to build.

Cabal/src/Distribution/Compat/ResponseFile.hs

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
-- Compatibility layer for GHC.ResponseFile
44
-- Implementation from base 4.12.0 is used.
55
-- http://hackage.haskell.org/package/base-4.12.0.0/src/LICENSE
6-
module Distribution.Compat.ResponseFile (expandResponse) where
6+
module Distribution.Compat.ResponseFile (expandResponse, escapeArgs) where
77

88
import Distribution.Compat.Prelude
99
import Prelude ()
@@ -13,7 +13,7 @@ import System.IO (hPutStrLn, stderr)
1313
import System.IO.Error
1414

1515
#if MIN_VERSION_base(4,12,0)
16-
import GHC.ResponseFile (unescapeArgs)
16+
import GHC.ResponseFile (unescapeArgs, escapeArgs)
1717
#else
1818

1919
unescapeArgs :: String -> [String]
@@ -47,6 +47,20 @@ unescape args = reverse . map reverse $ go args NoneQ False [] []
4747
| '"' == c = go cs DblQ False a as
4848
| otherwise = go cs NoneQ False (c:a) as
4949

50+
escapeArgs :: [String] -> String
51+
escapeArgs = unlines . map escapeArg
52+
53+
escapeArg :: String -> String
54+
escapeArg = reverse . foldl' escape []
55+
56+
escape :: String -> Char -> String
57+
escape cs c
58+
| isSpace c
59+
|| '\\' == c
60+
|| '\'' == c
61+
|| '"' == c = c:'\\':cs -- n.b., our caller must reverse the result
62+
| otherwise = c:cs
63+
5064
#endif
5165

5266
expandResponse :: [String] -> IO [String]

0 commit comments

Comments
 (0)