ghc-shake icon indicating copy to clipboard operation
ghc-shake copied to clipboard

ghc --make reimplemented with Shake

ghc-shake

This is a reimplementation of ghc --make using Shake. It's entirely one process, so unlike out-of-process Shake, you won't see any slowdown compared to --make if you compile with only one core.

What's the benefit?

1. You get faster rebuild checking, because Shake doesn't
recompute the entire dependency graph (ghc --make must
preprocess and parse all source code every time it loads.)

2. You can keep going even when one file fails to compile,
making sure that anything can be built, is built.

3. You get all the nice Shake features, e.g. unchanging
rebuilds and profiling.  The profiling is really
handy!

How do I use it?

You'll need these two (somewhat hard to get) items:

- GHC 8.0

- A customized version of Shake: https://github.com/ezyang/shake

- Appropriately patched copies of all of Shake's dependencies
  to work with GHC 8.0.  If you wait, these will probably work
  out; but at the time of writing I needed to pass
  --allow-newer=base,transformers,process to cabal to get
  all of the dependencies to install.

One way to to get everything installed (assuming GHC 8.0 is in your path) is to run:

git clone https://github.com/ezyang/shake
(cd shake && cabal install --allow-newer=base,transformers,process)
git clone https://github.com/ezyang/ghc-shake
(cd ghc-shake && cabal install --allow-newer=base,transformers,process)

This will enable usage of ghc --frontend GhcShake. We have a sample script 'ghc-shake' in our source directory which you can pass to Cabal as a --with-ghc argument, which will override the meaning of --make (however, you'll need to edit the -plugin-package-db arguments to accurately reflect your installation. If you're not building ghc-shake in place, deleting them should be good enough.)

What doesn't work

1. Re-linking detection across packages.  See
    https://ghc.haskell.org/trac/ghc/ticket/10161

2. Profiling.  See
    https://ghc.haskell.org/trac/ghc/ticket/11293

3. Linking things that are not executables

4. Recompilation after package database changes.  (We
do correctly pick up changes to external interface
files, however.)

5. ghc-shake is not really lib-ified properly (it
should be namespaced and given explicit exports).
I'll do this eventually.

6. hs-boot loops don't work; we don't properly
invalidate the EPS when we successfully compile
the replacement for an hs file.

If you need something, shout and I'll try to implement it.