Skip to content

Commit

Permalink
Cabal uses main as the unit id of all executable packages. This con…
Browse files Browse the repository at this point in the history
…fused multi component sessions.

Solution: include the hash of the options in the unit id when the unit id is called "main".

Fixes #3513
  • Loading branch information
wz1000 committed Jul 26, 2023
1 parent ca638bd commit fda63c5
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 12 deletions.
20 changes: 19 additions & 1 deletion ghcide/session-loader/Development/IDE/Session.hs
Original file line number Diff line number Diff line change
Expand Up @@ -484,7 +484,24 @@ loadSessionWithOptions recorder SessionLoadingOptions{..} dir = do
packageSetup (hieYaml, cfp, opts, libDir) = do
-- Parse DynFlags for the newly discovered component
hscEnv <- emptyHscEnv ideNc libDir
(df, targets) <- evalGhcEnv hscEnv $ setOptions opts (hsc_dflags hscEnv)
(df', targets) <- evalGhcEnv hscEnv $ setOptions opts (hsc_dflags hscEnv)
let df =
#if MIN_VERSION_ghc(9,3,0)
case unitIdString (homeUnitId_ df') of
-- cabal uses main for the unit id of all executable packages
-- This makes multi-component sessions confused about what
-- options to use for that component.
-- Solution: hash the options and use that as part of the unit id
-- This works because there won't be any dependencies on the
-- executable unit.
"main" ->
let hash = B.unpack $ B16.encode $ H.finalize $ H.updates H.init (map B.pack $ componentOptions opts)
hashed_uid = Compat.toUnitId (Compat.stringToUnit ("main-"++hash))
in setHomeUnitId_ hashed_uid df'
#else
df'
#endif

let deps = componentDependencies opts ++ maybeToList hieYaml
dep_info <- getDependencyInfo deps
-- Now lookup to see whether we are combining with an existing HscEnv
Expand All @@ -499,6 +516,7 @@ loadSessionWithOptions recorder SessionLoadingOptions{..} dir = do
-- We will modify the unitId and DynFlags used for
-- compilation but these are the true source of
-- information.

new_deps = RawComponentInfo (homeUnitId_ df) df targets cfp opts dep_info
: maybe [] snd oldDeps
-- Get all the unit-ids for things in this component
Expand Down
23 changes: 12 additions & 11 deletions ghcide/src/Development/IDE/Import/FindImports.hs
Original file line number Diff line number Diff line change
Expand Up @@ -136,17 +136,6 @@ locateModule env comp_info exts targetFor modName mbPkgName isSource = do
#else
Nothing -> do
#endif
-- first try to find the module as a file. If we can't find it try to find it in the package
-- database.
-- Here the importPaths for the current modules are added to the front of the import paths from the other components.
-- This is particularly important for Paths_* modules which get generated for every component but unless you use it in
-- each component will end up being found in the wrong place and cause a multi-cradle match failure.
let import_paths' =
#if MIN_VERSION_ghc(9,3,0)
import_paths
#else
map snd import_paths
#endif

mbFile <- locateModuleFile ((homeUnitId_ dflags, importPaths dflags) : other_imports) exts targetFor isSource $ unLoc modName
case mbFile of
Expand Down Expand Up @@ -174,6 +163,18 @@ locateModule env comp_info exts targetFor modName mbPkgName isSource = do
import_paths'
#endif

-- first try to find the module as a file. If we can't find it try to find it in the package
-- database.
-- Here the importPaths for the current modules are added to the front of the import paths from the other components.
-- This is particularly important for Paths_* modules which get generated for every component but unless you use it in
-- each component will end up being found in the wrong place and cause a multi-cradle match failure.
import_paths' =
#if MIN_VERSION_ghc(9,3,0)
import_paths
#else
map snd import_paths
#endif

toModLocation uid file = liftIO $ do
loc <- mkHomeModLocation dflags (unLoc modName) (fromNormalizedFilePath file)
#if MIN_VERSION_ghc(9,0,0)
Expand Down

0 comments on commit fda63c5

Please sign in to comment.