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

Failed build script is not tracked in fingerprint. #6770

Closed
ehuss opened this issue Mar 21, 2019 · 3 comments · Fixed by #6782
Closed

Failed build script is not tracked in fingerprint. #6770

ehuss opened this issue Mar 21, 2019 · 3 comments · Fixed by #6782
Labels
A-build-scripts Area: build.rs scripts A-rebuild-detection Area: rebuild detection and fingerprinting C-bug Category: bug

Comments

@ehuss
Copy link
Contributor

ehuss commented Mar 21, 2019

There is a scenario where cargo fails to rebuild when the execution of a build script is interrupted (such as hitting ctrl-c). There are a variety of ways this can happen, the test below illustrates one way.

The fundamental problem is that the fingerprint does not track enough information about the execution of a build script as a dependency. #6720 added tracking the invoked.timestamp file, but that is not sufficient.

I've been pondering various ways to fix this, but not loving the options. I would be interested if anyone has any more ideas. Bonus points if both this and #6733 can be fixed. Some options:

  • Build script fingerprint of registry dependencies is not tracked in fingerprint. #6733 mentions adding the info from build_script_local_fingerprints, but there are some complications with updating that after the build is done (it would need to do everything that prepare_build_cmd does, too).
  • Add another file that is written in the fingerprint dir that tracks the completion of running the build script, perhaps with a sequence number bumped each time it is run.
  • When the build script starts, write invoked.timestamp.start (and delete invoked.timestamp) and then when the build script succeeds, rename it to invoked.timestamp. I think this should work, but I'm not sure.
  • (Crazy) Switch to a database for fingerprint tracking to make it easier to track dependencies.

Example

(This currently fails on the last line where the build succeeds when it should fail.)

#[test]
fn script_fails_stay_dirty() {
    let p = project()
        .file(
            "build.rs",
            r#"
                mod helper;
                fn main() {
                    println!("cargo:rerun-if-changed=build.rs");
                    helper::doit();
                }
            "#,
        )
        .file("helper.rs", "pub fn doit() {}")
        .file("src/lib.rs", "")
        .build();

    p.cargo("build").run();
    p.change_file("helper.rs", r#"pub fn doit() {panic!("Crash!");}"#);
    p.cargo("build")
        .with_stderr_contains("[..]Crash![..]")
        .with_status(101)
        .run();
    // There was a bug where this second call would be "fresh".
    p.cargo("build")
        .with_stderr_contains("[..]Crash![..]")
        .with_status(101)
        .run();
}
@ehuss ehuss added C-bug Category: bug A-rebuild-detection Area: rebuild detection and fingerprinting A-build-scripts Area: build.rs scripts labels Mar 21, 2019
@alexcrichton
Copy link
Member

Jeez we just can't seem to get this right :(. I really would start seriously considering larger scale revamps because it's be clear that ever since inception we haven't been able to ever produce a bug-free system where incremental works correctly in all cases...

Is the problem here that there's still a file on the filesystem which indicates a successful run, and so during the failing step above Cargo correctly realizes it doesn't need to rebuild the build script itself but incorrectly reuses the old successful output assuming the new binary succeeded?

I sort of forget how this is solved for crates, but I vaguely remember us deleting files that is recognized specially (this could be totally wrong though). Do you recall off the top of your head how that works for normal crates?

@ehuss
Copy link
Contributor Author

ehuss commented Mar 21, 2019

still a file on the filesystem

Correct. The build script fingerprint only tracks the rerun-if statements, and this example it is literally just build.rs. Thinking about it more, perhaps it is sufficient to add the fingerprint of the compilation of the build script? I'm going to experiment with that, it might be sufficient. I think the issue in #6720 would still broken here, though.

For context, this was discovered by @eddyb working on the gll crate which has a number of modules in the build script and he was hitting the OOM killer (I think). gll could add rerun-if-changed lines for each file, but I don't think it is reasonable to require that for normal rust modules.

how that works for normal crates

A normal crate would catch this from the dep-info file. The running of a build script is the odd one out. It requires build script authors to be extremely diligent in tracking all inputs, and I think we can ease that a little. I suspect I'm missing something, though.

@alexcrichton
Copy link
Member

Hm ok, so it sounds like the build script execution is buggily not tracking the build script itself. In that one of the inputs to the build script execution should be the binary of the build script itself, which we should recognize has changed from the previous successful run which triggers a run until it succeeds.

I do remember we fixed a number of issues like this by adding dependency edges from packages to their dependencies (in the fingerprints), so maybe we're just missing that for build script execution?

bors added a commit that referenced this issue Mar 26, 2019
…chton

Fix fingerprint for canceled build script.

Fixes #6770. See that issue for a description.

The fix is to include the compilation of the build script itself in the fingerprint of the `RunCustomBuild` Unit.

This also includes some documentation for how fingerprints work.

Also includes a test for docker-style caching of dependencies where timestamps get truncated to the nearest second.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-build-scripts Area: build.rs scripts A-rebuild-detection Area: rebuild detection and fingerprinting C-bug Category: bug
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants