4

I have this kind of rule:

"foo" *> \out do
  need something
  create "foo" somehow

It's built correctly, and running the build twice won't build the target. Then I add a system' to this rule:

"foo" *> \out do
  ...
  system' something

Running shake now doesn't rebuild the "foo" target, because no dependencies changed. Anyway, the rule changed. So I expect the newly added system' action to change the history of the rule, and in turn force a rebuild of "foo", but it wasn't the case. Usually in autoconf/automake systems, or even in non-trivial makefiles, the rules depend on Makefile itself, so that whenever it changes the project is rebuilt. In Shake I expect this to work and to be fine grained.

In the source code of system' I can't see anything that adds an implicit dependency on the command being run.

Am I doing something wrong? Is it intentional to not support this kind of dependencies, or it's simply not implemented?

lethalman
  • 1,976
  • 1
  • 14
  • 18

1 Answers1

2

The behaviour you are seeing is expected, and the ICFP 2012 paper S6.2 outlines some strategies for coping with it. It would be ideal if each output depended on the rule used to build it, but that requires some equality over rules (which are just functions whose source code is unavailable during execution). One day I hope Shake will work as you describe, but I don't think it's possible at the moment in GHC.

To minimize the number of build system changes, it is best to keep anything you think will change on a regular basis out of the build system. Any list of files (for example which files are required to link a C executable) can be put in configuration files or depended upon properly through the use of the oracle mechanism.

Of course, the rules will still change from time to time, and there are two approaches you can take:

Rebuild everything if anything changes

A simple conservative approach, as adopted by many Makefiles, is to rebuild everything if anything changes. An easy way to implement this strategy is to hash the Shake scripts, and use that as the shakeVersion field. For projects that rebuild reasonably quickly this can work well.

Rebuild with manual control

For larger projects, the build system is often in daily flux, but most parts of the build system have no impact on most rules. For some rules I explicitly need some source files in the rule, for example if there is a large generator in a file, I would need that in the rule producing the generated output. If you also use writeFileChanged to write the generated file, then many modifications to the generator will cause only minimal rebuilding.

If the changes are more invasive, I manually increment the shakeVersion field, and force a complete rebuild. In a mature build system with proper dependency tracking, this event may happen only a few times a year.

Neil Mitchell
  • 9,090
  • 1
  • 27
  • 85
  • 1
    For a system' wouldn't be enough to just save in the history the command issued? Also, hashing of the file seems too complex, isn't need ["Build.sh"] enough? – lethalman Feb 14 '13 at 22:44
  • 1
    Saving the command issued is not enough, since I can't tell what command would be issued this time round without running the rule, which is too late (Make statically knows the commands that will be run, Shake does not).Hashing the file would let you make all rules depend on the contents without changing any rule, need ["Build.sh"] would have to be added to each rule. – Neil Mitchell Feb 14 '13 at 22:52