I have a Haskell program that I want to compile with GHC, orchestrated by the Shake build system. Which commands should I execute, and under what circumstances should they be rerun?
1 Answers
There are two approaches to doing the compilation, and two approaches to getting the dependencies. You need to pick one from each set (all 4 combinations make sense), to come up with a combined approach.
Compilation
You can either:
- Call
ghc -c
on each file in turn, depending on the.hs
file and any.hi
files it transitively imports, generating both a.hi
and.o
file. At the end, callghc -o
depending on all the.o
files. For actual code see this example. - OR Call
ghc --make
once, depending on all.hs
files. For actual code see this example.
The advantage of ghc --make
is that it is faster than multiple calls to ghc -c
since GHC can load each .hi
file only once, instead of once per command. Typically the speedup is 3x. The disadvantage is parallelism is harder (you can use -j
to ghc --make
, but Shake still assumes each action consumes one CPU), and that two ghc --make
compilations can't both run at the same time if they overlap on any dependencies.
Dependencies
You can either:
- Parse the Haskell files to find dependencies recursively. To parse a file you can either look for
import
statements (and perhaps#include
statements) following a coding convention, or use a library such ashaskell-src-exts
. For actual code with a very approximateimport
parser see this example. - OR Use the output of
ghc -M
to detect the dependencies, which can be parsed using the Shake helper functionparseMakefile
. For actual code see this example.
The advantage of parsing the Haskell files is that it is possible to have generated Haskell files and it can be much quicker. The advantage of using ghc -M
is that it is easier to support all GHC features.

- 9,090
- 1
- 27
- 85
-
2It's great that you post this here, but strictly speaking this doesn't conform with SO policy because only the external code examples answer the question. I think you should embed the crucial rules in the post. – leftaroundabout Jun 08 '18 at 10:54
-
1Thanks @leftaroundabout - I expanded the answers so now the bullet points completely answer the question in enough detail - which is probably way more useful. The code is still linked, but it's not the answer, and it's mostly so people who understand the answer can copy it more easily. I don't want to reproduce the full code in SO since it detracts from the understanding of the answer. – Neil Mitchell Jun 08 '18 at 11:17