2

我试图弄清楚如何在执行命令之前从 Progress 类型(在 Development.Shake.Progress 中)获取进度信息以输出它。可能的期望输出将是:

[1/9] Compiling src/Window/Window.cpp
[2/9] Compiling src/Window/GlfwError.cpp
[3/9] Compiling src/Window/GlfwContext.cpp
[4/9] Compiling src/Util/MemTrack.cpp
...

现在我正在使用一些 IORef 来模拟这个,它保持总数(最初设置为源文件的总和)和我在执行每个构建命令之前增加的计数,但这对我来说似乎是一个 hackish 解决方案。

最重要的是,该解决方案似乎在干净的构建上可以正常工作,但在部分构建上表现不佳,因为显示的总和仍然是所有源文件的总和。

通过访问 Progress 数据类型,我将能够使用它的 countSkipped、countBuild 和 countTodo 成员正确计算这个分数(参见 Progress.hs:53),但我仍然不确定如何实现这一点。

任何帮助表示赞赏。

4

1 回答 1

1

typeProgress的值目前只能作为存储在shakeProgress. 您可以随时通过以下方式获得Progress

{-# LANGUAGE RecordWildCards #-}
import Development.Shake
import Data.IORef
import Data.Monoid
import Control.Monad

main = do
    ref <- newIORef $ return mempty
    shakeArgs shakeOptions{shakeProgress = writeIORef ref} $ do
         want ["test" ++ show i | i <- [1..5]]
         "test*" %> \out -> do
             Progress{..} <- liftIO $ join $ readIORef ref
             putNormal $
                "[" ++ show (countBuilt + countSkipped + 1) ++
                "/" ++ show (countBuilt + countSkipped + countTodo) ++
                "] " ++ out
             writeFile' out ""

在这里,我们创建一个IORef来隐藏传递给 的参数shakeProgress,然后在运行规则时检索它。运行上面的代码我看到:

[1/5] test5
[2/5] test4
[3/5] test3
[4/5] test2
[5/5] test1

以更高的并行度运行会产生不太精确的结果 - 最初在 todo 中只有 3 个项目(在countTodo找到项目时摇动增量,并在它知道任何项目后立即生成项目),并且通常有两个规则在运行在同一索引处(没有关于有多少正在进行中的信息)。鉴于您的特定规则的知识,您可以优化输出,例如存储IORef您的增量以确保索引是单调的。

此代码有些令人费解的原因是该Progress信息旨在用于异步进度消息,尽管您的方法似乎完全有效。可能值得getProgress :: Action Progress为同步进度消息引入一个函数。

于 2015-08-21T14:46:14.500 回答