@@ -15,10 +15,6 @@ module Stack.Ghci
1515 , GhciPkgInfo (.. )
1616 , GhciException (.. )
1717 , ghci
18-
19- -- TODO: Address what should and should not be exported.
20- , renderScriptGhci
21- , renderScriptIntero
2218 ) where
2319
2420import Stack.Prelude
@@ -72,6 +68,7 @@ data GhciOpts = GhciOpts
7268 , ghciSkipIntermediate :: ! Bool
7369 , ghciHidePackages :: ! Bool
7470 , ghciNoBuild :: ! Bool
71+ , ghciOnlyMain :: ! Bool
7572 } deriving Show
7673
7774-- | Necessary information to load a package or its components.
@@ -331,72 +328,65 @@ runGhci GhciOpts{..} targets mainIsTargets pkgs extraFiles = do
331328 -- is included.
332329 (if null pkgs then id else (" -i" : )) $
333330 odir <> pkgopts <> map T. unpack ghciGhcOptions <> ghciArgs <> extras)
334- interrogateExeForRenderFunction = do
335- menv <- liftIO $ configEnvOverride config defaultEnvSettings
336- output <- execObserve menv (fromMaybe (compilerExeName wc) ghciGhcCommand) [" --version" ]
337- if " Intero" `isPrefixOf` output
338- then return renderScriptIntero
339- else return renderScriptGhci
331+ -- TODO: Consider optimizing this check. Perhaps if no
332+ -- "with-ghc" is specified, assume that it is not using intero.
333+ checkIsIntero =
334+ -- Optimization dependent on the behavior of renderScript -
335+ -- it doesn't matter if it's intero or ghci when loading
336+ -- multiple packages.
337+ case pkgs of
338+ [_] -> do
339+ menv <- liftIO $ configEnvOverride config defaultEnvSettings
340+ output <- execObserve menv (fromMaybe (compilerExeName wc) ghciGhcCommand) [" --version" ]
341+ return $ " Intero" `isPrefixOf` output
342+ _ -> return False
340343 withSystemTempDir " ghci" $ \ tmpDirectory -> do
341344 macrosOptions <- writeMacrosFile tmpDirectory pkgs
342345 if ghciNoLoadModules
343346 then execGhci macrosOptions
344347 else do
345348 checkForDuplicateModules pkgs
346- renderFn <- interrogateExeForRenderFunction
349+ isIntero <- checkIsIntero
347350 bopts <- view buildOptsL
348351 mainFile <- figureOutMainFile bopts mainIsTargets targets pkgs
349- scriptPath <- writeGhciScript tmpDirectory (renderFn pkgs mainFile extraFiles)
352+ scriptPath <- writeGhciScript tmpDirectory (renderScript isIntero pkgs mainFile ghciOnlyMain extraFiles)
350353 execGhci (macrosOptions ++ [" -ghci-script=" <> toFilePath scriptPath])
351354
352355writeMacrosFile :: (MonadIO m ) => Path Abs Dir -> [GhciPkgInfo ] -> m [String ]
353356writeMacrosFile tmpDirectory packages = do
354- preprocessCabalMacros packages macrosFile
357+ preprocessCabalMacros packages macrosFile
355358 where
356359 macrosFile = tmpDirectory </> $ (mkRelFile " cabal_macros.h" )
357360
358361writeGhciScript :: (MonadIO m ) => Path Abs Dir -> GhciScript -> m (Path Abs File )
359362writeGhciScript tmpDirectory script = do
360- liftIO $ scriptToFile scriptPath script
361- setScriptPerms scriptFilePath
362- return scriptPath
363+ liftIO $ scriptToFile scriptPath script
364+ setScriptPerms scriptFilePath
365+ return scriptPath
363366 where
364367 scriptPath = tmpDirectory </> $ (mkRelFile " ghci-script" )
365368 scriptFilePath = toFilePath scriptPath
366369
367- findOwningPackageForMain :: [GhciPkgInfo ] -> Path Abs File -> Maybe GhciPkgInfo
368- findOwningPackageForMain pkgs mainFile =
369- find (\ pkg -> toFilePath (ghciPkgDir pkg) `isPrefixOf` toFilePath mainFile) pkgs
370-
371- renderScriptGhci :: [GhciPkgInfo ] -> Maybe (Path Abs File ) -> [Path Abs File ] -> GhciScript
372- renderScriptGhci pkgs mainFile extraFiles =
373- let addPhase = mconcat $ fmap renderPkg pkgs
374- mainPhase = case mainFile of
375- Just path -> cmdAddFile path
376- Nothing -> mempty
377- modulePhase = cmdModule $ foldl' S. union S. empty (fmap ghciPkgModules pkgs)
378- in case getFileTargets pkgs <> extraFiles of
379- [] -> addPhase <> mainPhase <> modulePhase
380- fileTargets -> mconcat $ map cmdAddFile fileTargets
381- where
382- renderPkg pkg = cmdAdd (ghciPkgModules pkg)
383-
384- renderScriptIntero :: [GhciPkgInfo ] -> Maybe (Path Abs File ) -> [Path Abs File ] -> GhciScript
385- renderScriptIntero pkgs mainFile extraFiles =
386- let addPhase = mconcat $ fmap renderPkg pkgs
387- mainPhase = case mainFile of
388- Just path ->
389- case findOwningPackageForMain pkgs path of
390- Just mainPkg -> cmdCdGhc (ghciPkgDir mainPkg) <> cmdAddFile path
391- Nothing -> cmdAddFile path
392- Nothing -> mempty
393- modulePhase = cmdModule $ foldl' S. union S. empty (fmap ghciPkgModules pkgs)
394- in case getFileTargets pkgs <> extraFiles of
395- [] -> addPhase <> mainPhase <> modulePhase
396- fileTargets -> mconcat $ map cmdAddFile fileTargets
397- where
398- renderPkg pkg = cmdCdGhc (ghciPkgDir pkg)
399- <> cmdAdd (ghciPkgModules pkg)
370+ renderScript :: Bool -> [GhciPkgInfo ] -> Maybe (Path Abs File ) -> Bool -> [Path Abs File ] -> GhciScript
371+ renderScript isIntero pkgs mainFile onlyMain extraFiles = do
372+ let cdPhase = case (isIntero, pkgs) of
373+ -- If only loading one package, set the cwd properly.
374+ -- Otherwise don't try. See
375+ -- https://github.com/commercialhaskell/stack/issues/3309
376+ (True , [pkg]) -> cmdCdGhc (ghciPkgDir pkg)
377+ _ -> mempty
378+ addPhase = cmdAdd $ S. fromList (map Left allModules ++ addMain)
379+ addMain = case mainFile of
380+ Just path -> [Right path]
381+ _ -> []
382+ modulePhase = cmdModule $ S. fromList allModules
383+ allModules = concatMap (S. toList . ghciPkgModules) pkgs
384+ case getFileTargets pkgs <> extraFiles of
385+ [] ->
386+ if onlyMain
387+ then cdPhase <> if isJust mainFile then cmdAdd (S. fromList addMain) else mempty
388+ else cdPhase <> addPhase <> modulePhase
389+ fileTargets -> cmdAdd (S. fromList (map Right fileTargets))
400390
401391-- Hacky check if module / main phase should be omitted. This should be
402392-- improved if / when we have a better per-component load.
0 commit comments