我有一个Haskell项目,其中大部分可执行文件来自大多数相同的模块。我正在使用Makefile来启用并行构建,它几乎以我想要的方式工作。这是我当前Makefile的精简版本,其中的想法来自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
如您所见,我仍然使用ghc --make
进行链接(仅限);这样,各个模块可以并行编译,ghc --make
只调用链接器。
不幸的是,这不是万无一失的:仅当 bin1.o 比可执行文件更新时才会触发重新链接,例如 bin1 ,但如果只有一个其他目标文件已更新。当在模块中进行更改以使其导致 .o 文件更新时,可能会发生这种情况,但模块的界面不会更改,即 .hi 文件未被触及。
一个替代解决方案是每次调用make时触发每个二进制文件的空ghc --make
;不幸的是,这很慢并且使输出变得混乱(我希望看到什么东西被链接,什么时候没有)。
ghc -M
仅为每个 .o 文件生成一个依赖关系行,但链接的可执行文件没有生成依赖关系。有关哪个 .o 文件链接到哪个可执行文件(给定主模块的名称 binN.hs )的信息显然是存在的,但是我不完全清楚可以使用任何Makefile魔法来实现它。
我只能通过为 .hsdepend 编写后处理器来想办法做到这一点,但这似乎过分了。
有人能提出更好的解决方案吗?
答案 0 :(得分:0)
我的建议是,不要费心去做这项工作。它应该工作,如果它工作会很好,但ghc的-M
支持当前被破坏(因为它没有生成适当的依赖规则,并且省略了一些非Haskell文件的规则)。实际上让它可靠地工作将需要付出很多努力,最终将触发更多的重建,而不是严格必要的。
此外,对并行构建的支持已合并到GHC中,因此当ghc-7.8发布时,您将能够使用普通ghc --make
来获得并行构建。或者你现在可以使用ghc的HEAD。