| ... |
... |
@@ -12,6 +12,12 @@ module GHC.Linker.Deps |
|
12
|
12
|
( LinkDepsOpts (..)
|
|
13
|
13
|
, LinkDeps (..)
|
|
14
|
14
|
, getLinkDeps
|
|
|
15
|
+ , Linkables (..)
|
|
|
16
|
+ , LinkDep (..)
|
|
|
17
|
+ , LinkModule (..)
|
|
|
18
|
+ , linkablesGet
|
|
|
19
|
+ , resolveLinkDeps
|
|
|
20
|
+ , selectLinkDeps
|
|
15
|
21
|
)
|
|
16
|
22
|
where
|
|
17
|
23
|
|
| ... |
... |
@@ -42,16 +48,13 @@ import GHC.Unit.Module.Graph |
|
42
|
48
|
import GHC.Unit.Home.ModInfo
|
|
43
|
49
|
|
|
44
|
50
|
import GHC.Iface.Errors.Types
|
|
45
|
|
-import GHC.Iface.Errors.Ppr
|
|
46
|
51
|
|
|
47
|
52
|
import GHC.Utils.Misc
|
|
48
|
53
|
import GHC.Unit.Home
|
|
49
|
|
-import qualified GHC.Unit.Home.Graph as HUG
|
|
50
|
54
|
import GHC.Data.Maybe
|
|
51
|
55
|
|
|
52
|
56
|
import Control.Applicative
|
|
53
|
57
|
import Control.Monad.IO.Class (MonadIO (liftIO))
|
|
54
|
|
-import Control.Monad.Trans.Except (ExceptT, runExceptT, throwE)
|
|
55
|
58
|
|
|
56
|
59
|
import Data.Foldable (traverse_)
|
|
57
|
60
|
import qualified Data.Set as Set
|
| ... |
... |
@@ -60,11 +63,8 @@ import Data.List (isSuffixOf) |
|
60
|
63
|
import System.FilePath
|
|
61
|
64
|
import System.Directory
|
|
62
|
65
|
import GHC.Utils.Logger (Logger)
|
|
63
|
|
-import Control.Monad ((<$!>))
|
|
64
|
|
-import GHC.Driver.Env
|
|
65
|
|
-import {-# SOURCE #-} GHC.Driver.Main
|
|
66
|
|
-import Data.Time.Clock
|
|
67
|
66
|
import GHC.Unit.Home.Graph
|
|
|
67
|
+import GHC.Driver.Env.Types (Linkables (..), LinkDeps (..))
|
|
68
|
68
|
|
|
69
|
69
|
|
|
70
|
70
|
data LinkDepsOpts = LinkDepsOpts
|
| ... |
... |
@@ -86,12 +86,9 @@ data LinkDepsOpts = LinkDepsOpts |
|
86
|
86
|
, ldLogger :: !Logger
|
|
87
|
87
|
}
|
|
88
|
88
|
|
|
89
|
|
-data LinkDeps = LinkDeps
|
|
90
|
|
- { ldNeededLinkables :: [Linkable]
|
|
91
|
|
- , ldAllLinkables :: [Linkable]
|
|
92
|
|
- , ldNeededUnits :: [UnitId]
|
|
93
|
|
- , ldAllUnits :: UniqDSet UnitId
|
|
94
|
|
- }
|
|
|
89
|
+linkablesGet :: Linkables -> SrcSpan -> [Module] -> IO LinkDeps
|
|
|
90
|
+linkablesGet Linkables {..} span mods =
|
|
|
91
|
+ linkablesSelect =<< linkablesResolve span mods
|
|
95
|
92
|
|
|
96
|
93
|
-- | Find all the packages and linkables that a set of modules depends on
|
|
97
|
94
|
--
|
| ... |
... |
@@ -108,14 +105,8 @@ getLinkDeps |
|
108
|
105
|
-> [Module] -- If you need these
|
|
109
|
106
|
-> IO LinkDeps -- ... then link these first
|
|
110
|
107
|
getLinkDeps opts interp pls span mods = do
|
|
111
|
|
- -- The interpreter and dynamic linker can only handle object code built
|
|
112
|
|
- -- the "normal" way, i.e. no non-std ways like profiling or ticky-ticky.
|
|
113
|
|
- -- So here we check the build tag: if we're building a non-standard way
|
|
114
|
|
- -- then we need to find & link object files built the "normal" way.
|
|
115
|
|
- maybe_normal_osuf <- checkNonStdWay opts interp span
|
|
116
|
|
-
|
|
117
|
|
- withTiming (ldLogger opts) (text "getLinkDeps" <+> brackets (ppr span)) (const ()) $
|
|
118
|
|
- get_link_deps opts pls maybe_normal_osuf span mods
|
|
|
108
|
+ linkables <- resolveLinkDeps opts pls span mods
|
|
|
109
|
+ selectLinkDeps opts interp span linkables
|
|
119
|
110
|
|
|
120
|
111
|
-- | Determine which parts of a module and its dependencies should be linked
|
|
121
|
112
|
-- when resolving external dependencies.
|
| ... |
... |
@@ -151,7 +142,7 @@ data LinkExternal = |
|
151
|
142
|
}
|
|
152
|
143
|
|
|
153
|
144
|
instance Outputable LinkExternal where
|
|
154
|
|
- ppr LinkExternal {..} = ppr le_module <> brackets (ppr le_details)
|
|
|
145
|
+ ppr LinkExternal {..} = ppr le_module Outputable.<> brackets (ppr le_details)
|
|
155
|
146
|
|
|
156
|
147
|
-- | The decision about the linking method used for a given module.
|
|
157
|
148
|
data LinkModule =
|
| ... |
... |
@@ -180,48 +171,31 @@ instance Outputable LinkModule where |
|
180
|
171
|
LinkObjectModule mod _ -> ppr mod
|
|
181
|
172
|
LinkByteCodeModule mod _ -> ppr mod <+> brackets (text "BC")
|
|
182
|
173
|
|
|
183
|
|
--- | Compute the linkables for the given module set's dependencies.
|
|
184
|
|
---
|
|
185
|
|
--- Home modules in make mode are treated separately in a preprocessing step,
|
|
186
|
|
--- then all the remaining external deps are processed for both modes.
|
|
187
|
|
--- If bytecode is available, transitive external deps are included, otherwise
|
|
188
|
|
--- the module's library is linked and processing stops.
|
|
189
|
|
---
|
|
190
|
|
--- The results are split into sets of needed/loaded modules/packages.
|
|
191
|
|
-get_link_deps
|
|
192
|
|
- :: LinkDepsOpts
|
|
193
|
|
- -> LoaderState
|
|
194
|
|
- -> Maybe FilePath -- replace object suffixes?
|
|
195
|
|
- -> SrcSpan
|
|
196
|
|
- -> [Module]
|
|
197
|
|
- -> IO LinkDeps
|
|
198
|
|
-get_link_deps opts pls maybe_normal_osuf span mods = do
|
|
199
|
|
- (link_deps_home, module_deps_external) <- separate_home_deps
|
|
200
|
|
- link_deps_external <- external_deps opts module_deps_external
|
|
201
|
|
- let (loaded_modules, needed_modules, ldAllUnits, ldNeededUnits) =
|
|
202
|
|
- classify_deps pls link_deps_home link_deps_external
|
|
203
|
|
- ldNeededLinkables <- mapM module_linkable needed_modules
|
|
204
|
|
- pure LinkDeps {
|
|
205
|
|
- ldNeededLinkables,
|
|
206
|
|
- ldAllLinkables = loaded_modules ++ ldNeededLinkables,
|
|
207
|
|
- ldNeededUnits,
|
|
208
|
|
- ldAllUnits
|
|
209
|
|
- }
|
|
|
174
|
+resolveLinkDeps ::
|
|
|
175
|
+ LinkDepsOpts ->
|
|
|
176
|
+ LoaderState ->
|
|
|
177
|
+ SrcSpan ->
|
|
|
178
|
+ [Module] ->
|
|
|
179
|
+ IO ([Linkable], [LinkModule], UniqDSet UnitId, [UnitId])
|
|
|
180
|
+resolveLinkDeps opts pls span mods =
|
|
|
181
|
+ withTiming (ldLogger opts) (text "getLinkDeps" <+> brackets (ppr span)) (const ()) $ do
|
|
|
182
|
+ (link_deps_home, module_deps_external) <- separate_home_deps
|
|
|
183
|
+ link_deps_external <- external_deps opts module_deps_external
|
|
|
184
|
+ pure (classify_deps pls link_deps_home link_deps_external)
|
|
210
|
185
|
where
|
|
211
|
186
|
mod_graph = ldModuleGraph opts
|
|
212
|
187
|
unit_env = ldUnitEnv opts
|
|
213
|
188
|
noninteractive = filterOut isInteractiveModule mods
|
|
214
|
189
|
|
|
215
|
|
- -- Preprocess the dependencies in make mode to remove all home modules,
|
|
216
|
|
- -- since the transitive dependency closure is already cached for those in
|
|
217
|
|
- -- the HUG (see MultiLayerModulesTH_* tests for the performance impact).
|
|
|
190
|
+ -- Preprocess the dependencies to remove all home modules, since the
|
|
|
191
|
+ -- transitive dependency closure is already cached for those in the HUG
|
|
|
192
|
+ -- (see MultiLayerModulesTH_* tests for the performance impact).
|
|
218
|
193
|
--
|
|
219
|
|
- -- Returns the remaining, external, dependencies on the right, which is the
|
|
220
|
|
- -- entire set for oneshot mode.
|
|
221
|
|
- separate_home_deps =
|
|
222
|
|
- if ldOneShotMode opts
|
|
223
|
|
- then pure ([], LinkExternal LinkAllDeps <$!> noninteractive)
|
|
224
|
|
- else make_deps
|
|
|
194
|
+ -- Returns the remaining, external, dependencies on the right.
|
|
|
195
|
+ -- This function only supports make mode; oneshot mode (in which the
|
|
|
196
|
+ -- entire dependency set would be treated as external) is not used by
|
|
|
197
|
+ -- this worker and is not supported here.
|
|
|
198
|
+ separate_home_deps = make_deps
|
|
225
|
199
|
|
|
226
|
200
|
make_deps = do
|
|
227
|
201
|
(dep_ext, mmods) <- unzip <$> mapM get_mod_info all_home_mods
|
| ... |
... |
@@ -265,6 +239,22 @@ get_link_deps opts pls maybe_normal_osuf span mods = do |
|
265
|
239
|
Nothing -> throwProgramError opts $
|
|
266
|
240
|
text "getLinkDeps: Home module not loaded" <+> ppr (gwib_mod gwib) <+> ppr uid
|
|
267
|
241
|
|
|
|
242
|
+select_link_deps
|
|
|
243
|
+ :: LinkDepsOpts
|
|
|
244
|
+ -> Maybe FilePath -- replace object suffixes?
|
|
|
245
|
+ -> SrcSpan
|
|
|
246
|
+ -> ([Linkable], [LinkModule], UniqDSet UnitId, [UnitId])
|
|
|
247
|
+ -> IO LinkDeps
|
|
|
248
|
+select_link_deps opts maybe_normal_osuf span (loaded_modules, needed_modules, ldAllUnits, ldNeededUnits) = do
|
|
|
249
|
+ ldNeededLinkables <- mapM module_linkable needed_modules
|
|
|
250
|
+ pure LinkDeps {
|
|
|
251
|
+ ldNeededLinkables,
|
|
|
252
|
+ ldAllLinkables = loaded_modules ++ ldNeededLinkables,
|
|
|
253
|
+ ldNeededUnits,
|
|
|
254
|
+ ldAllUnits
|
|
|
255
|
+ }
|
|
|
256
|
+ where
|
|
|
257
|
+
|
|
268
|
258
|
no_obj :: Outputable a => a -> IO b
|
|
269
|
259
|
no_obj mod = dieWith opts span $
|
|
270
|
260
|
text "cannot find object file for module" <+>
|
| ... |
... |
@@ -277,7 +267,7 @@ get_link_deps opts pls maybe_normal_osuf span mods = do |
|
277
|
267
|
-- results.
|
|
278
|
268
|
module_linkable = \case
|
|
279
|
269
|
LinkHomeModule hmi ->
|
|
280
|
|
- adjust_linkable (expectJust "getLinkDeps" (homeModLinkable hmi))
|
|
|
270
|
+ adjust_linkable (expectJust "foo" (homeModLinkable hmi))
|
|
281
|
271
|
|
|
282
|
272
|
LinkObjectModule mod loc -> do
|
|
283
|
273
|
findObjectLinkableMaybe mod loc >>= \case
|
| ... |
... |
@@ -321,6 +311,20 @@ get_link_deps opts pls maybe_normal_osuf span mods = do |
|
321
|
311
|
CoreBindings WholeCoreBindings {wcb_module} ->
|
|
322
|
312
|
pprPanic "Unhydrated core bindings" (ppr wcb_module)
|
|
323
|
313
|
|
|
|
314
|
+selectLinkDeps
|
|
|
315
|
+ :: LinkDepsOpts
|
|
|
316
|
+ -> Interp
|
|
|
317
|
+ -> SrcSpan -- for error messages
|
|
|
318
|
+ -> ([Linkable], [LinkModule], UniqDSet UnitId, [UnitId])
|
|
|
319
|
+ -> IO LinkDeps -- ... then link these first
|
|
|
320
|
+selectLinkDeps opts interp span linkables = do
|
|
|
321
|
+ -- The interpreter and dynamic linker can only handle object code built
|
|
|
322
|
+ -- the "normal" way, i.e. no non-std ways like profiling or ticky-ticky.
|
|
|
323
|
+ -- So here we check the build tag: if we're building a non-standard way
|
|
|
324
|
+ -- then we need to find & link object files built the "normal" way.
|
|
|
325
|
+ maybe_normal_osuf <- checkNonStdWay opts interp span
|
|
|
326
|
+ select_link_deps opts maybe_normal_osuf span linkables
|
|
|
327
|
+
|
|
324
|
328
|
data LinkDep =
|
|
325
|
329
|
LinkModules !(UniqDFM ModuleName LinkModule)
|
|
326
|
330
|
|
|
| ... |
... |
@@ -331,11 +335,6 @@ instance Outputable LinkDep where |
|
331
|
335
|
LinkModules mods -> text "modules:" <+> ppr (eltsUDFM mods)
|
|
332
|
336
|
LinkLibrary uid -> text "library:" <+> ppr uid
|
|
333
|
337
|
|
|
334
|
|
-data OneshotError =
|
|
335
|
|
- NoInterface !MissingInterfaceError
|
|
336
|
|
- |
|
|
337
|
|
- LinkBootModule !Module
|
|
338
|
|
-
|
|
339
|
338
|
-- | Compute the transitive dependency closure of the given modules.
|
|
340
|
339
|
--
|
|
341
|
340
|
-- Used for all oneshot mode dependencies and for external dependencies of home
|
| ... |
... |
@@ -346,21 +345,13 @@ external_deps :: |
|
346
|
345
|
[LinkExternal] ->
|
|
347
|
346
|
IO [LinkDep]
|
|
348
|
347
|
external_deps opts mods =
|
|
349
|
|
- runExceptT (external_deps_loop opts mods emptyUDFM) >>= \case
|
|
350
|
|
- Right a -> pure (eltsUDFM a)
|
|
351
|
|
- Left err -> throwProgramError opts (message err)
|
|
352
|
|
- where
|
|
353
|
|
- message = \case
|
|
354
|
|
- NoInterface err ->
|
|
355
|
|
- missingInterfaceErrorDiagnostic (ldMsgOpts opts) err
|
|
356
|
|
- LinkBootModule mod ->
|
|
357
|
|
- link_boot_mod_error mod
|
|
|
348
|
+ eltsUDFM <$> external_deps_loop opts mods emptyUDFM
|
|
358
|
349
|
|
|
359
|
350
|
external_deps_loop ::
|
|
360
|
351
|
LinkDepsOpts ->
|
|
361
|
352
|
[LinkExternal] ->
|
|
362
|
353
|
UniqDFM UnitId LinkDep ->
|
|
363
|
|
- ExceptT OneshotError IO (UniqDFM UnitId LinkDep)
|
|
|
354
|
+ IO (UniqDFM UnitId LinkDep)
|
|
364
|
355
|
external_deps_loop _ [] acc =
|
|
365
|
356
|
pure acc
|
|
366
|
357
|
external_deps_loop opts (job@LinkExternal {le_module = mod, ..} : mods) acc = do
|
| ... |
... |
@@ -386,8 +377,7 @@ external_deps_loop opts (job@LinkExternal {le_module = mod, ..} : mods) acc = do |
|
386
|
377
|
-- link an object file (which happens for home unit modules, since those
|
|
387
|
378
|
-- have no libraries).
|
|
388
|
379
|
process_module = \case
|
|
389
|
|
- LinkAllDeps | is_home || package_bc -> try_iface
|
|
390
|
|
- | otherwise -> add_library
|
|
|
380
|
+ LinkAllDeps -> add_library
|
|
391
|
381
|
|
|
392
|
382
|
-- @LinkOnlyPackages@ is used for make mode home modules, so all imports
|
|
393
|
383
|
-- that are not external are already processed otherwise.
|
| ... |
... |
@@ -407,45 +397,9 @@ external_deps_loop opts (job@LinkExternal {le_module = mod, ..} : mods) acc = do |
|
407
|
397
|
| otherwise
|
|
408
|
398
|
= False
|
|
409
|
399
|
|
|
410
|
|
- -- Load the iface and attempt to get bytecode from Core bindings.
|
|
411
|
|
- try_iface =
|
|
412
|
|
- liftIO (ldLoadIface opts load_reason mod) >>= \case
|
|
413
|
|
- Failed err -> throwE (NoInterface err)
|
|
414
|
|
- Succeeded (iface, loc) -> do
|
|
415
|
|
- mb_load_bc <- liftIO (ldLoadByteCode opts (mi_module iface))
|
|
416
|
|
- with_iface iface loc mb_load_bc
|
|
417
|
|
-
|
|
418
|
|
- -- Decide how to link this module.
|
|
419
|
|
- -- If bytecode or an object file is available, use those in that order.
|
|
420
|
|
- -- Otherwise fall back to linking a library.
|
|
421
|
|
- with_iface iface loc mb_load_bc
|
|
422
|
|
- | IsBoot <- mi_boot iface
|
|
423
|
|
- = throwE (LinkBootModule mod)
|
|
424
|
|
-
|
|
425
|
|
- | ldUseByteCode opts
|
|
426
|
|
- , is_home || package_bc
|
|
427
|
|
- , Just load_bc <- mb_load_bc
|
|
428
|
|
- = add_module iface (LinkByteCodeModule mod load_bc) "bytecode"
|
|
429
|
|
-
|
|
430
|
|
- | is_home
|
|
431
|
|
- = add_module iface (LinkObjectModule mod loc) "object"
|
|
432
|
|
-
|
|
433
|
|
- | otherwise
|
|
434
|
|
- = add_library
|
|
435
|
|
-
|
|
436
|
400
|
add_library =
|
|
437
|
401
|
pure (addToUDFM acc mod_unit_id (LinkLibrary mod_unit_id), [], Just "library")
|
|
438
|
402
|
|
|
439
|
|
- add_module iface lmod action =
|
|
440
|
|
- with_deps with_mod iface True action
|
|
441
|
|
- where
|
|
442
|
|
- with_mod = alterUDFM (add_package_module lmod) acc mod_unit_id
|
|
443
|
|
-
|
|
444
|
|
- add_package_module lmod = \case
|
|
445
|
|
- Just (LinkLibrary u) -> Just (LinkLibrary u)
|
|
446
|
|
- Just (LinkModules old) -> Just (LinkModules (addToUDFM old mod_name lmod))
|
|
447
|
|
- Nothing -> Just (LinkModules (unitUDFM mod_name lmod))
|
|
448
|
|
-
|
|
449
|
403
|
with_deps acc iface local action =
|
|
450
|
404
|
pure (addListToUDFM acc link, new_local ++ new_package, Just action)
|
|
451
|
405
|
where
|
| ... |
... |
@@ -458,26 +412,17 @@ external_deps_loop opts (job@LinkExternal {le_module = mod, ..} : mods) acc = do |
|
458
|
412
|
| (_, GWIB m _) <- Set.toList (dep_direct_mods (mi_deps iface))
|
|
459
|
413
|
]
|
|
460
|
414
|
|
|
461
|
|
- -- If bytecode linking of external dependencies is enabled, add them to the
|
|
462
|
|
- -- jobs passed to the next iteration of 'external_deps_loop'.
|
|
463
|
|
- -- Otherwise, link all package deps as libraries.
|
|
464
|
|
- package_deps iface
|
|
465
|
|
- | package_bc
|
|
466
|
|
- = ([], [LinkExternal LinkAllDeps usg_mod | UsagePackageModule {usg_mod} <- mi_usages iface])
|
|
467
|
|
- | otherwise
|
|
468
|
|
- = ([(u, LinkLibrary u) | u <- Set.toList (dep_direct_pkgs (mi_deps iface))], [])
|
|
469
|
|
-
|
|
470
|
|
- load_reason =
|
|
471
|
|
- text "need to link module" <+> ppr mod <+>
|
|
472
|
|
- text "due to use of Template Haskell"
|
|
473
|
|
-
|
|
474
|
|
- package_bc = ldPkgByteCode opts
|
|
475
|
|
-
|
|
476
|
|
- -- In multiple home unit mode, this only considers modules from the same
|
|
477
|
|
- -- unit as the splice's module to be eligible for linking bytecode when
|
|
478
|
|
- -- @-fpackage-db-byte-code@ is off.
|
|
479
|
|
- -- For make mode, this is irrelevant, since any bytecode from the HUG is
|
|
480
|
|
- -- obtained directly, not going through 'external_deps'.
|
|
|
415
|
+ -- External package dependencies are always linked as libraries; this
|
|
|
416
|
+ -- worker does not support traversing external package modules for
|
|
|
417
|
+ -- bytecode ("-fpackage-db-byte-code").
|
|
|
418
|
+ package_deps iface =
|
|
|
419
|
+ ([(u, LinkLibrary u) | u <- Set.toList (dep_direct_pkgs (mi_deps iface))], [])
|
|
|
420
|
+
|
|
|
421
|
+ -- Considers only modules from the same unit as the splice's module to be
|
|
|
422
|
+ -- eligible for linking bytecode.
|
|
|
423
|
+ -- For make mode, this is irrelevant for home modules in general, since any
|
|
|
424
|
+ -- bytecode from the HUG is obtained directly, not going through
|
|
|
425
|
+ -- 'external_deps'.
|
|
481
|
426
|
is_home
|
|
482
|
427
|
| Just home <- ue_homeUnit (ldUnitEnv opts)
|
|
483
|
428
|
= homeUnitAsUnit home == mod_unit
|
| ... |
... |
@@ -489,11 +434,6 @@ external_deps_loop opts (job@LinkExternal {le_module = mod, ..} : mods) acc = do |
|
489
|
434
|
mod_unit_id = moduleUnitId mod
|
|
490
|
435
|
mod_unit = moduleUnit mod
|
|
491
|
436
|
|
|
492
|
|
-link_boot_mod_error :: Module -> SDoc
|
|
493
|
|
-link_boot_mod_error mod =
|
|
494
|
|
- text "module" <+> ppr mod <+>
|
|
495
|
|
- text "cannot be linked; it is only available as a boot module"
|
|
496
|
|
-
|
|
497
|
437
|
-- | Split link dependencies into the sets of modules and packages that have
|
|
498
|
438
|
-- been linked previously and those that need to be linked now by checking for
|
|
499
|
439
|
-- their presence in the 'LoaderState':
|