On Sun, Feb 28, 2016 at 11:51 AM, Neil Mitchell <
ndmit...@gmail.com> wrote:
> My first thought was maybe you didn't have any default statements, and
> thus it was building the intermediate because it wanted it as an
> end-product - but checking, that isn't the case.
Indeed I forgot to mention that the behaviour I was experienced was
even in the case I called explicitly `ninja output` (thus not the
default rule which builds everything.)
> I compared Ninja to
> my reimplementation of Ninja (where I reimplemented Ninja from
> experiments and the manual, see
http://shakebuild.com/ninja) and found
> my implementation follows the semantics you expected. My small test
> case was:
>
> rule run
> command = touch $out
> build intermediate.txt: run
> build out1.txt: run || intermediate.txt
> default out1.txt
I have made a simple test with `make` (the GNU version) for a similar scenario:
~~~~
input :
touch input
intermediary : input
touch intermediary
output : input | intermediary
touch output
~~~~
Then tested it with:
~~~~
make -f ./makefile output
rm ./intermediary
make -f ./makefile output
~~~~
"Unfortunately" even `make` has the same odd behaviour, i.e. it
insists in re-creating the intermediary file although it is not needed
for rebuilding anything being asked for.
Thus this might be one explanation why `ninja` behaves the way it
does, namely to be compliant with `make` (and thus easier to be used
as a drop-in replacement in various build generator tools).
> One way around the problem is to have the rule for the intermediate
> file spit out intermediate.big and intermediate.stamp - where the big
> file is the real one, and the stamp file is zero bytes. You can then
> depend on the stamp file in all the rules, but use the big file in the
> rules. Since Ninja doesn't know about the big file, deleting it will
> not make any difference.
Indeed this would be a solution I haven't though about. Thanks for
pointing it out.
However, although it solves my particular problem, I find this
solution problematic. First of all it could lead to buggy builds
because now Ninja knows nothing about the "actual" file, and imagine
that the developer manually (who uses a build generator thus not being
aware of these "hacks") deletes the "big" file to force Ninja to
re-build its dependencies, which unfortunately doesn't happen anymore.
The second reason would be for build generators. Now I failed to
mention that the Ninja script I use is not written by hand, but
instead generated with my own custom-built (for that purpose) Python
script. This script of mine already doesn't use a lot of Ninja
features (like the `$in` and `$out` variables), but instead relies on
build-scoped variables like `input__whatever_a`, `output__whatever_b`,
etc., thus it wouldn't be hard for me to make it use the "build-stamp"
files you've suggested. But in doing so (and because I want to
minimize the changes to my own Python script), I'll resort to create a
"build-stamp" file for every other output-file, thus doubling the
number of files in my temporary folder, and possibly introducing other
bugs in the process.
Thus I see this "hack" as problematic when applied "on scale".
Perhaps the best solution for this issue to introduce a third category
of dependencies, something as "optional", which behave just like
"order-only" but don't require rebuilding.
Ciprian.