Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

mtime set to 0 in .ninja_log for outputs of rule with restat = 1 whose sole dependency is a phony target #2405

Closed
sdefresne opened this issue Mar 28, 2024 · 1 comment
Labels
Milestone

Comments

@sdefresne
Copy link

This was found when making a change in gn to use phony targets (https://gn-review.git.corp.google.com/c/gn/+/16920) for Chromium.

If a target use a custom rule, has restat = 1, does not modify its output, and only has phony target as outputs, then ninja will record a mtime of 0 for that target if it decides to rebuild it as part of an incremental build. From that point, the build will always be considered as dirty because the recorded mtime (0) will always be older than the mtime of the phony target.

Sample reproduction:

$ mkdir repro && cd repro
$ touch a
$ cat > build.ninja <<EOF
rule create_b
  command = test -f b || touch b
  restat = 1

build s: phony a
build b: create_b | s
EOF
$ ninja b -d explain
ninja explain: output b doesn't exist
[1/1] test -f b || touch b
$ ninja b -d explain
ninja: no work to do.
$ touch a
$ ninja b -d explain
ninja explain: restat of output b older than most recent input s (1711640092851462338 vs 1711640098788860000)
[1/1] test -f b || touch b
$ ninja b -d explain
ninja explain: restat of output b older than most recent input s (0 vs 1711640098788860000)
[1/1] test -f b || touch b
$ cat .ninja_log 
# ninja log v5
0	10	1711640092851462338	b	142acf958f60ee36
1	7	0	b	142acf958f60ee36
1	7	0	b	142acf958f60ee36

As can be seen, the mtime for b is stored as 0 after the target is rebuild due to the modification of a.

I think this is because the following code in Builder::FinishCommand(...):

  // Restat the edge outputs
  TimeStamp output_mtime = 0;
  bool restat = edge->GetBindingBool("restat");
  if (!config_.dry_run) {
    bool node_cleaned = false;
    ...

    if (node_cleaned) {
      TimeStamp restat_mtime = 0;
      // If any output was cleaned, find the most recent mtime of any
      // (existing) non-order-only input or the depfile.
      for (vector<Node*>::iterator i = edge->inputs_.begin();
           i != edge->inputs_.end() - edge->order_only_deps_; ++i) {
        // here (*i)->path() is "s" which does not exist, so
        // Stat() returns 0.
        TimeStamp input_mtime = disk_interface_->Stat((*i)->path(), err);
        ...
      }
      
      ...

      output_mtime = restat_mtime;
    }
  }
@sdefresne
Copy link
Author

So it looks like it reproduce with origin/release but not with origin/master.

After looking at the changes between those two branches, it looks like this was fixed by a2b5e6d.

sdefresne added a commit to sdefresne/ninja that referenced this issue Mar 28, 2024
This is a fix for issue ninja-build#2405 where a target with a single phony
input would be considered dirty forever after being built if the
rule was setting `restat = 1` because the code would try to stat
a non-existing file to record the input mtime.

Instead use the mtime recorded in the Node instance (restating it
if necessary) to avoid this issue.
ArthurSonzogni pushed a commit to ArthurSonzogni/gn that referenced this issue Mar 29, 2024
This reverts commit cfddfff.

Reason for revert: this breaks the incremental build of certains
targets of Chromium (i.e. base_unittests for device when the gn
variable `enable_run_ios_unittests_with_xctest = true`). This is
due to ninja-build/ninja#2405 which is
fixed in the development branch but not yet released.

Original change's description:
> [bundle] Use "phony" builtin tool for create_bundle targets
>
> Instead of using the "stamp" tool which creates files (and potentially
> slow down the build since this requires access to the filesystem), use
> the builtin "phony" tool.
>
> Bug: 194
> Change-Id: Ie1af7020af4e7efc6c8848244c21dac549f179aa
> Reviewed-on: https://gn-review.googlesource.com/c/gn/+/16920
> Reviewed-by: David Turner <digit@google.com>
> Commit-Queue: Sylvain Defresne <sdefresne@chromium.org>

# Not skipping CQ checks because original CL landed > 1 day ago.

Bug: 194
Change-Id: Id14e5c08e2ca40f6b2fe40d3a526295786f83302
Reviewed-on: https://gn-review.googlesource.com/c/gn/+/16940
Reviewed-by: David Turner <digit@google.com>
Commit-Queue: Sylvain Defresne <sdefresne@chromium.org>
@jhasse jhasse added the bug label Apr 4, 2024
@jhasse jhasse added this to the 1.12.0 milestone Apr 4, 2024
@jhasse jhasse closed this as completed Apr 7, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants