mirror of
https://github.com/haskell/ghcide.git
synced 2024-12-11 15:37:02 +03:00
Local hidir and hiedir folders to avoid conflicts with Cabal (#441)
* Local hidir and hiedir folders to avoid conflicts with Cabal hi files created by ghcide would have different optimization settings, triggering Cabal recompilation if they were stored in Cabal folders hie files would end up in the src folder as -hiedir is not set by Cabal Telling GHC to write interface/hie files is pointless since we do it ourselves, and it also leads to the recompilation checker getting confused Using hie-bios initSession does things like setting up the cache directory for interface files and other things which ghcide would rather manage itself. * linker options Co-authored-by: Matthew Pickering <matthewtpickering@gmail.com>
This commit is contained in:
parent
5bea92f9d3
commit
48a7867a07
56
exe/Main.hs
56
exe/Main.hs
@ -19,6 +19,9 @@ import Control.DeepSeq (NFData)
|
||||
import Control.Exception
|
||||
import Control.Monad.Extra
|
||||
import Control.Monad.IO.Class
|
||||
import qualified Crypto.Hash.SHA1 as H
|
||||
import qualified Data.ByteString.Char8 as B
|
||||
import Data.ByteString.Base16
|
||||
import Data.Default
|
||||
import System.Time.Extra
|
||||
import Development.IDE.Core.Debouncer
|
||||
@ -57,15 +60,28 @@ import qualified Data.Map.Strict as Map
|
||||
import GHC hiding (def)
|
||||
import GHC.Generics (Generic)
|
||||
import qualified GHC.Paths
|
||||
import DynFlags
|
||||
|
||||
import HIE.Bios.Environment
|
||||
import HIE.Bios
|
||||
import HIE.Bios.Cradle
|
||||
import HIE.Bios.Types
|
||||
|
||||
-- Prefix for the cache path
|
||||
cacheDir :: String
|
||||
cacheDir = "ghcide"
|
||||
|
||||
-- Set the GHC libdir to the nix libdir if it's present.
|
||||
getLibdir :: IO FilePath
|
||||
getLibdir = fromMaybe GHC.Paths.libdir <$> lookupEnv "NIX_GHC_LIBDIR"
|
||||
|
||||
getCacheDir :: [String] -> IO FilePath
|
||||
getCacheDir opts = IO.getXdgDirectory IO.XdgCache (cacheDir </> opts_hash)
|
||||
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 $ encode $ H.finalize $ H.updates H.init (map B.pack opts)
|
||||
|
||||
ghcideVersion :: IO String
|
||||
ghcideVersion = do
|
||||
path <- getExecutablePath
|
||||
@ -224,14 +240,50 @@ getComponentOptions cradle = do
|
||||
|
||||
|
||||
createSession :: ComponentOptions -> IO HscEnvEq
|
||||
createSession opts = do
|
||||
createSession (ComponentOptions theOpts _) = do
|
||||
libdir <- getLibdir
|
||||
|
||||
cacheDir <- Main.getCacheDir theOpts
|
||||
|
||||
env <- runGhc (Just libdir) $ do
|
||||
_targets <- initSession opts
|
||||
dflags <- getSessionDynFlags
|
||||
(dflags', _targets) <- addCmdOpts theOpts dflags
|
||||
_ <- setSessionDynFlags $
|
||||
-- disabled, generated directly by ghcide instead
|
||||
flip gopt_unset Opt_WriteInterface $
|
||||
-- disabled, generated directly by ghcide instead
|
||||
-- also, it can confuse the interface stale check
|
||||
dontWriteHieFiles $
|
||||
setHiDir cacheDir $
|
||||
setDefaultHieDir cacheDir $
|
||||
setIgnoreInterfacePragmas $
|
||||
setLinkerOptions $
|
||||
disableOptimisation dflags'
|
||||
getSession
|
||||
initDynLinker env
|
||||
newHscEnvEq env
|
||||
|
||||
-- we don't want to generate object code so we compile to bytecode
|
||||
-- (HscInterpreted) which implies LinkInMemory
|
||||
-- HscInterpreted
|
||||
setLinkerOptions :: DynFlags -> DynFlags
|
||||
setLinkerOptions df = df {
|
||||
ghcLink = LinkInMemory
|
||||
, hscTarget = HscNothing
|
||||
, ghcMode = CompManager
|
||||
}
|
||||
|
||||
setIgnoreInterfacePragmas :: DynFlags -> DynFlags
|
||||
setIgnoreInterfacePragmas df =
|
||||
gopt_set (gopt_set df Opt_IgnoreInterfacePragmas) Opt_IgnoreOptimChanges
|
||||
|
||||
disableOptimisation :: DynFlags -> DynFlags
|
||||
disableOptimisation df = updOptLevel 0 df
|
||||
|
||||
setHiDir :: FilePath -> DynFlags -> DynFlags
|
||||
setHiDir f d =
|
||||
-- override user settings to avoid conflicts leading to recompilation
|
||||
d { hiDir = Just f}
|
||||
|
||||
cradleToSession :: Maybe FilePath -> Cradle a -> Action HscEnvEq
|
||||
cradleToSession mbYaml cradle = do
|
||||
|
@ -171,7 +171,10 @@ executable ghcide
|
||||
hslogger,
|
||||
base == 4.*,
|
||||
binary,
|
||||
base16-bytestring >=0.1.1 && <0.2,
|
||||
bytestring,
|
||||
containers,
|
||||
cryptohash-sha1 >=0.11.100 && <0.12,
|
||||
data-default,
|
||||
deepseq,
|
||||
directory,
|
||||
|
@ -12,6 +12,8 @@ module Development.IDE.GHC.Compat(
|
||||
mkHieFile,
|
||||
writeHieFile,
|
||||
readHieFile,
|
||||
setDefaultHieDir,
|
||||
dontWriteHieFiles,
|
||||
hPutStringBuffer,
|
||||
includePathsGlobal,
|
||||
includePathsQuote,
|
||||
@ -156,3 +158,19 @@ pattern IEThingAll a <-
|
||||
#else
|
||||
GHC.IEThingAll a
|
||||
#endif
|
||||
|
||||
setDefaultHieDir :: FilePath -> DynFlags -> DynFlags
|
||||
setDefaultHieDir _f d =
|
||||
#if MIN_GHC_API_VERSION(8,8,0)
|
||||
d { hieDir = hieDir d `mappend` Just _f}
|
||||
#else
|
||||
d
|
||||
#endif
|
||||
|
||||
dontWriteHieFiles :: DynFlags -> DynFlags
|
||||
dontWriteHieFiles d =
|
||||
#if MIN_GHC_API_VERSION(8,8,0)
|
||||
gopt_unset d Opt_WriteHie
|
||||
#else
|
||||
d
|
||||
#endif
|
||||
|
@ -19,6 +19,8 @@ module Development.IDE.GHC.Util(
|
||||
textToStringBuffer,
|
||||
readFileUtf8,
|
||||
hDuplicateTo',
|
||||
setDefaultHieDir,
|
||||
dontWriteHieFiles
|
||||
) where
|
||||
|
||||
import Control.Concurrent
|
||||
@ -27,7 +29,6 @@ import Data.Maybe
|
||||
import Data.Typeable
|
||||
import qualified Data.ByteString.Internal as BS
|
||||
import Fingerprint
|
||||
import GHC
|
||||
import GhcMonad
|
||||
import GhcPlugins hiding (Unique)
|
||||
import Data.IORef
|
||||
@ -52,6 +53,7 @@ import Lexer
|
||||
import StringBuffer
|
||||
import System.FilePath
|
||||
|
||||
import Development.IDE.GHC.Compat as GHC
|
||||
import Development.IDE.Types.Location
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user