Marge Bot pushed to branch wip/marge_bot_batch_merge_job at Glasgow Haskell Compiler / GHC
Commits:
-
1314f2fd
by David Eichmann at 2026-06-16T05:46:52-04:00
-
7f72bcb3
by mangoiv at 2026-06-16T05:47:39-04:00
-
842bef9f
by Alan Zimmerman at 2026-06-16T05:48:25-04:00
-
38b3e94d
by Wolfgang Jeltsch at 2026-06-16T11:32:09-04:00
-
678ee355
by Christian Georgii at 2026-06-16T11:32:13-04:00
18 changed files:
- .gitlab-ci.yml
- + changelog.d/fix-plugin-finder-multi-home-unit.md
- compiler/.hlint.yaml
- compiler/GHC/Unit/Finder.hs
- compiler/Language/Haskell/Syntax/Extension.hs
- hadrian/src/Rules/Rts.hs
- + testsuite/tests/driver/multipleHomeUnits/plugin01/all.T
- + testsuite/tests/driver/multipleHomeUnits/plugin01/appunit
- + testsuite/tests/driver/multipleHomeUnits/plugin01/p/MyPlugin.hs
- + testsuite/tests/driver/multipleHomeUnits/plugin01/pluginunit
- + testsuite/tests/driver/multipleHomeUnits/plugin01/q/App.hs
- + testsuite/tests/driver/multipleHomeUnits/plugin02/all.T
- + testsuite/tests/driver/multipleHomeUnits/plugin02/appunit
- + testsuite/tests/driver/multipleHomeUnits/plugin02/p/MyPlugin.hs
- + testsuite/tests/driver/multipleHomeUnits/plugin02/pluginunit
- + testsuite/tests/driver/multipleHomeUnits/plugin02/q/App.hs
- + testsuite/tests/driver/multipleHomeUnits/plugin02/r/RexLib.hs
- + testsuite/tests/driver/multipleHomeUnits/plugin02/reexportunit
Changes:
| ... | ... | @@ -194,8 +194,9 @@ workflow: |
| 194 | 194 | # https://gitlab.com/gitlab-org/gitlab/-/issues/32837). This leads to the
|
| 195 | 195 | # hack in this MR where by default all jobs are `interruptible: True`, but
|
| 196 | 196 | # for pipelines we definitely want to run, there is a dummy job which
|
| 197 | -# happens first, which is `interreuptible: False`. This has the effect of
|
|
| 198 | -# dirtying the whole pipeline and
|
|
| 197 | +# happens first, which is `interruptible: False`. This has the effect of
|
|
| 198 | +# dirtying the whole pipeline and preventing another push to master from
|
|
| 199 | +# cancelling it.
|
|
| 199 | 200 | #
|
| 200 | 201 | # For now, this patch solves the immediate problem of making sure nightly
|
| 201 | 202 | # jobs are not cancelled.
|
| 1 | +section: compiler
|
|
| 2 | +synopsis: Find plugins defined in sibling home units in multiple-home-unit sessions
|
|
| 3 | +issues: #27349
|
|
| 4 | +mrs: !16156
|
|
| 5 | +description: {
|
|
| 6 | + In a multiple-home-unit session (e.g. ``cabal repl --enable-multi-repl`` or HLS), the plugin finder now also searches the home units that the current home unit depends on, following module reexports along the way, so a ``-fplugin`` defined in (or reexported by) a sibling home unit is found and loaded instead of failing as a hidden package.
|
|
| 7 | +} |
| ... | ... | @@ -3,6 +3,8 @@ |
| 3 | 3 | ##########################
|
| 4 | 4 | |
| 5 | 5 | - ignore: {}
|
| 6 | +- ignore: {name: Use camelCase}
|
|
| 7 | +- ignore: {name: Eta reduce}
|
|
| 6 | 8 | - warn: {name: Unused LANGUAGE pragma}
|
| 7 | 9 | - warn: {name: Use fewer LANGUAGE pragmas}
|
| 8 | 10 | - warn: {name: Redundant return}
|
| ... | ... | @@ -231,36 +231,14 @@ findImportedModuleNoHsc fc fopts ue home_module_name_providers_map mb_home_unit |
| 231 | 231 | NoPackage (panic "findImportedModule: no home-unit")
|
| 232 | 232 | |
| 233 | 233 | home_pkg_import :: (UnitId, FinderOpts) -> IO FindResult
|
| 234 | - home_pkg_import (uid, opts)
|
|
| 235 | - -- If the module is reexported, then look for it as if it was from the
|
|
| 236 | - -- perspective of that package which reexports it.
|
|
| 237 | - | Just real_mod_name
|
|
| 238 | - <- lookupUniqMap (finder_reexportedModules opts) mod_name
|
|
| 239 | - = findImportedModuleNoHsc fc opts ue home_module_name_providers_map
|
|
| 240 | - (Just $ DefiniteHomeUnit uid Nothing)
|
|
| 241 | - real_mod_name
|
|
| 242 | - NoPkgQual
|
|
| 243 | - | elementOfUniqSet mod_name (finder_hiddenModules opts)
|
|
| 244 | - = return (mkHomeHidden uid)
|
|
| 245 | - | otherwise
|
|
| 246 | - = findHomePackageModule fc opts uid mod_name
|
|
| 247 | - |
|
| 248 | - any_home_import :: IO FindResult
|
|
| 249 | - any_home_import = foldr1 orIfNotFound $
|
|
| 250 | - home_import :| map home_pkg_import other_fopts
|
|
| 251 | - -- Do not try to be smart and change this to `foldr orIfNotFound home_import
|
|
| 252 | - -- (map home_pkg_import other_fopts)`, as that would not be the same.
|
|
| 253 | - -- `home_import` is first because we need to first look within the current
|
|
| 254 | - -- unit before looking at the other units in order.
|
|
| 234 | + home_pkg_import = findHomeUnitDepModule fc ue home_module_name_providers_map mod_name
|
|
| 255 | 235 | |
| 256 | 236 | pkg_import :: IO FindResult
|
| 257 | 237 | pkg_import = findExposedPackageModule fc fopts unit_state mod_name mb_pkg
|
| 258 | 238 | |
| 259 | 239 | unqual_import :: IO FindResult
|
| 260 | - unqual_import
|
|
| 261 | - = any_home_import
|
|
| 262 | - `orIfNotFound`
|
|
| 263 | - findExposedPackageModule fc fopts unit_state mod_name NoPkgQual
|
|
| 240 | + unqual_import = findHomeOrRegularPackageModule fc fopts ue
|
|
| 241 | + home_module_name_providers_map mb_home_unit mod_name
|
|
| 264 | 242 | |
| 265 | 243 | unit_state :: UnitState
|
| 266 | 244 | unit_state = case mb_home_unit_id of
|
| ... | ... | @@ -268,22 +246,44 @@ findImportedModuleNoHsc fc fopts ue home_module_name_providers_map mb_home_unit |
| 268 | 246 | Just home_unit_id -> HUG.homeUnitEnv_units $
|
| 269 | 247 | ue_findHomeUnitEnv home_unit_id ue
|
| 270 | 248 | |
| 271 | - home_unit_deps :: Set UnitId
|
|
| 272 | - home_unit_deps = homeUnitDepends unit_state
|
|
| 249 | + other_fopts :: [(UnitId, FinderOpts)]
|
|
| 250 | + other_fopts = homeUnitDepsFinderOpts ue home_module_name_providers_map
|
|
| 251 | + unit_state mod_name
|
|
| 252 | + |
|
| 253 | +-- | Locate a plugin module requested by the user, for a compiler
|
|
| 254 | +-- plugin. This consults the same set of exposed packages as
|
|
| 255 | +-- 'findImportedModule', unless @-hide-all-plugin-packages@ or
|
|
| 256 | +-- @-plugin-package@ are specified.
|
|
| 257 | +findPluginModuleNoHsc
|
|
| 258 | + :: FinderCache
|
|
| 259 | + -> FinderOpts
|
|
| 260 | + -> UnitEnv
|
|
| 261 | + -> HomeModuleNameProvidersMap
|
|
| 262 | + -> Maybe HomeUnit
|
|
| 263 | + -> ModuleName
|
|
| 264 | + -> IO FindResult
|
|
| 265 | +findPluginModuleNoHsc fc fopts ue home_module_name_providers_map mb_home_unit@(Just home_unit) mod_name =
|
|
| 266 | + findHomeModuleAmongDeps fc fopts ue home_module_name_providers_map
|
|
| 267 | + mb_home_unit mod_name
|
|
| 268 | + `orIfNotFound`
|
|
| 269 | + findExposedPluginPackageModule fc fopts unit_state mod_name
|
|
| 270 | + where
|
|
| 271 | + unit_state = HUG.homeUnitEnv_units $
|
|
| 272 | + ue_findHomeUnitEnv (homeUnitId home_unit) ue
|
|
| 273 | +findPluginModuleNoHsc fc fopts ue _ Nothing mod_name =
|
|
| 274 | + findExposedPluginPackageModule fc fopts (ue_homeUnitState ue) mod_name
|
|
| 273 | 275 | |
| 274 | - ranked_home_unit_deps :: [UnitId]
|
|
| 275 | - ranked_home_unit_deps = rankedHomeUnitDeps home_module_name_providers_map
|
|
| 276 | - mod_name
|
|
| 277 | - home_unit_deps
|
|
| 276 | +findPluginModule :: HscEnv -> ModuleName -> IO FindResult
|
|
| 277 | +findPluginModule hsc_env mod_name = do
|
|
| 278 | + let fc = hsc_FC hsc_env
|
|
| 279 | + mb_home_unit = hsc_home_unit_maybe hsc_env
|
|
| 280 | + home_module_name_providers_map =
|
|
| 281 | + mgHomeModuleNameProvidersMap (hsc_mod_graph hsc_env)
|
|
| 282 | + findPluginModuleNoHsc fc (initFinderOpts (hsc_dflags hsc_env))
|
|
| 283 | + (hsc_unit_env hsc_env) home_module_name_providers_map mb_home_unit mod_name
|
|
| 278 | 284 | |
| 279 | - other_fopts :: [(UnitId, FinderOpts)]
|
|
| 280 | - other_fopts
|
|
| 281 | - = [
|
|
| 282 | - (uid, opts) |
|
|
| 283 | - uid <- ranked_home_unit_deps,
|
|
| 284 | - let opts = initFinderOpts $
|
|
| 285 | - homeUnitEnv_dflags (ue_findHomeUnitEnv uid ue)
|
|
| 286 | - ]
|
|
| 285 | +-- -----------------------------------------------------------------------------
|
|
| 286 | +-- Home Module Finder Helpers
|
|
| 287 | 287 | |
| 288 | 288 | -- | Yields the unit IDs from the given set as a list with those that refer to
|
| 289 | 289 | -- providers of the given home module name coming first. This is to prioritize
|
| ... | ... | @@ -323,24 +323,93 @@ rankedHomeUnitDeps home_module_name_providers_map mod_name home_unit_deps |
| 323 | 323 | uncached_deps :: Set UnitId
|
| 324 | 324 | uncached_deps = Set.difference home_unit_deps cached_providers
|
| 325 | 325 | |
| 326 | --- | Locate a plugin module requested by the user, for a compiler
|
|
| 327 | --- plugin. This consults the same set of exposed packages as
|
|
| 328 | --- 'findImportedModule', unless @-hide-all-plugin-packages@ or
|
|
| 329 | --- @-plugin-package@ are specified.
|
|
| 330 | -findPluginModuleNoHsc :: FinderCache -> FinderOpts -> UnitState -> Maybe HomeUnit -> ModuleName -> IO FindResult
|
|
| 331 | -findPluginModuleNoHsc fc fopts units (Just home_unit) mod_name =
|
|
| 332 | - findHomeModule fc fopts home_unit mod_name
|
|
| 333 | - `orIfNotFound`
|
|
| 334 | - findExposedPluginPackageModule fc fopts units mod_name
|
|
| 335 | -findPluginModuleNoHsc fc fopts units Nothing mod_name =
|
|
| 336 | - findExposedPluginPackageModule fc fopts units mod_name
|
|
| 326 | +-- | The 'FinderOpts' of the home units that should be searched, sorted by
|
|
| 327 | +-- priority order specified by 'rankedHomeUnitDeps'.
|
|
| 328 | +homeUnitDepsFinderOpts
|
|
| 329 | + :: UnitEnv
|
|
| 330 | + -> HomeModuleNameProvidersMap
|
|
| 331 | + -> UnitState -- ^ unit state of the requesting home unit
|
|
| 332 | + -> ModuleName
|
|
| 333 | + -> [(UnitId, FinderOpts)]
|
|
| 334 | +homeUnitDepsFinderOpts ue home_module_name_providers_map unit_state mod_name =
|
|
| 335 | + [ (uid, initFinderOpts (ue_unitFlags uid ue))
|
|
| 336 | + | uid <- rankedHomeUnitDeps home_module_name_providers_map mod_name
|
|
| 337 | + (homeUnitDepends unit_state)
|
|
| 338 | + ]
|
|
| 339 | + |
|
| 340 | +-- | Search for @mod_name@ in the given home unit.
|
|
| 341 | +findHomeUnitDepModule
|
|
| 342 | + :: FinderCache
|
|
| 343 | + -> UnitEnv
|
|
| 344 | + -> HomeModuleNameProvidersMap
|
|
| 345 | + -> ModuleName
|
|
| 346 | + -> (UnitId, FinderOpts)
|
|
| 347 | + -> IO FindResult
|
|
| 348 | +findHomeUnitDepModule fc ue home_module_name_providers_map mod_name (uid, opts)
|
|
| 349 | + -- If the module is reexported, then look for it as if it was from the
|
|
| 350 | + -- perspective of the package which reexports it.
|
|
| 351 | + | Just real_mod_name
|
|
| 352 | + <- lookupUniqMap (finder_reexportedModules opts) mod_name
|
|
| 353 | + = findHomeOrRegularPackageModule fc opts ue home_module_name_providers_map
|
|
| 354 | + (Just $ DefiniteHomeUnit uid Nothing)
|
|
| 355 | + real_mod_name
|
|
| 356 | + | elementOfUniqSet mod_name (finder_hiddenModules opts)
|
|
| 357 | + = return (mkHomeHidden uid)
|
|
| 358 | + | otherwise
|
|
| 359 | + = findHomePackageModule fc opts uid mod_name
|
|
| 360 | + |
|
| 361 | +-- | Search for @mod_name@ among the home units: first the current home unit,
|
|
| 362 | +-- then the home units it depends on, in priority order, following module
|
|
| 363 | +-- reexports along the way (see 'findHomeUnitDepModule'). Yields the first
|
|
| 364 | +-- successful result.
|
|
| 365 | +findHomeModuleAmongDeps
|
|
| 366 | + :: FinderCache
|
|
| 367 | + -> FinderOpts
|
|
| 368 | + -> UnitEnv
|
|
| 369 | + -> HomeModuleNameProvidersMap
|
|
| 370 | + -> Maybe HomeUnit
|
|
| 371 | + -> ModuleName
|
|
| 372 | + -> IO FindResult
|
|
| 373 | +findHomeModuleAmongDeps fc fopts ue home_module_name_providers_map mb_home_unit mod_name =
|
|
| 374 | + foldr1 orIfNotFound (home_import :| map home_pkg_import other_fopts)
|
|
| 375 | + -- Do not try to be smart and change this to `foldr orIfNotFound home_import
|
|
| 376 | + -- (map home_pkg_import other_fopts)`, as that would not be the same.
|
|
| 377 | + -- `home_import` is first because we need to first look within the current
|
|
| 378 | + -- unit before looking at the other units in order.
|
|
| 379 | + where
|
|
| 380 | + home_import = case mb_home_unit of
|
|
| 381 | + Just home_unit -> findHomeModule fc fopts home_unit mod_name
|
|
| 382 | + Nothing -> pure $
|
|
| 383 | + NoPackage (panic "findHomeModuleAmongDeps: no home-unit")
|
|
| 384 | + home_pkg_import = findHomeUnitDepModule fc ue home_module_name_providers_map mod_name
|
|
| 337 | 385 | |
| 338 | -findPluginModule :: HscEnv -> ModuleName -> IO FindResult
|
|
| 339 | -findPluginModule hsc_env mod_name = do
|
|
| 340 | - let fc = hsc_FC hsc_env
|
|
| 341 | - let units = hsc_units hsc_env
|
|
| 342 | - let mb_home_unit = hsc_home_unit_maybe hsc_env
|
|
| 343 | - findPluginModuleNoHsc fc (initFinderOpts (hsc_dflags hsc_env)) units mb_home_unit mod_name
|
|
| 386 | + unit_state = case homeUnitId <$> mb_home_unit of
|
|
| 387 | + Nothing -> ue_homeUnitState ue
|
|
| 388 | + Just home_unit_id -> HUG.homeUnitEnv_units $
|
|
| 389 | + ue_findHomeUnitEnv home_unit_id ue
|
|
| 390 | + other_fopts = homeUnitDepsFinderOpts ue home_module_name_providers_map
|
|
| 391 | + unit_state mod_name
|
|
| 392 | + |
|
| 393 | +-- | Search the home-unit graph and otherwise the regular exposed package
|
|
| 394 | +-- database.
|
|
| 395 | +findHomeOrRegularPackageModule
|
|
| 396 | + :: FinderCache
|
|
| 397 | + -> FinderOpts
|
|
| 398 | + -> UnitEnv
|
|
| 399 | + -> HomeModuleNameProvidersMap
|
|
| 400 | + -> Maybe HomeUnit
|
|
| 401 | + -> ModuleName
|
|
| 402 | + -> IO FindResult
|
|
| 403 | +findHomeOrRegularPackageModule fc fopts ue home_module_name_providers_map mb_home_unit mod_name =
|
|
| 404 | + findHomeModuleAmongDeps fc fopts ue home_module_name_providers_map
|
|
| 405 | + mb_home_unit mod_name
|
|
| 406 | + `orIfNotFound`
|
|
| 407 | + findExposedPackageModule fc fopts unit_state mod_name NoPkgQual
|
|
| 408 | + where
|
|
| 409 | + unit_state = case homeUnitId <$> mb_home_unit of
|
|
| 410 | + Nothing -> ue_homeUnitState ue
|
|
| 411 | + Just home_unit_id -> HUG.homeUnitEnv_units $
|
|
| 412 | + ue_findHomeUnitEnv home_unit_id ue
|
|
| 344 | 413 | |
| 345 | 414 | |
| 346 | 415 | -- | A version of findExactModule which takes the exact parts of the HscEnv it needs
|
| ... | ... | @@ -108,7 +108,7 @@ dataConCantHappen x = case x of {} |
| 108 | 108 | -- See Note [XRec and SrcSpans in the AST]
|
| 109 | 109 | type family XRec p a = r | r -> a
|
| 110 | 110 | |
| 111 | -type family Anno a = b -- See Note [XRec and Anno in the AST] in GHC.Parser.Annotation
|
|
| 111 | +type family Anno a -- See Note [XRec and Anno in the AST] in GHC.Parser.Annotation
|
|
| 112 | 112 | |
| 113 | 113 | {-
|
| 114 | 114 | Note [XRec and SrcSpans in the AST]
|
| ... | ... | @@ -25,7 +25,7 @@ buildGhcInternalImportDef target = do |
| 25 | 25 | |
| 26 | 26 | buildGhcInternalImportLib :: FilePath -> Action ()
|
| 27 | 27 | buildGhcInternalImportLib target = do
|
| 28 | - let input = dropExtensions target <.> "def" -- the .def file
|
|
| 28 | + let input = dropExtension (dropExtension target) <.> "def" -- the .def file
|
|
| 29 | 29 | output = target -- the .dll.a import lib
|
| 30 | 30 | need [input]
|
| 31 | 31 | runBuilder Dlltool ["-d", input, "-l", output] [input] [output] |
| 1 | +# A plugin (MyPlugin, in home unit plugin-0) is enabled by a module (App, in
|
|
| 2 | +# home unit app-0) belonging to a *different* home unit in the same session.
|
|
| 3 | +# Resolving -fplugin must search sibling home units; previously the plugin
|
|
| 4 | +# finder only looked at the current home unit and registered external packages,
|
|
| 5 | +# so this failed with "Could not load module 'MyPlugin' ... hidden package".
|
|
| 6 | +#
|
|
| 7 | +# -fbyte-code-and-object-code -fprefer-byte-code makes the plugin load as
|
|
| 8 | +# byte-code from its (interpreted) home unit, mirroring how a multiple-home-unit
|
|
| 9 | +# session is driven by 'cabal repl --enable-multi-repl' and HLS.
|
|
| 10 | +test('multipleHomeUnits_plugin01',
|
|
| 11 | + [req_plugins, extra_files(['p/', 'q/', 'pluginunit', 'appunit'])],
|
|
| 12 | + multiunit_compile,
|
|
| 13 | + [['pluginunit', 'appunit'],
|
|
| 14 | + '-v0 -fbyte-code-and-object-code -fprefer-byte-code']) |
| 1 | +-working-dir q App -this-unit-id app-0 -this-package-name app -package-id plugin-0 |
| 1 | +module MyPlugin (plugin) where
|
|
| 2 | + |
|
| 3 | +import GHC.Plugins
|
|
| 4 | + |
|
| 5 | +-- A no-op plugin: it makes no changes to the program but, to run at all, it
|
|
| 6 | +-- must be found and loaded by the consumer module's compilation.
|
|
| 7 | +plugin :: Plugin
|
|
| 8 | +plugin = defaultPlugin { pluginRecompile = purePlugin } |
| 1 | +-working-dir p MyPlugin -this-unit-id plugin-0 -this-package-name plugin -package ghc |
| 1 | +{-# OPTIONS_GHC -fplugin=MyPlugin #-}
|
|
| 2 | +module App where
|
|
| 3 | + |
|
| 4 | +-- The plugin 'MyPlugin' lives in a *sibling* home unit (plugin-0), not in a
|
|
| 5 | +-- registered package. Resolving -fplugin must therefore search sibling home
|
|
| 6 | +-- units, just like an ordinary import does.
|
|
| 7 | +app :: ()
|
|
| 8 | +app = () |
| 1 | +# A plugin (MyPlugin) lives in home unit plugin-0 and is *reexported* by a
|
|
| 2 | +# second home unit, reexport-0 (via -reexported-module). The consumer module
|
|
| 3 | +# App, in home unit app-0, enables it with -fplugin=MyPlugin but depends only on
|
|
| 4 | +# reexport-0, not on plugin-0 directly. Resolving -fplugin must therefore follow
|
|
| 5 | +# the reexport through the sibling home unit, exactly as an ordinary import
|
|
| 6 | +# does. A home-unit search that ignores reexported-modules fails with
|
|
| 7 | +# "Could not load module 'MyPlugin' ... hidden package".
|
|
| 8 | +#
|
|
| 9 | +# -fbyte-code-and-object-code -fprefer-byte-code makes the plugin load as
|
|
| 10 | +# byte-code from its (interpreted) home unit, mirroring how a multiple-home-unit
|
|
| 11 | +# session is driven by 'cabal repl --enable-multi-repl' and HLS.
|
|
| 12 | +test('multipleHomeUnits_plugin02',
|
|
| 13 | + [req_plugins, extra_files(['p/', 'q/', 'r/', 'pluginunit', 'reexportunit', 'appunit'])],
|
|
| 14 | + multiunit_compile,
|
|
| 15 | + [['pluginunit', 'reexportunit', 'appunit'],
|
|
| 16 | + '-v0 -fbyte-code-and-object-code -fprefer-byte-code']) |
| 1 | +-working-dir q App -this-unit-id app-0 -this-package-name app -package-id reexport-0 |
| 1 | +module MyPlugin (plugin) where
|
|
| 2 | + |
|
| 3 | +import GHC.Plugins
|
|
| 4 | + |
|
| 5 | +-- A no-op plugin: it makes no changes to the program but, to run at all, it
|
|
| 6 | +-- must be found and loaded by the consumer module's compilation.
|
|
| 7 | +plugin :: Plugin
|
|
| 8 | +plugin = defaultPlugin { pluginRecompile = purePlugin } |
| 1 | +-working-dir p MyPlugin -this-unit-id plugin-0 -this-package-name plugin -package ghc |
| 1 | +{-# OPTIONS_GHC -fplugin=MyPlugin #-}
|
|
| 2 | +module App where
|
|
| 3 | + |
|
| 4 | +-- The plugin 'MyPlugin' lives in home unit plugin-0, but this unit (app-0)
|
|
| 5 | +-- depends only on reexport-0, which *reexports* MyPlugin (it does not contain
|
|
| 6 | +-- MyPlugin itself). Resolving -fplugin must therefore follow the reexport into
|
|
| 7 | +-- the sibling home unit, exactly as an ordinary import does.
|
|
| 8 | +app :: ()
|
|
| 9 | +app = () |
| 1 | +module RexLib where
|
|
| 2 | + |
|
| 3 | +-- Home unit reexport-0 re-exports MyPlugin (from plugin-0) via the
|
|
| 4 | +-- -reexported-module flag; see the 'reexportunit' arguments. This module exists
|
|
| 5 | +-- only to make reexport-0 a non-empty home unit, mirroring a real library
|
|
| 6 | +-- package that reexports a module from one of its dependencies.
|
|
| 7 | +rexLib :: ()
|
|
| 8 | +rexLib = () |
| 1 | +-working-dir r RexLib -this-unit-id reexport-0 -this-package-name reexport -package-id plugin-0 -reexported-module MyPlugin |