我有一个项目,我使用shake来生成一堆基于输入文件的报告,并作为一个宁静的Web服务运行。我选择Shake的一个原因是,如果输入文件没有改变(例如基于Digest,可通过shakeOptions
配置),则不应重建任何内容。
我注意到即使我刚刚构建过程也会运行,并且在两次运行之间没有发生文件更改。所以我尝试了一个简单的例子,它应该模拟我的一个构建过程
import Control.Monad.IO.Class
import Development.Shake
wanted = "foo.3"
main = shake shakeOptions $ do
want [wanted] -- (1)
"*.1" %> \out -> do -- (2)
liftIO $ putStrLn out
unit $ cmd Shell "touch" "foo.2"
"*.2" %> \out -> do need [out] -- (3)
unit $ cmd "touch" wanted
action $ unit $ cmd Shell "touch" wanted -- (4)
虽然%>
规则从未运行,但action
规则始终完成。
如果我注释掉(4)并手动创建文件“foo.1” - 规则(1)失败,因为它没有弄清楚(2) - > (3)可以建立结果。
如果另一方面我注释掉(2)和(3)并离开(4) - 即使“foo.3”存在并且之前已经“摇摆”,规则也会运行。
我使用shake-0.15.11结合摇动 - 使用shake runhaskell Main.hs --package shake
或shake exec -- testshake
没有任何区别。编译器是GHC-8.0.2。所有这些都是在Linux(Mint)上完成的。
我读了How does Shake decide whether to rebuild a target? - 只有当输入文件或输出文件发生变化(其中变化由shakeOptions
配置确定)时,我才从中收集震动重建内容< / p>
答案 0 :(得分:1)
首先,pat %> act
表示您创建了文件构建规则,该规则将针对将使用模式pat
接受的任何文件路径运行。这意味着,如果有人调用need [foo]
和pat ?== foo
,那么将使用参数act
运行操作foo
。因此,操作act
应该尝试构建foo
。
其次,关于action
,如文档中所述:
该操作将在每次构建执行中运行(除非使用了withoutActions)。
wand
定义如下:want = action . need
。
例如,我重新设计了您的示例,其中包含有关文件之间依赖关系的一些假设。也就是说,foo.3需要foo.2,foo.2需要foo.1和foo.1已经存在(它的来源)。
wanted = "foo.3"
main = shake shakeOptions $ do
want [wanted]
"*.3" %> \out -> do
putNormal out
need [out -<.> ".2"]
unit $ cmd Shell "touch" out
"*.2" %> \out -> do
putNormal out
need [out -<.> ".1"]
unit $ cmd Shell "touch" out