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 を使用してこれをシミュレートしていますが、これはハックなソリューションのように思えます。

その上、このソリューションはクリーン ビルドでは正しく動作するように見えますが、表示される合計がすべてのソース ファイルの合計であるため、部分ビルドでは正しく動作しません。

Progress データ型にアクセスすると、countSkipped、countBuild、および countTodo メンバーを使用してこの割合を正しく計算できます (Progress.hs:53 を参照)。

どんな助けでも大歓迎です。

4

1 に答える 1

1

type の値Progressは現在、 に格納されている関数の引数としてのみ使用できますshakeProgressProgress次の方法でいつでも取得できます。

{-# 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に渡された引数を squirrelする を作成しshakeProgress、後でルールを実行するときにそれを取得します。上記のコードを実行すると、次のようになります。

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

より高いレベルの並列処理で実行すると、精度の低い結果が得られます。最初は todo に 3 つのアイテムしかなく (ShakecountTodoはアイテム todo を見つけるとインクリメントし、アイテムのいずれかを認識するとすぐにアイテムを生成します)、多くの場合、2 つのルールが実行されます。同じインデックスで (進行中の数に関する情報はありません)。特定のルールの知識があれば、出力を調整できます。たとえば、IORefインクリメントを格納して、インデックスが単調であることを確認できます。

このコードがやや複雑な理由はProgress、あなたのアプローチは完全に有効に見えますが、情報が非同期の進行状況メッセージに使用されることを意図していたためです。getProgress :: Action Progress同期進行メッセージの関数を導入する価値があるかもしれません。

于 2015-08-21T14:46:14.500 に答える