I have a Haskell project where a number of executables are produced from mostly the same modules. I'm using a Makefile to enable parallel builds, and it very nearly works the way I want. Here's a stripped down version of my current Makefile, with ideas taken from http://www.haskell.org/ghc/docs/latest/html/users_guide/separate-compilation.html#using-make:
HFLAGS=-O3 -Wall -v0 -fno-ignore-asserts
HASKELLS=bin1 bin2 bin3 bin4 bin5 bin6 bin7 bin8 bin9
all: $(HASKELLS)
%.hi: %.o
@:
%.hi %.o: %.hs
ghc -c $(HFLAGS) $<
$(HASKELLS): %: %.o
ghc --make $(HFLAGS) $@
.hsdepend: *.hs
ghc -M -dep-makefile .hsdepend *.hs
rm -f .hsdepend.bak
include .hsdepend
As you can see, I still use ghc --make
for linking (only); this way the individual modules can be compiled in parallel, and ghc --make
only invokes the linker.
Unfortunately this is not foolproof: A relink is triggered only for, say, bin1 only if bin1.o is newer than the executable, but not if only one of the other object files has been updated. This can happen when a change is made in a module such that it results in the .o file being updated, but the interface of the module does not change, i.e. the .hi file is not touched.
One alterative solution would be to trigger a null ghc --make
for every binary every time make is invoked; unfortunately, this is slow and clutters the output (I'd like to see when something was linked and when not).
ghc -M
only generates a dependency line for each .o file, but none for the linked executables. The information about which .o files to link into which executable (given the name of the main module binN.hs) obviously is there, but it's not entirely clear to me if it's possible to get to it using any Makefile magic.
I can only think of a way to do what this by writing a post-processor for .hsdepend, but that seems excessive.
Can anyone suggest a better solution?