我试图找出如何从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解决方案。 / p>
最重要的是,这个解决方案似乎在干净的构建上正常工作,但在部分构建上行为不当,因为显示的总和仍然是所有源文件的总和。
通过访问Progress数据类型,我可以使用countSkipped,countBuild和countTodo成员正确计算这个分数(参见Progress.hs:53),但我仍然不确定如何实现这一点。
感谢任何帮助。
答案 0 :(得分:1)
类型Progress
的值当前仅可用作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个项目(Shake会增加countTodo
,因为它会找到项目todo,并在知道任何项目后立即生成项目) ,并且通常有两个规则在同一个索引上运行(没有关于有多少正在进行中的信息)。根据您的特定规则的知识,您可以优化输出,例如存储一个IORef
增量以确保索引是单调的。
此代码有点令人费解的原因是Progress
信息旨在用于异步进度消息,尽管您的方法似乎完全有效。可能值得为同步进度消息引入getProgress :: Action Progress
函数。