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?

1

There are 1 answers

1
nh2 On BEST ANSWER

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.