@@ -56,6 +56,7 @@ import Development.IDE.Types.HscEnvEq (HscEnvEq)
5656import Development.IDE.Types.Location
5757import Development.IDE.Types.Options
5858import qualified HIE.Bios as HieBios
59+ import qualified HIE.Bios.Cradle.Utils as HieBios
5960import HIE.Bios.Environment hiding (getCacheDir )
6061import HIE.Bios.Types hiding (Log )
6162import qualified HIE.Bios.Types as HieBios
@@ -1023,6 +1024,121 @@ memoIO op = do
10231024 return (Map. insert k res mp, res)
10241025 Just res -> return (mp, res)
10251026
1027+ unit_flags :: [Flag (CmdLineP [String ])]
1028+ unit_flags = [defFlag " unit" (SepArg addUnit)]
1029+
1030+ addUnit :: String -> EwM (CmdLineP [String ]) ()
1031+ addUnit unit_str = liftEwM $ do
1032+ units <- getCmdLineState
1033+ putCmdLineState (unit_str : units)
1034+
1035+ -- | Throws if package flags are unsatisfiable
1036+ setOptions :: GhcMonad m
1037+ => NormalizedFilePath
1038+ -> ComponentOptions
1039+ -> DynFlags
1040+ -> FilePath -- ^ root dir, see Note [Root Directory]
1041+ -> m (NonEmpty (DynFlags , [GHC. Target ]))
1042+ setOptions cfp (ComponentOptions theOpts compRoot _) dflags rootDir = do
1043+ ((theOpts',_errs,_warns),units) <- processCmdLineP unit_flags [] (map noLoc theOpts)
1044+ case NE. nonEmpty units of
1045+ Just us -> initMulti us
1046+ Nothing -> do
1047+ (df, targets) <- initOne (map unLoc theOpts')
1048+ -- A special target for the file which caused this wonderful
1049+ -- component to be created. In case the cradle doesn't list all the targets for
1050+ -- the component, in which case things will be horribly broken anyway.
1051+ --
1052+ -- When we have a singleComponent that is caused to be loaded due to a
1053+ -- file, we assume the file is part of that component. This is useful
1054+ -- for bare GHC sessions, such as many of the ones used in the testsuite
1055+ --
1056+ -- We don't do this when we have multiple components, because each
1057+ -- component better list all targets or there will be anarchy.
1058+ -- It is difficult to know which component to add our file to in
1059+ -- that case.
1060+ -- Multi unit arguments are likely to come from cabal, which
1061+ -- does list all targets.
1062+ --
1063+ -- If we don't end up with a target for the current file in the end, then
1064+ -- we will report it as an error for that file
1065+ let abs_fp = toAbsolute rootDir (fromNormalizedFilePath cfp)
1066+ let special_target = Compat. mkSimpleTarget df abs_fp
1067+ pure $ (df, special_target : targets) :| []
1068+ where
1069+ initMulti unitArgFiles =
1070+ forM unitArgFiles $ \ f -> do
1071+ args <- liftIO $ expandResponse [f]
1072+ -- The reponse files may contain arguments like "+RTS",
1073+ -- and hie-bios doesn't expand the response files of @-unit@ arguments.
1074+ -- Thus, we need to do the stripping here.
1075+ initOne $ HieBios. removeRTS $ HieBios. removeVerbosityOpts args
1076+ initOne this_opts = do
1077+ (dflags', targets') <- addCmdOpts this_opts dflags
1078+ let dflags'' =
1079+ case unitIdString (homeUnitId_ dflags') of
1080+ -- cabal uses main for the unit id of all executable packages
1081+ -- This makes multi-component sessions confused about what
1082+ -- options to use for that component.
1083+ -- Solution: hash the options and use that as part of the unit id
1084+ -- This works because there won't be any dependencies on the
1085+ -- executable unit.
1086+ " main" ->
1087+ let hash = B. unpack $ B16. encode $ H. finalize $ H. updates H. init (map B. pack this_opts)
1088+ hashed_uid = Compat. toUnitId (Compat. stringToUnit (" main-" ++ hash))
1089+ in setHomeUnitId_ hashed_uid dflags'
1090+ _ -> dflags'
1091+
1092+ let targets = makeTargetsAbsolute root targets'
1093+ root = case workingDirectory dflags'' of
1094+ Nothing -> compRoot
1095+ Just wdir -> compRoot </> wdir
1096+ let dflags''' =
1097+ setWorkingDirectory root $
1098+ disableWarningsAsErrors $
1099+ -- disabled, generated directly by ghcide instead
1100+ flip gopt_unset Opt_WriteInterface $
1101+ -- disabled, generated directly by ghcide instead
1102+ -- also, it can confuse the interface stale check
1103+ dontWriteHieFiles $
1104+ setIgnoreInterfacePragmas $
1105+ setBytecodeLinkerOptions $
1106+ disableOptimisation $
1107+ Compat. setUpTypedHoles $
1108+ makeDynFlagsAbsolute compRoot -- makeDynFlagsAbsolute already accounts for workingDirectory
1109+ dflags''
1110+ return (dflags''', targets)
1111+
1112+ setIgnoreInterfacePragmas :: DynFlags -> DynFlags
1113+ setIgnoreInterfacePragmas df =
1114+ gopt_set (gopt_set df Opt_IgnoreInterfacePragmas ) Opt_IgnoreOptimChanges
1115+
1116+ disableOptimisation :: DynFlags -> DynFlags
1117+ disableOptimisation df = updOptLevel 0 df
1118+
1119+ setHiDir :: FilePath -> DynFlags -> DynFlags
1120+ setHiDir f d =
1121+ -- override user settings to avoid conflicts leading to recompilation
1122+ d { hiDir = Just f}
1123+
1124+ setODir :: FilePath -> DynFlags -> DynFlags
1125+ setODir f d =
1126+ -- override user settings to avoid conflicts leading to recompilation
1127+ d { objectDir = Just f}
1128+
1129+ getCacheDirsDefault :: String -> [String ] -> IO CacheDirs
1130+ getCacheDirsDefault prefix opts = do
1131+ dir <- Just <$> getXdgDirectory XdgCache (cacheDir </> prefix ++ " -" ++ opts_hash)
1132+ return $ CacheDirs dir dir dir
1133+ where
1134+ -- Create a unique folder per set of different GHC options, assuming that each different set of
1135+ -- GHC options will create incompatible interface files.
1136+ opts_hash = B. unpack $ B16. encode $ H. finalize $ H. updates H. init (map B. pack opts)
1137+
1138+ -- | Sub directory for the cache path
1139+ cacheDir :: String
1140+ cacheDir = " ghcide"
1141+
10261142----------------------------------------------------------------------------------------------------
10271143
10281144data PackageSetupException
0 commit comments