summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthew Pickering <matthewtpickering@gmail.com>2019-03-10 17:43:10 +0000
committerMarge Bot <ben+marge-bot@smart-cactus.org>2019-03-12 09:04:52 -0400
commit2d7dd0285bbc364f89d4d97928674f7ea73ed2c8 (patch)
tree64afbe9484037925efe0575e77971f532ac155fd
parent4cf2160afe0e08fe29576895a1eced863d3a521d (diff)
downloadhaskell-2d7dd0285bbc364f89d4d97928674f7ea73ed2c8.tar.gz
Hadrian: Add ./hadrian/ghci.sh script for fast development feedback
Running the `./hadrian/ghci` target will load the main compiler into a ghci session. This is intended for fast development feedback, modules are only typechecked so it isn't possible to run any functions in the repl. You can also use this target with `ghcid`. The first time this command is run hadrian will need to compile a few dependencies which will take 1-2 minutes. Loading GHC into GHCi itself takes about 30 seconds. Internally this works by calling a new hadrian target called `tool-args`. This target prints out the package and include flags which are necessary to load files into ghci. The same target is intended to be used by other tooling which uses the GHC API in order to set up the correct GHC API session. For example, using this target it is also possible to use HIE when developing on GHC.
-rw-r--r--hadrian/README.md38
-rwxr-xr-xhadrian/ghci.sh3
-rw-r--r--hadrian/hadrian.cabal1
-rw-r--r--hadrian/src/Builder.hs6
-rw-r--r--hadrian/src/Main.hs1
-rw-r--r--hadrian/src/Oracles/Setting.hs2
-rw-r--r--hadrian/src/Rules.hs35
-rwxr-xr-xhadrian/src/Settings.hs4
-rw-r--r--hadrian/src/Settings/Builders/Ghc.hs13
-rw-r--r--hadrian/src/Settings/Flavours/GhcInGhci.hs25
10 files changed, 123 insertions, 5 deletions
diff --git a/hadrian/README.md b/hadrian/README.md
index 179d9d07ce..77c3cd0950 100644
--- a/hadrian/README.md
+++ b/hadrian/README.md
@@ -158,6 +158,27 @@ build stage2:lib:text
build stage1:exe:haddock
```
+#### Fast feedback using ghci
+
+Running the `./hadrian/ghci.sh` script will load the main compiler into
+a ghci session. This is intended for fast development feedback, modules are only
+typechecked so it isn't possible to run any functions in the repl.
+
+```
+./hadrian/ghci.sh
+```
+
+You can also use this target with `ghcid`.
+
+```
+ghcid --command="./hadrian/ghci.sh"
+```
+
+The first time this command is run hadrian will need to compile a few dependencies
+which will take 1-2 minutes. Loading GHC into GHCi itself takes about 30 seconds and
+reloads after that take in the region of 1-5 seconds depending on which modules
+need to be recompiled.
+
#### Testing
To run GHC testsuite, use `build test`. See
@@ -203,6 +224,23 @@ a compiler built using Stage2. This is useful for cross-compilation. Detailed
instructions can be found in the corresponding
[part of the user settings manual](doc/user-settings.md#specifying-the-final-stage-to-build).
+#### Integrating Hadrian into other tooling
+
+The `tool-args` target is designed to allow hadrian to be integrated into other
+tooling which uses the GHC API.
+`tool-args` prints out a list of flags which hadrian will use to compile
+a module in the `compiler` directory. Using these flags you can then set up
+a GHC API session with the correct environment to load a module into your own
+GHC session. This is how `haskell-ide-engine` is able to support hadrian.
+
+```
+> ./hadrian/build.sh tool-args
+-hide-all-packages -no-user-package-db -package-db _build/stage0/lib/packag...
+```
+
+
+The `./hadrian/ghci.sh` script is implemented using this target.
+
Troubleshooting
---------------
diff --git a/hadrian/ghci.sh b/hadrian/ghci.sh
new file mode 100755
index 0000000000..4a70946269
--- /dev/null
+++ b/hadrian/ghci.sh
@@ -0,0 +1,3 @@
+#!/usr/bin/env bash
+
+ghci $(TERM=dumb CABFLAGS=-v0 . "hadrian/build.cabal.sh" tool-args -q --build-root=.hadrian_ghci --flavour=ghc-in-ghci "$@") -fno-code -fwrite-interface -hidir=.hadrian_ghci/interface -O0 ghc/Main.hs
diff --git a/hadrian/hadrian.cabal b/hadrian/hadrian.cabal
index a5a1ead0e7..a0b364855f 100644
--- a/hadrian/hadrian.cabal
+++ b/hadrian/hadrian.cabal
@@ -97,6 +97,7 @@ executable hadrian
, Settings.Flavours.Quick
, Settings.Flavours.QuickCross
, Settings.Flavours.Quickest
+ , Settings.Flavours.GhcInGhci
, Settings.Packages
, Settings.Warnings
, Stage
diff --git a/hadrian/src/Builder.hs b/hadrian/src/Builder.hs
index 6d334d80f4..d855aa5bde 100644
--- a/hadrian/src/Builder.hs
+++ b/hadrian/src/Builder.hs
@@ -45,7 +45,11 @@ instance NFData CcMode
-- * Compile a C source file.
-- * Extract source dependencies by passing @-M@ command line argument.
-- * Link object files & static libraries into an executable.
-data GhcMode = CompileHs | CompileCWithGhc | FindHsDependencies | LinkHs
+data GhcMode = CompileHs
+ | CompileCWithGhc
+ | FindHsDependencies
+ | LinkHs
+ | ToolArgs
deriving (Eq, Generic, Show)
instance Binary GhcMode
diff --git a/hadrian/src/Main.hs b/hadrian/src/Main.hs
index 083e6838d8..fe5dbbb937 100644
--- a/hadrian/src/Main.hs
+++ b/hadrian/src/Main.hs
@@ -50,6 +50,7 @@ main = do
Rules.SourceDist.sourceDistRules
Rules.Test.testRules
Rules.topLevelTargets
+ Rules.toolArgsTarget
shakeArgsWith options CommandLine.optDescrs $ \_ targets -> do
Environment.setupEnvironment
diff --git a/hadrian/src/Oracles/Setting.hs b/hadrian/src/Oracles/Setting.hs
index 4666539f93..a869a31e12 100644
--- a/hadrian/src/Oracles/Setting.hs
+++ b/hadrian/src/Oracles/Setting.hs
@@ -3,7 +3,7 @@ module Oracles.Setting (
getSettingList, anyTargetPlatform, anyTargetOs, anyTargetArch, anyHostOs,
ghcWithInterpreter, ghcEnableTablesNextToCode, useLibFFIForAdjustors,
ghcCanonVersion, cmdLineLengthLimit, iosHost, osxHost, windowsHost,
- hostSupportsRPaths, topDirectory, libsuf
+ hostSupportsRPaths, topDirectory, libsuf, ghcVersionStage
) where
import Hadrian.Expression
diff --git a/hadrian/src/Rules.hs b/hadrian/src/Rules.hs
index c5be5a7ff9..e4de23f34d 100644
--- a/hadrian/src/Rules.hs
+++ b/hadrian/src/Rules.hs
@@ -1,4 +1,5 @@
-module Rules (buildRules, oracleRules, packageTargets, topLevelTargets) where
+module Rules (buildRules, oracleRules, packageTargets, topLevelTargets
+ , toolArgsTarget ) where
import qualified Hadrian.Oracles.ArgsHash
import qualified Hadrian.Oracles.Cabal.Rules
@@ -26,6 +27,38 @@ import Target
import UserSettings
import Utilities
+
+-- | @tool-args@ is used by tooling in order to get the arguments necessary
+-- to set up a GHC API session which can compile modules from GHC. When
+-- run, the target prints out the arguments that would be passed to @ghc@
+-- during normal compilation to @stdout@.
+--
+-- This target is called by the `ghci.sh` script in order to load all of GHC's
+-- modules into GHCi.
+toolArgsTarget :: Rules ()
+toolArgsTarget = do
+ "tool-args" ~> do
+ let fake_target = target (Context Stage0 compiler dynamic)
+ (Ghc ToolArgs Stage0) [] ["ignored"]
+
+ -- need the autogenerated files so that they are precompiled
+ generatedGhcDependencies Stage0 >>= need
+ interpret fake_target Rules.Generate.compilerDependencies >>= need
+
+ root <- buildRoot
+ let dir = buildDir (vanillaContext Stage0 compiler)
+ need [ root <//> dir -/- "Config.hs" ]
+ need [ root <//> dir -/- "Fingerprint.hs" ]
+ need [ root <//> dir -/- "Parser.hs" ]
+ need [ root <//> dir -/- "Lexer.hs" ]
+ need [ root <//> dir -/- "CmmParse.hs" ]
+ need [ root <//> dir -/- "CmmLex.hs" ]
+
+ -- Find out the arguments that are needed to load a module into the
+ -- session
+ arg_list <- interpret fake_target getArgs
+ liftIO $ putStrLn (intercalate " " arg_list)
+
allStages :: [Stage]
allStages = [minBound .. maxBound]
diff --git a/hadrian/src/Settings.hs b/hadrian/src/Settings.hs
index bc0f8cecaa..3089c0a4e6 100755
--- a/hadrian/src/Settings.hs
+++ b/hadrian/src/Settings.hs
@@ -18,6 +18,7 @@ import Settings.Flavours.Profiled
import Settings.Flavours.Quick
import Settings.Flavours.Quickest
import Settings.Flavours.QuickCross
+import Settings.Flavours.GhcInGhci
getArgs :: Args
getArgs = expr flavour >>= args
@@ -38,7 +39,8 @@ hadrianFlavours =
[ defaultFlavour, developmentFlavour Stage1, developmentFlavour Stage2
, performanceFlavour, profiledFlavour, quickFlavour, quickestFlavour
, quickCrossFlavour
- , performanceLlvmFlavour, profiledLlvmFlavour, quickLlvmFlavour ]
+ , performanceLlvmFlavour, profiledLlvmFlavour, quickLlvmFlavour
+ , ghcInGhciFlavour ]
flavour :: Action Flavour
flavour = do
diff --git a/hadrian/src/Settings/Builders/Ghc.hs b/hadrian/src/Settings/Builders/Ghc.hs
index 0d0d58a09f..940eab546a 100644
--- a/hadrian/src/Settings/Builders/Ghc.hs
+++ b/hadrian/src/Settings/Builders/Ghc.hs
@@ -11,7 +11,18 @@ import qualified Context as Context
import Rules.Libffi (libffiName)
ghcBuilderArgs :: Args
-ghcBuilderArgs = mconcat [compileAndLinkHs, compileC, findHsDependencies]
+ghcBuilderArgs = mconcat [ compileAndLinkHs, compileC, findHsDependencies
+ , toolArgs]
+
+toolArgs :: Args
+toolArgs = do
+ builder (Ghc ToolArgs) ? mconcat
+ [ packageGhcArgs
+ , includeGhcArgs
+ , map ("-optc" ++) <$> getStagedSettingList ConfCcArgs
+ , map ("-optP" ++) <$> getStagedSettingList ConfCppArgs
+ , map ("-optP" ++) <$> getContextData cppOpts
+ ]
compileAndLinkHs :: Args
compileAndLinkHs = (builder (Ghc CompileHs) ||^ builder (Ghc LinkHs)) ? do
diff --git a/hadrian/src/Settings/Flavours/GhcInGhci.hs b/hadrian/src/Settings/Flavours/GhcInGhci.hs
new file mode 100644
index 0000000000..82fd0f2411
--- /dev/null
+++ b/hadrian/src/Settings/Flavours/GhcInGhci.hs
@@ -0,0 +1,25 @@
+module Settings.Flavours.GhcInGhci (ghcInGhciFlavour) where
+
+import Expression
+import Flavour
+import {-# SOURCE #-} Settings.Default
+import Settings.Flavours.Common
+
+-- Please update doc/flavours.md when changing this file.
+ghcInGhciFlavour :: Flavour
+ghcInGhciFlavour = defaultFlavour
+ { name = "ghc-in-ghci"
+ , args = defaultBuilderArgs <> ghciArgs <> defaultPackageArgs
+ , libraryWays = pure [vanilla, dynamic]
+ , rtsWays = pure [vanilla, threaded, dynamic]
+ , dynamicGhcPrograms = return False }
+
+ghciArgs :: Args
+ghciArgs = sourceArgs SourceArgs
+ { hsDefault = mconcat $
+ [ pure ["-O0", "-H64m"]
+ , naturalInBaseFixArgs
+ ]
+ , hsLibrary = mempty
+ , hsCompiler = mempty
+ , hsGhc = mempty }