-
-
Notifications
You must be signed in to change notification settings - Fork 441
Fixes redundant hash in ghcide cache path (getCacheDirsDefault) #4854
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
5 commits
Select commit
Hold shift + click to select a range
cfea9dd
* I updated the setOptions function so it now also returns the genera…
adpad-13 c0a1062
Updated Ghc.hs for the hashing logic as the hashing logic was moved t…
adpad-13 62e878c
Updated Ghc.hs for the hashing logic as the hashing logic was moved t…
adpad-13 c61dc27
Add haddock documentation and fix spacing
adpad-13 9240858
Update ghcide/session-loader/Development/IDE/Session/Ghc.hs
adpad-13 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Some comments aren't visible on the classic Files Changed page.
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,4 +1,4 @@ | ||
| {-# LANGUAGE CPP #-} | ||
|
Check warning on line 1 in ghcide/session-loader/Development/IDE/Session/Ghc.hs
|
||
| module Development.IDE.Session.Ghc where | ||
|
|
||
| import Control.Monad | ||
|
|
@@ -58,6 +58,7 @@ | |
| singleMessage) | ||
| import GHC.Unit.State | ||
|
|
||
|
|
||
| #if MIN_VERSION_ghc(9,13,0) | ||
| import GHC.Driver.Make (checkHomeUnitsClosed) | ||
| #endif | ||
|
|
@@ -79,7 +80,18 @@ | |
| "New component cache HscEnvEq:" <+> viaShow componentCache | ||
| LogDLLLoadError errorString -> | ||
| "Error dynamically loading libm.so.6:" <+> pretty errorString | ||
|
|
||
| -- | Configuration info for a particular home unit. | ||
| data HomeUnitConfig = HomeUnitConfig | ||
| { | ||
| -- | The dynamic flags to compile this specific unit. | ||
| homeUnitDynFlags :: DynFlags | ||
| -- | All the targets for this unit. | ||
| , homeUnitTargets :: [GHC.Target] | ||
| -- | Optional hash seed to differentiate home units | ||
| -- with same `-this-unit-id`. Used when `-this-unit-id` is "main", | ||
| -- which is common when loading a single target. | ||
| , homeUnitHash :: Maybe B.ByteString | ||
| } | ||
| -- This is pristine information about a component | ||
| data RawComponentInfo = RawComponentInfo | ||
| { rawComponentUnitId :: UnitId | ||
|
|
@@ -95,6 +107,8 @@ | |
| -- | Maps cradle dependencies, such as `stack.yaml`, or `.cabal` file | ||
| -- to last modification time. See Note [Multi Cradle Dependency Info]. | ||
| , rawComponentDependencyInfo :: DependencyInfo | ||
| -- | An optional hash seed generated in 'setOptions' for the unit id "main". | ||
| , rawComponentHash :: Maybe B.ByteString | ||
| } | ||
|
|
||
| -- This is processed information about the component, in particular the dynflags will be modified. | ||
|
|
@@ -209,13 +223,13 @@ | |
| -> ComponentOptions | ||
| -> DynFlags | ||
| -> FilePath -- ^ root dir, see Note [Root Directory] | ||
| -> m (NonEmpty (DynFlags, [GHC.Target])) | ||
| -> m (NonEmpty HomeUnitConfig) | ||
| setOptions haddockOpt cfp (ComponentOptions theOpts compRoot _) dflags rootDir = do | ||
| ((theOpts',_errs,_warns),units) <- processCmdLineP unit_flags [] (map noLoc theOpts) | ||
| case NE.nonEmpty units of | ||
| Just us -> initMulti us | ||
| Nothing -> do | ||
| (df, targets) <- initOne (map unLoc theOpts') | ||
| (HomeUnitConfig df targets mHash) <- initOne (map unLoc theOpts') | ||
| -- A special target for the file which caused this wonderful | ||
| -- component to be created. In case the cradle doesn't list all the targets for | ||
| -- the component, in which case things will be horribly broken anyway. | ||
|
|
@@ -235,7 +249,7 @@ | |
| -- we will report it as an error for that file | ||
| let abs_fp = toAbsolute rootDir (fromNormalizedFilePath cfp) | ||
| let special_target = Compat.mkSimpleTarget df abs_fp | ||
| pure $ (df, special_target : targets) :| [] | ||
| pure $ HomeUnitConfig df (special_target : targets) mHash :| [] | ||
| where | ||
| initMulti unitArgFiles = | ||
| forM unitArgFiles $ \f -> do | ||
|
|
@@ -246,7 +260,7 @@ | |
| initOne $ HieBios.removeRTS $ HieBios.removeVerbosityOpts args | ||
| initOne this_opts = do | ||
| (dflags', targets') <- addCmdOpts this_opts dflags | ||
| let dflags'' = | ||
| let (dflags'',mHash) = | ||
| case unitIdString (homeUnitId_ dflags') of | ||
| -- cabal uses main for the unit id of all executable packages | ||
| -- This makes multi-component sessions confused about what | ||
|
|
@@ -255,10 +269,11 @@ | |
| -- 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 this_opts) | ||
| let hashBytes =H.finalize $ H.updates H.init (map B.pack this_opts) | ||
| hash = B.unpack $ B16.encode hashBytes | ||
| hashed_uid = Compat.toUnitId (Compat.stringToUnit ("main-"++hash)) | ||
| in setHomeUnitId_ hashed_uid dflags' | ||
| _ -> dflags' | ||
| in (setHomeUnitId_ hashed_uid dflags', Just hashBytes) | ||
| _ -> (dflags', Nothing) | ||
|
|
||
| let targets = makeTargetsAbsolute root targets' | ||
| root = case workingDirectory dflags'' of | ||
|
|
@@ -279,14 +294,14 @@ | |
| Compat.setUpTypedHoles $ | ||
| makeDynFlagsAbsolute compRoot -- makeDynFlagsAbsolute already accounts for workingDirectory | ||
| dflags'' | ||
| return (dflags''', targets) | ||
| return (HomeUnitConfig dflags''' targets mHash) | ||
|
|
||
| addComponentInfo :: | ||
| MonadUnliftIO m => | ||
| Recorder (WithPriority Log) -> | ||
| (String -> [String] -> IO CacheDirs) -> | ||
| (String -> Maybe B.ByteString -> [String] -> IO CacheDirs) -> | ||
| DependencyInfo -> | ||
| NonEmpty (DynFlags, [GHC.Target]) -> | ||
| NonEmpty HomeUnitConfig-> | ||
| (Maybe FilePath, NormalizedFilePath, ComponentOptions) -> | ||
| Map.Map (Maybe FilePath) [RawComponentInfo] -> | ||
| m (Map.Map (Maybe FilePath) [RawComponentInfo], ([ComponentInfo], [ComponentInfo])) | ||
|
|
@@ -298,15 +313,15 @@ | |
| -- We will modify the unitId and DynFlags used for | ||
| -- compilation but these are the true source of | ||
| -- information. | ||
| new_deps = fmap (\(df, targets) -> RawComponentInfo (homeUnitId_ df) df targets cfp opts dep_info) newDynFlags | ||
| new_deps = fmap (\(HomeUnitConfig df targets mHash) -> RawComponentInfo (homeUnitId_ df) df targets cfp opts dep_info mHash) newDynFlags | ||
| all_deps = new_deps `NE.appendList` fromMaybe [] oldDeps | ||
| -- Get all the unit-ids for things in this component | ||
|
|
||
| all_deps' <- forM all_deps $ \RawComponentInfo{..} -> do | ||
| let prefix = show rawComponentUnitId | ||
| -- See Note [Avoiding bad interface files] | ||
| let cacheDirOpts = componentOptions opts | ||
| cacheDirs <- liftIO $ getCacheDirs prefix cacheDirOpts | ||
| cacheDirs <- liftIO $ getCacheDirs prefix rawComponentHash cacheDirOpts | ||
| processed_df <- setCacheDirs recorder cacheDirs rawComponentDynFlags | ||
| -- The final component information, mostly the same but the DynFlags don't | ||
| -- contain any packages which are also loaded | ||
|
|
@@ -422,14 +437,28 @@ | |
| & maybe id setHieDir hieCacheDir | ||
| & maybe id setODir oCacheDir | ||
|
|
||
| getCacheDirsDefault :: String -> [String] -> IO CacheDirs | ||
| getCacheDirsDefault prefix opts = do | ||
| dir <- Just <$> getXdgDirectory XdgCache (cacheDir </> prefix ++ "-" ++ opts_hash) | ||
| -- | Append the hash to the unit id to create unique cache folders. | ||
| -- | ||
| -- This function generates a single, unified hash. | ||
| -- If an optional base hash (@mFirstHash@) is provided—which | ||
| -- is common for a single target with `-this-unit-id` as "main"- | ||
| -- we set the prefix to "main", extract the context generated | ||
| -- from the @mFirstHash@, and update the @opts@ into the same hash. | ||
| -- | ||
| -- This guarantees a unique cache folder for different GHC | ||
| -- options(avoiding incompatible interface files) while | ||
| -- keeping the path short and clean. | ||
| getCacheDirsDefault :: String -> Maybe B.ByteString -> [String] -> IO CacheDirs | ||
| getCacheDirsDefault prefix mFirstHash opts = do | ||
|
Comment on lines
+451
to
+452
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As this function got more complicated, let's give it some proper haddock docs! |
||
| dir <- Just <$> getXdgDirectory XdgCache (cacheDir </> prefix' ++ "-" ++ opts_hash) | ||
| return $ CacheDirs dir dir dir | ||
| where | ||
| -- Create a unique folder per set of different GHC options, assuming that each different set of | ||
| -- GHC options will create incompatible interface files. | ||
| opts_hash = B.unpack $ B16.encode $ H.finalize $ H.updates H.init (map B.pack opts) | ||
| -- Create a unique folder per set of different GHC options. | ||
| prefix' = if isJust mFirstHash then "main" else prefix | ||
| basectx = case mFirstHash of | ||
| Just h -> H.updates H.init [h] | ||
| Nothing -> H.init | ||
| opts_hash = B.unpack $ B16.encode $ H.finalize $ H.updates basectx (map B.pack opts) | ||
|
|
||
| setNameCache :: NameCache -> HscEnv -> HscEnv | ||
| setNameCache nc hsc = hsc { hsc_NC = nc } | ||
|
|
||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.