我应该如何让Shake知道';ghc——make';是否需要跟踪对haskell文件的更改?
我想知道将shake和我应该如何让Shake知道';ghc——make';是否需要跟踪对haskell文件的更改?,haskell,shake-build-system,Haskell,Shake Build System,我想知道将shake和ghc--make一起使用的推荐方法。在我的项目中,shake规则用于将C源代码编译成它们的*.o文件(我称之为cobjects),这些对象通过调用ghc--make链接到我的haskell程序中。在该命令执行期间,ghc自行确定何时需要重建我的haskell文件 下面的示例没有正确编写以集成这两个工具。如果.hs文件发生更改,则重新运行shake脚本不会重新调用ghc--make。我理解为什么shake不知道如何重建,但我不知道建议的修复方法 main = shake s
ghc--make一起使用的推荐方法。在我的项目中,shake规则用于将C源代码编译成它们的*.o
文件(我称之为cobjects
),这些对象通过调用ghc--make
链接到我的haskell程序中。在该命令执行期间,ghc
自行确定何时需要重建我的haskell文件
下面的示例没有正确编写以集成这两个工具。如果.hs
文件发生更改,则重新运行shake脚本不会重新调用ghc--make
。我理解为什么shake不知道如何重建,但我不知道建议的修复方法
main = shake shakeOptions $ do
want [main_exe]
main_exe *> \out -> do
need cobjects
cmd "ghc --make" hs_compileFlags cobjects "main.hs"
cobjects **> ...
看起来推荐的方法可能是使用“虚假”规则,并在顶部为该规则添加一个want
。这是从本有用的教程中找到的:
我第一次尝试将这个想法应用到我的例子中:
main = shake shakeOptions $ do
want [main_exe, "compile and link hs"]
main_exe *> \out -> do
need cobjects
cobjects **> ...
"compile and link hs" ~> do
cmd "ghc --make" hs_compileFlags cobjects "main.hs"
函数指定字符串“compile and link hs”
是规则名,而不是文件名
虽然这将始终尝试按我所希望的方式运行新规则,但不幸的是,它尝试在main_exe
的规则之前运行该规则,这不是我所希望的
将对新规则的需求移动到main_exe
的规则中似乎可以解决此新问题:
main = shake shakeOptions $ do
want [main_exe]
main_exe *> \out -> do
need cobjects
need ["compile and link hs"]
cobjects **> ...
"compile and link hs" ~> do
cmd "ghc --make" hs_compileFlags cobjects "main.hs"
虽然这是可行的,但我不明白Shake如何决定在第一段代码中运行这两个规则的顺序。一般原则是,如果规则运行使用文件的命令,它应该取决于文件。在您的情况下,您必须需要所有东西ghc——发出请求,最简单的方法是使用ghc-M
(它会生成Makefile
):
needMakefileDependencies
函数位于Development.Shake.Util
中。唯一的微妙之处是,我在运行该命令后调用needMakefileDependencies
,因为否则还不会创建对象文件(您可以通过使用parseMakefile
自己只过滤Makefile
中的.hs
文件来解决这个问题)。问题:当您说“当.hs文件更改时”-您的意思是“当main.hs
更改”还是涉及其他.hs文件?在我看来,您的main\u exe`规则应该在某个地方包含需要“main.hs”
。不,我的意思是“当任何.hs文件更改时”“。如果main.hs
未更改,但main.hs
所依赖的另一个源文件foo.hs
已更改,然后,命令ghc--make
足够聪明,它自己就可以明白它必须重新编译main.hs
以及依赖于foo.hs
的任何其他内容。部分答案可能是使用ghc-M
让ghc发出依赖信息——有关更多详细信息,请参阅。然后,您可以将其合并到needs
语句中。不要重新运行ghc--make
“当任何.hs文件发生更改时”,您不想总是重新运行ghc--make
?这似乎是重新链接可执行文件所必需的,然后ghc--make
也应该获取对.hs文件的任何更改。是的,我始终希望运行ghc--make
。它应该在(可能)为cobjects执行规则之后运行。一般来说,需要非虚假规则中的虚假规则不是一个好主意。我怀疑如果你用cmd“ghc--make”…
替换need[“compile and link hs”]
,它会做完全相同的事情,这会让你回到你在问题中遇到的问题。这并不像need
处理所有ghc-M
请求那么简单。您还必须安排对可能需要重新编译的每个文件调用ghc
,其中包括通过CPP
进行的更改、更改的编译标志、模板haskell的addDependentFile
(ghc-M
不跟踪此情况),以及包数据库的任何更改时间。此外,如果源文件已被删除,则与陈旧的.hi/.o
文件有关的一些奇怪错误也会出现。这些可能与每个项目都不相关,但损坏的构建系统非常令人沮丧,因此了解它们是件好事。正如@JohnL所说,addDependentFile
不起作用,如果ghc pkg list
的输出发生更改,您可能需要调用ghc--make
,以捕获任何包更改。我认为您不需要在每个文件上调用ghc
,因为--make
模式将解决这个问题。陈旧的.hi/.o
文件不应该有任何错误,即使某些内容已被删除(除了那些单独来自ghc--make
的内容)。我同意,调用ghc--make
应该处理与这些问题相关的所有问题。我的意思是,如果你想完全避免ghc--make
,这些都是你需要自己管理的问题。
main = shake shakeOptions $ do
want [main_exe]
main_exe *> \out -> do
need cobjects
cmd "ghc -M" hs_compileFlags "main.hs"
cmd "ghc --make" hs_compileFlags cobjects "main.hs"
needMakefileDependencies "Makefile"
cobjects **> ...