问题
How can I force build.rs
to run again without cleaning my whole project? I checked cargo build --help
but I couldn't find anything related to build.rs
.
回答1:
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.
回答2:
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'?
回答3:
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.
回答4:
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");
}
回答5:
I can offer the solution that works for me well.
Add the following to build.rs file to a dependency that have to be rebuilt everytime:
use failure::{format_err, Error};
use std::env;
use std::path::PathBuf;
use std::process::Command;
/// Just useful trait to run a command
trait RunIt {
fn run_it(&mut self, err: &str) -> Result<(), Error>;
}
impl RunIt for Command {
fn run_it(&mut self, err: &str) -> Result<(), Error> {
let output = self.output()?;
if !output.status.success() {
let out = String::from_utf8_lossy(&output.stderr);
eprintln!("{}", out);
Err(format_err!("{}", err))
} else {
Ok(())
}
}
}
fn main() -> Result<(), Error> {
// Your build stuff
// Activate this feature to rebuild this dependency everytime
if cfg!(feature = "refresh") {
Command::new("touch")
.args(&["build.rs"])
.run_it("Can't touch the build file")?;
}
Ok(())
}
Add the feature to Cargo.toml to declare the feature:
[package]
name = "sensitive-crate"
[features]
default = []
refresh = []
And activate refresh feature to rebuild the dependency everytime:
[package]
name = "my_project_1"
[dependencies]
sensitive-crate = { path = "../sensitive-crate", features = ["refresh"] }
来源:https://stackoverflow.com/questions/49077147/how-can-i-force-build-rs-to-run-again-without-cleaning-my-whole-project