mirror of
https://github.com/pbakaus/impeccable.git
synced 2026-09-19 17:46:36 +03:00
core/build.rs: refuse a detector archive built by another rustc, in plain words
The archive links only against the exact rustc that built it; a mismatch used to surface as pages of undefined std symbols from the linker. The detector repo now writes rustc-version.txt next to the archive (and ships it with the release); when it is present, build.rs compares it with its own compiler and names both versions. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Vau2X53xGTjjTCXWMVBoNY
This commit is contained in:
co-authored by
Claude Fable 5.1
parent
3d8b13812f
commit
836516a7a0
@@ -74,6 +74,7 @@ fn main() {
|
||||
bundle.display()
|
||||
);
|
||||
|
||||
check_rustc_version(&dir);
|
||||
println!("cargo:rustc-link-search=native={}", dir.display());
|
||||
println!("cargo:rustc-link-lib=static={LIB_NAME}");
|
||||
println!(
|
||||
@@ -166,6 +167,10 @@ fn fetch_into(cache: &Path, lib: &Path, version: &str, short: &str, file_name: &
|
||||
let tmp = cache.join(format!(".{file_name}.part.{}", std::process::id()));
|
||||
fs::write(&tmp, &bytes).unwrap_or_else(|e| panic!("cannot write {}: {e}", tmp.display()));
|
||||
fs::rename(&tmp, lib).unwrap_or_else(|e| panic!("cannot move {} into place: {e}", tmp.display()));
|
||||
// Best effort: the compiler that built the release, for check_rustc_version.
|
||||
if let Ok(v) = download(&format!("{base}/detector-v{version}/rustc-version.txt")) {
|
||||
let _ = fs::write(cache.join("rustc-version.txt"), v);
|
||||
}
|
||||
println!("cargo:warning=fetched detector v{version} for {short} into {}", lib.display());
|
||||
}
|
||||
|
||||
@@ -254,3 +259,28 @@ fn sha256_hex(bytes: &[u8]) -> String {
|
||||
let digest = Sha256::digest(bytes);
|
||||
digest.iter().map(|b| format!("{b:02x}")).collect()
|
||||
}
|
||||
|
||||
/// The archive's objects reference std by mangled symbol name, so they only
|
||||
/// link against the exact rustc that built them. `cargo xtask detector-archive`
|
||||
/// writes `rustc-version.txt` next to the archive and the release ships it;
|
||||
/// when it is there, refuse a mismatch with a message that names both
|
||||
/// versions instead of leaving the linker to print pages of undefined symbols.
|
||||
fn check_rustc_version(dir: &Path) {
|
||||
let recorded = match fs::read_to_string(dir.join("rustc-version.txt")) {
|
||||
Ok(s) => s.trim().to_string(),
|
||||
Err(_) => return,
|
||||
};
|
||||
let rustc = env::var("RUSTC").unwrap_or_else(|_| "rustc".to_string());
|
||||
let out = match std::process::Command::new(&rustc).arg("-V").output() {
|
||||
Ok(o) => String::from_utf8_lossy(&o.stdout).trim().to_string(),
|
||||
Err(_) => return,
|
||||
};
|
||||
if !recorded.is_empty() && recorded != out {
|
||||
panic!(
|
||||
"the detector archive in {} was built by `{recorded}` but this build uses `{out}`. \
|
||||
Both must be the exact version rust-toolchain.toml pins (run `rustup show`); a toolchain \
|
||||
bump needs a new detector release (docs/ENGINE.md).",
|
||||
dir.display()
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user