How can I make build.rs rerun every time that cargo run or cargo build is run?

I'm using build.rs with this crate, and there's a problem: sometimes when the files that this crate deals with change, the build.rs doens't re-run automatically. My build.rs file runs essentially instantly, so having it run on every build to completely exclude this class of often VERY frustrating to debug errors (since the tool that generates the files likes to misbehave, and I never know if it's build.rs misbehaving or the tool) is sensible. How can I make that happen?

build.rs

fn main() {
    // Tell Cargo that if the given file changes, to rerun this build script.
    println!("cargo:rerun-if-changed=path/to/file/relative/to/crate/root");
    ...
}
1 Like

rerun-if-changed has a footgun: if you use it, you're responsible for declaring all files that may affect this build script. It's not additive, it replaces Cargo's built-in logic.

1 Like

The default logic, by the way, is that build.rs will re-run if any file under the package directory changes (except for files that have been explicitly excluded/ignored). This should work fine as long as all your files are within the package's root directory and its subdirectories. But if they are located elsewhere, you'll need to tell Cargo where to find them.

Ideally, the actix-web-static-files crate would have a way to do this automatically. I see you found the open issue about this:

as a workaround shouldn't

fn main() {
    std::env::set_var("REBUILD", format!("{:?}", std::time::Instant::now())
    println!("cargo:rerun-if-env-changed=REBUILD");
    ...

work?

1 Like

If I understand correctly, then that's no trivial footgun. Could this behavior be changed to be additive, or alternatively, could an additive version of this be introduced?

AFAIK, the non-additive behavior is intentional, since the common case is to not rerun build script unless the files it uses are changed.

I'm aware of that. But professionally I've come across situations where I want the normal behavior plus a rebuild when a specific project-defined file changes. Currently that requires a full rebuild because incremental builds have proven to show inconsistent behavior there, sometimes updating the information and sometimes not.

Hence my request: using cargo:rerun-if-env-changed would be annoying because it requires manually specifying all the stuff you can usually take for granted, including things I don't know will be included.

Another way of saying that is that using this will likely cause the build to break in perhaps not so obvious ways.

The files that get changed are .gitignored, is this sufficient for the exception? The changes generally take the form of adding new files that will be caught in build.rs's run, but only if it runs. This is the only ignoring that I'm aware of (some library may be doing some sort of ignoring too, there are over 300 crates in my project including recursive dependencies).

1 Like

Yes. Cargo reads .gitignore files and uses them the exclude files from packaging and change-tracking. (The other way to exclude files is using the "include" and "exclude" fields in Cargo.toml.)

Alright, thanks. It seems like I should just use include to override .gitignore for the purposes of build.rs