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 forbuild.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:
- 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
- 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 inCargo.toml
withbuild = false
Note: since the
OUT_DIR
env var is not present forbin
targets, if yourbuild.rs
script usesenv!("OUT_DIR")
, you may "fix this" by usingconcat!(env!("CARGO_MANIFEST_DIR"), "/target/")
instead.