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?

有帮助吗?

解决方案

My advice would be, don't bother trying to make this work. It should work, and it would be nice if it worked, but ghc's -M support is currently broken (as in, it doesn't generate proper dependency rules, and omits rules for some non-Haskell files). Actually getting this to work reliably will take a great deal of effort, and in the end will trigger more rebuilds than strictly necessary.

Furthermore, support for parallel builds has been merged into GHC, so when ghc-7.8 is released you'll be able to use plain ghc --make to get parallel builds. Or you could use ghc's HEAD now.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top