When using parallel builds in shake, i get malformed output like this:
[»] Compiling src/Game/Game.cpp
[»] Compiling [»] Compiling [»] Compiling src/Graphics/Image/Png/PngLoader.cpp
src/Main.cpp
src/System/HeartBeat.cpp
[»] Compiling src/Window/Window.cpp
[»] Compiling src/Window/GlfwContext.cpp
I suppose that it is some kind of synchronization problem with my printing. I should note that i am using the following as an output command:
shakeOutput = const $ BS.putStr . BS.pack
And the status message printing section my rules looks like this:
liftIO $ setSGR [SetColor Foreground Vivid Green]
putNormal "[\175] Compiling "
liftIO $ setSGR [SetColor Foreground Vivid Yellow]
putNormal $ c ++ "\n"
liftIO $ setSGR [Reset]
Is there a way to avoid that kind of printing problems with my output built in in shake? If not what kind of haskell syncronization method would be appropriate to use, knowing that the printing code is inside a shake rule?
The reason shakeOutput
defaults to const $ BS.putStr . BS.pack
is because the BS.putStr
takes the Haskell console lock, and thus ensures output isn't interleaved. I don't believe this is a contractual guarantee of BS.putStr
, but if it ever stops being so, I will add a lock around shakeOutput
by default. There are two approaches to fix the problem:
One approach is to add a lock, ideally a renterant Mutex (not something I've seen in Haskell already, but can be synthesised relatively easily on top of MVar
and myThreadId
). Then you make shakeOutput
take the lock, and in your snippets which call shakeOutput
multiple times you also take the lock around the entire block. The Mutex probably wants to be stored in a top-level unsafePerformIO
CAF.
shakeOutput
callSince shakeOutput
is already atomic you can just reuse that property by rewriting your code as:
putNormal $
setSGRCode [SetColor Foreground Vivid Green] ++
"[\175] Compiling " ++
setSGRCode [SetColor Foreground Vivid Yellow] ++
c ++ "\n" ++
setSGRCode [Reset]
I'd encourage the second approach, since it's much simpler, and also makes sure that if the verbosity is turned to quiet the codes don't still get printed.