Search code examples
shake-build-system

Depending on a generated file


What's the right way for a rule to need a generated file? Here's what I tried:

import Development.Shake
import System.IO
import Control.Monad

main = do
    s <- withBinaryFile "/dev/urandom" ReadMode $ replicateM 10 . hGetChar

    shakeArgs shakeOptions $ do
        want ["a.out"]

        "generated" *> \target -> writeFileChanged target s

        "*.out" *> \out -> do
            need ["generated"]
            writeFile' out =<< readFile' "generated"

But this results in the rule for generated not getting re-run, so a.out stays the same after repeated runs.


Solution

  • To solve your problem you need to add alwaysRerun to the definition of generated, so that the generated rule always runs. You are correctly depending on generated with the need (and also with the readFile', which does a need behind scenes), it's just that generated doesn't have any input dependencies, so never gets rerun. Adding alwaysRerun gives generated a dependency that always changes. I would expect to see:

    "generated" *> \target -> do
        alwaysRerun
        writeFileChanged target s
    

    (You can also move the definition of s down to under generated, but I have a suspicion that's just an artefact of how you've simplified your test case.)