Search code examples
haskellshake-build-system

Storing metadata for rules


I have a function that rebuilds a target whenever the associated command changes:

target :: FilePath -> [FilePath] -> String -> Rules ()
target dst deps cline = do
  let dcmd = dst <.> "x"
  dcmd %> \out -> do
    alwaysRerun
    writeFileChanged out cline
    return ()
  dst %> \out -> do
    c <- readFile' dcmd
    need deps
    () <- cmd $ "../dumpdeps/dumpdeps " ++ out ++ " " ++ c
    needMakefileDependencies $ out <.> "d"
    return ()

I would prefer not to touch the filesystem for this task, is there any way to store the associated command line and trigger the final rule when that command changes?


Solution

  • I'd personally do this using the file system. File systems have great debuggers (ls and cat) and a large array of manipulation tools (echo, rm, touch). They also tend to be very fast for small files, living mostly in the cache. If you avoid the files, you tend to have less visibility of what's happening.

    That said, there can be very good reasons to avoid the files. The closest thing Shake has to your pattern above is to use an Oracle. Note that doesn't quite match the pattern you are doing, as it assumes the cline can be computed from dst, which might be possible in your case or might not.

    If Oracle doesn't suit you, you can define your own Rule instance which can operate much the same way as a file, but store the values in the Shake database instead.

    (If either of those cause any difficulties, let me know which is the relevant one to your question, and I'll expand the right one.)