How can I force `build.rs` to run again without cleaning my whole project?

If you got target under gitignore (which you should) this might be useful for any file changes when you're developing and testing the build script.

if Path::new(".git/HEAD").exists() {
    println!("cargo:rerun-if-changed=.git/HEAD");
}

If build.rs changes, Cargo already rebuilds the project:

Note that if the build script itself (or one of its dependencies) changes, then it's rebuilt and rerun unconditionally, so cargo:rerun-if-changed=build.rs is almost always redundant (unless you want to ignore changes in all other files except for build.rs). doc

On Linux, I will just do touch build.rs && cargo build. For Windows, see Windows equivalent of the Linux command 'touch'?


If you print

"cargo:rerun-if-changed=<FILE>"

the build will be triggered every time the file has changed.

rerun-if-changed=PATH is a path to a file or directory which indicates that the build script should be re-run if it changes (detected by a more-recent last-modified timestamp on the file). Normally build scripts are re-run if any file inside the crate root changes, but this can be used to scope changes to just a small set of files. -- source

I'm not aware of a solution without changing a file manually (I just put a whitespace anywhere in my build.rs, it will be removed by rustfmt though).

I have several buildscripts in my projects, and mostly these two lines give me a nice solution:

println!("cargo:rerun-if-changed=build.rs");
println!("cargo:rerun-if-changed=path/to/Cargo.lock");

but I guess you are looking for a command rustc/cargo command. Anyway, you can put in a small script, which will edit a certain file, which will trigger the build-process.


Register build.rs as a crate's bin target:

  1. Add this to your Cargo.toml file:
[package]
edition = "2018"
build = "build.rs"

[[bin]]
name = "force-build"
path = "build.rs"
required-features = ["build_deps"]  # only needed for build-dependencies
  1. If you have any [build-dependencies] (e.g. some_crate = "1.2.3"), you need to add those to (the main) [dependencies] (sadly no [bin-dependencies] as of yet), but you can make them optional:
[dependencies]
some_crate = { version = "1.2.3", optional = true }

[features]
build_deps = ["some_crate"]

Then you can run the build script with:

$ cargo run --bin force-build --features build_deps

(or $ cargo run --bin force-build when no [build-dependencies])

  • You can even disable the automatic call of the build script by replacing the build = "build.rs" line in Cargo.toml with build = false

  • Note: since the OUT_DIR env var is not present for bin targets, if your build.rs script uses env!("OUT_DIR"), you may "fix this" by using concat!(env!("CARGO_MANIFEST_DIR"), "/target/") instead.