4

我有几个(独立的)文件需要很长时间才能编译,所以我想我会尝试并行编译,根据 Don Stewart在此处的回答。

我按照这里的说明进行操作,所以我的 makefile 看起来像

quickbuild:
    ghc --make MyProg.hs -o MyProg

depend:
    ghc -M -dep-makefile makefile MyProg

# DO NOT DELETE: Beginning of Haskell dependencies
...
MyProg.o : MyProg.hs
MyProg.o : B.hi
MyProg.o : C.hi
...
# DO NOT DELETE: End of Haskell dependenciesghc

(注意:与文档相反,GHC 似乎默认为“Makefile”而不是“makefile”,即使存在“makefile”也是如此。)

我的问题是:如何让 quickbuild 依赖于任何自动生成依赖项(以便 make 实际上并行运行)?我尝试将“MyProg.o”添加到“quickbuild”的依赖项列表中,但“make”(正确地)抱怨没有构建“B.hi”的规则。

4

1 回答 1

1

我建议不要make用于这种目的。

查看ghc-parmake及其问题,尤其是这个问题- GHC 有一个非常复杂的重新编译检查器,您无法使用 Makefiles 复制它(它可以检测例如您自己项目之外的包文件是否发生更改)。

您也不会从并行make -j运行多个 GHC 中获得很大的加速(实际上不大于 2),因为触发多个 GHC 具有很高的启动开销,而ghc --make. 特别是,每个新的 GHC 调用都必须解析和.hi类型检查您正在编译的模块的所有依赖项中涉及的所有接口文件;ghc --make缓存它们。

相反,使用新ghc --make -j的 GHC 7.8 - 它是真正并行的。

它将比您手动编写的 Makefile 更可靠且更省力,并且比 Make 可以使用其文件时间戳更好地避免重新编译。


乍一看,这听起来像是 Haskell 的一个缺点,但实际上并非如此。在其他喜欢make用于构建的语言中,比如 C++,当项目之外的文件发生变化时,是不可能注意到的;在编译器本身中有一个构建系统ghc --make可以让您注意到这一点。

于 2014-02-28T10:56:05.527 回答