Shake has shakeVersion :: String
:
Defaults to 1. The version number of your build rules. Change the version number to force a complete rebuild, such as when making significant changes to the rules that require a wipe. The version number should be set in the source code, and not passed on the command line.
It is incredibly easy to improve the build system a bit and not notice that they were significant changes that require a wipe. If you distribute those via version control, it can lead to incorrect builds of my co-workers and in my Continuous Integration bot.
While I fix my own build by removing .shake.database
, communicating this to a whole company is not fun.
How can I deal with this automatically?
This is what I managed to come up with in https://github.com/ndmitchell/shake/issues/59; it is probably easier to spot it on stackoverflow than in a closed issue:
Let's assume my Shake rules are in Build.hs
.
I use a hash of Build.hs
itself as shakeVersion
:
{-# LANGUAGE TemplateHaskell #-}
import qualified Data.ByteString as BS
import Development.Shake.Classes (hashWithSalt)
import Language.Haskell.TH
-- | The name of this file we are in.
_THIS_FILE_NAME :: String
_THIS_FILE_NAME = $(LitE . StringL . loc_filename <$> location)
main = do
checksum <- dropWhile (== '-') . show . hashWithSalt 0 <$> BS.readFile _THIS_FILE_NAME
shakeArgs shakeOptions
{ shakeVersion = "hash-" ++ checksum ++ "-" ++ _THIS_FILE_NAME
} $ do ...
This way the version will be automatically changed when I change my Shake code, and I never have to worry about bumping it manually.
UPDATE: There is now a function getHashedShakeVersion
in shake
that allows to do the below a bit more easily.