Shake 不识别是否构建 rule/always 构建规则,即使它不应该

Shake does not recognize wether to build a rule/always builds a rule even if it shouldn't

我有一个项目,我使用 shake 生成一堆基于输入文件的报告,运行 作为一个 restful 网络服务。我选择 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" 存在并且已经 "built" 规则 运行s通过之前摇一摇。

我将 shake-0.15.11 与 shake 结合使用 - 使用 shake runhaskell Main.hs --package shakeshake exec -- testshake 没有任何区别。编译器是 GHC-8.0.2。所有这些都是在 Linux(薄荷)上完成的。

我读了 How does Shake decide whether to rebuild a target? - 我从中了解到,只有当输入文件或输出文件发生变化(其中变化由 shakeOptions 配置决定)时,shake 才会重建内容)

首先,pat %> act 意味着您创建文件构建规则,对于任何文件路径 都将是 运行 将接受模式 pat。这意味着如果有人调用 need [foo]pat ?== foo 那么将是 运行 带有参数 foo 的操作 act。因此,操作 act 应该尝试构建 foo.

其次,关于 action,如文档中所写:

The action will be run in every build execution (unless withoutActions is used).

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