3

我对Shake用来确定是否需要重建输出的规则感到困惑。我有一个简单的文档构建,有两个步骤。下面是完整的构建文件,但总而言之,asciidoc它用于将.txt文件转换为.dbxml(Docbook XML)文件,然后使用dblatex.

我希望如果我触摸 PDF 并重新运行摇动,什么都不会发生,因为输出比两个输入都新。然而,shake 实际上执行了 dblatex 步骤。

接下来,我希望如果我触摸该.dbxml文件,则shake 将执行 dblatex 而不是 asciidoc,因为 dbxml 比其输入(即.txt)更新。然而,shake 实际上同时执行 asciidoc 和 dblatex 步骤。

我在依赖项中犯了错误吗?

import Development.Shake
import Development.Shake.FilePath

-- List of output files
outputs = ["process.pdf"]

main = shakeArgs shakeOptions{shakeVerbosity=Diagnostic} $ do
    want outputs

    -- Rule to produce pdf files from dbxml inputs
    "*.pdf" *> \out -> do
        let dbxml = out `replaceExtension` "dbxml"
        need [dbxml]
        cmd "dblatex" "-o" out dbxml

    -- Rule to produce dbxml files from txt (asciidoc) inputs
    "*.dbxml" *> \out -> do
        let src = out `replaceExtension` "txt"
        need [src]
        cmd "asciidoc" "--backend=docbook45" "--doctype=article" "-o" out src
4

1 回答 1

4

在 Shake 中,如果文件的最后修改时间与构建时相比发生了变化,则认为文件是脏的。在 make 中,如果文件的最后修改时间于其依赖项,则认为文件是脏的。我怀疑你的观察都源于这种差异。为了直接回答这个问题,如果文件或其任何直接依赖项发生了变化,Shake 会重建文件。

为什么 Shake 做一些不同的事情?三个原因:

  1. 如果修改时间发生变化,Make 没有存储足够的信息来允许它重新构建,因为它没有记录有关上次构建中修改时间的任何额外元数据。
  2. 通过进行时间比较,make 依赖于单调递增的时钟,如果用户更改系统时间,时钟就会中断,并且似乎特别容易在 NFS 文件系统上损坏。
  3. 假设 A 依赖于 B,B 依赖于 C。C 发生变化,B 重建,但是 B 的规则足够聪明,可以发现旧的 B 不需要更新。在 make 中,您有两个不好的选择 - 无论如何触摸 B 并重建 A,或者不要触摸 B,然后每次运行 make 时运行 B 的规则。在 Shake 中,你不碰 B,A 不重建,B 下次也不重建。

至于您的构建系统,对我来说一切都很好。我唯一的小调整是使用中缀运算符-<.>而不是replaceExtension- 它们都是相同的功能,但运算符在我看来更清晰。

于 2013-10-19T22:05:31.533 回答