Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
我应该如何让Shake知道';ghc——make';是否需要跟踪对haskell文件的更改?_Haskell_Shake Build System - Fatal编程技术网

我应该如何让Shake知道';ghc——make';是否需要跟踪对haskell文件的更改?

我应该如何让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

我想知道将shake和
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 **> ...