如何在不清理整个项目的情况下再次强制 `build.rs` 到 运行?

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

如何在不清理整个项目的情况下再次强制 build.rs 到 运行?我检查了 cargo build --help 但找不到与 build.rs.

相关的任何内容

如果你打印

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

每次文件更改时都会触发构建。

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

我不知道没有手动更改文件的解决方案(我只是在我的 build.rs 中的任何地方放置了一个空格,但它会被 rustfmt 删除)。

我的项目中有几个构建脚本,主要是这两行给了我一个很好的解决方案:

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

但我猜你正在寻找命令 rustc/cargo 命令。无论如何,你可以放入一个小脚本,它会编辑某个文件,这会触发 build-process.

build.rs 注册为箱子的 bin 目标:

  1. 将此添加到您的 Cargo.toml 文件中:
[package]
edition = "2018"
build = "build.rs"

[[bin]]
name = "force-build"
path = "build.rs"
required-features = ["build_deps"]  # only needed for build-dependencies
  1. 如果您有任何 [build-dependencies]例如some_crate = "1.2.3"),您需要将它们添加到(主要)[dependencies](遗憾的是 no [bin-dependencies] as of yet),但您可以将它们设为可选:
[dependencies]
some_crate = { version = "1.2.3", optional = true }

[features]
build_deps = ["some_crate"]

然后你可以运行构建脚本:

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

(或 $ cargo run --bin force-build 当没有 [build-dependencies] 时)

  • 您甚至可以通过将 Cargo.toml 中的 build = "build.rs" 行替换为 [=24] 来禁用构建脚本的 自动 调用=]

  • 注意:由于 OUT_DIR 环境变量不存在于 bin 目标,如果您的 build.rs 脚本使用 env!("OUT_DIR"),您可以“改用 concat!(env!("CARGO_MANIFEST_DIR"), "/target/") 解决这个问题。

如果 build.rs 改变,Cargo 已经重建项目:

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

在 Linux,我会做 touch build.rs && cargo build。对于 Windows,请参阅 Windows equivalent of the Linux command 'touch'?

如果您在 gitignore 下获得目标(您应该这样做),这可能对您在开发和测试构建脚本时的任何文件更改很有用。

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

如果您尝试基于未生锈或 include!() 可能已更改的文件进行重建,您可以使用

const _: &[u8] = include_bytes!("foobar.baz");

以确保对这些文件的任何更改都会触发新的构建。很确定这个解决方案既不增加时间也不增加文件大小。

你也可以把它推到一个宏里,所以很容易做一堆文件。

macro_rules! build_on{($file:literal) => {
    const _: &[u8] = include_bytes!($file);
}

build_on!("foobar.baz");