Using the Shake Haskell build library, how can I write a rule using a program that needs to reach a fixed point? Imagine I have a program foo that takes a file input and produces an output file, which should have foo applied repeatedly until the output file does not change. How can I write that in Shake?
The typical example of this pattern is LaTeX.
Firstly, note that calling Latex repeatedly does not always produce a fixed point, so make sure you have a bound on the iterations. Also, some distributions (MikTex) provide Latex versions that automatically run as many times as they need to, so if you use those instead the problem goes away.
Write your own
foo_transitivecommandThe easiest way to solve the problem, assuming each run of
foohas the same dependencies, is to solve the problem outside the build system. Just write afoo_transitivecommand, either as a shell script or as a Haskell function, that when supplied an input file produces an output file by running repeatedly and checking if it has reached a fixed point. The build system can now usefoo_transitiveand there are no issues about dependencies.Encode it in the build system
You need to write two rules, one which makes one step, and one which figures out which step is the right one to use:
The first rule generates
tempfile.2fromtempfile.1and so on, so we canneed ["tempfile.100"]to get the 100th iteration. If the dependencies change in each step we can look at the previous result to calculate the new dependencies.The second rule loops round checking each pair of values in the sequence, and stopping when they are equal. If you are implementing this in a production build system you may wish to avoid calling
readFile'on each element twice (once asi-1and once asi).