1

I have a project where I use shake to generate a bunch of reports based on input-files, and run as a restful webservice. One reason why I chose Shake is that is should not rebuild anything if input-files have not changed (e.g. based on Digest, configurable via shakeOptions).

I noticed that the processes would run even if I had just built them and no file change had happened in between runs. So I tried a simple example it should simulate the process of one of my builds

import           Control.Monad.IO.Class
import           Development.Shake

wanted = "foo.3"

main = shake shakeOptions $ do
  want [wanted]                                       -- (1)
  "*.1" %> \out -> do                                 -- (2)
    liftIO $ putStrLn out
    unit $ cmd Shell "touch" "foo.2"

  "*.2" %> \out -> do need [out]                      -- (3)
                      unit $ cmd "touch" wanted

  action $ unit $ cmd Shell "touch" wanted            -- (4)

while the %> rules never run - the action rule is always done.

If I comment out (4) and create a file "foo.1" manually - the rule (1) is failing because it does not figure out that (2) -> (3) can build the result.

If on the other hand I comment out (2) and (3) and leave (4) - the rule runs even if "foo.3" exists and has been "built" by shake before.

I am using shake-0.15.11 in combination with shake - using shake runhaskell Main.hs --package shake or shake exec -- testshake does not make any difference. Compiler is GHC-8.0.2. All of this is done on a Linux (Mint).

I read How does Shake decide whether to rebuild a target? - from which I gathered that shake rebuilds stuff only if either the input-file(s) or the output-file change (where change is determined by the shakeOptions configuration)

Community
  • 1
  • 1
epsilonhalbe
  • 15,637
  • 5
  • 46
  • 74
  • You have strange build rules. (2) dosn't build `out`. (3) rule, instead of building an `out`, asks for it on input (need [out]). – freestyle May 04 '17 at 14:34
  • I thought I might have a bit of a misunderstanding - If I build `out` - how is the name of `out` determined? I thought `out` is the out-put of the pattern match on the lhs – epsilonhalbe May 04 '17 at 14:35
  • The build rule (2) can build any file witch file path has extension ".1". It's mean that if some one call `need ["xxx.1"]` then will be run (2) build rule with `out = "xxx.1"`. If, for example, in the build rule (2) you need file with extension ".2", you can write: `need [out -<.> ".2"]`, after this it will be accessed. – freestyle May 04 '17 at 14:45
  • AAAH now I got it! and what about `action`s - are they wildcard rules and run every time I call shake – epsilonhalbe May 04 '17 at 14:48
  • Yes. And `want` defined like this: `want = action . need` – freestyle May 04 '17 at 14:50
  • 1
    do you `action . need` to make your comments in answer? I would accept it. – epsilonhalbe May 04 '17 at 14:55
  • Well, I'll try to sum up. – freestyle May 04 '17 at 14:57

1 Answers1

1

First of all, pat %> act mean that you create the file-build-rule, which will be run for any file path witch will be accepted with the pattern pat. It's mean that if some one call need [foo] and pat ?== foo then will be run the action act with argument foo. So, the action act should to try build foo.

Secondly, about action, as wrote in the documentation:

The action will be run in every build execution (unless withoutActions is used).

And wand defined like this: want = action . need.

For example, I redesign your example with some assumptions about dependencies between your files. Namely, foo.3 need foo.2, foo.2 need foo.1 and foo.1 already exists (it's source).

wanted = "foo.3"
main = shake shakeOptions $ do
    want [wanted]

    "*.3" %> \out -> do                      
        putNormal out
        need [out -<.> ".2"]
        unit $ cmd Shell "touch" out

    "*.2" %> \out -> do
        putNormal out
        need [out -<.> ".1"]
        unit $ cmd Shell "touch" out
freestyle
  • 3,692
  • 11
  • 21