use std::fs;
use std::path::Path;
use std::process::Command;
use tempfile::TempDir;
fn write_project(dir: &Path) {
fs::create_dir_all(dir.join("src")).unwrap();
fs::write(
dir.join("Cargo.toml"),
"[package]\nname = \"app\"\nversion = \"0.1.0\"\nedition = \"2021\"\nbuild = \"build.rs\"\n",
)
.unwrap();
fs::write(
dir.join("build.rs"),
r##"use std::{env, fs, path::PathBuf};
fn main() {
let out = PathBuf::from(env::var("OUT_DIR").unwrap());
let gen = out.join("generated");
fs::create_dir_all(gen.join("inner")).unwrap();
fs::write(gen.join("inner/mod.rs"), "pub fn answer() -> u32 { 42 }\n").unwrap();
fs::write(
gen.join("mod.rs"),
format!("#[path = \"{}\"]\npub mod inner;\n", gen.join("inner/mod.rs").display()),
)
.unwrap();
println!("cargo:rerun-if-changed=build.rs");
}
"##,
)
.unwrap();
fs::write(
dir.join("src/main.rs"),
"mod generated {\n include!(concat!(env!(\"OUT_DIR\"), \"/generated/mod.rs\"));\n}\n\
fn main() { println!(\"{}\", generated::inner::answer()); }\n",
)
.unwrap();
}
fn mitts_build(dir: &Path, cache: &Path) -> (bool, String) {
let out = Command::new(env!("CARGO_BIN_EXE_mitts"))
.arg("build")
.arg("--manifest-path")
.arg(dir.join("Cargo.toml"))
.arg("--cache-dir")
.arg(cache)
.env("CI", "true")
.env_remove("MITTS_CACHE_DIR")
.output()
.expect("run mitts");
(
out.status.success(),
format!(
"{}\n{}",
String::from_utf8_lossy(&out.stdout),
String::from_utf8_lossy(&out.stderr)
),
)
}
#[test]
fn generated_code_naming_the_absolute_out_dir_compiles_from_the_restored_build_script_output() {
let temp = TempDir::new().unwrap();
let app = temp.path().join("app");
write_project(&app);
let cache = temp.path().join("cache");
let (ok, text) = mitts_build(&app, &cache);
assert!(ok, "cold build:\n{text}");
let main = app.join("src/main.rs");
let mut src = fs::read_to_string(&main).unwrap();
src.push_str("// touched\n");
fs::write(&main, src).unwrap();
let (ok, text) = mitts_build(&app, &cache);
assert!(ok, "rebuild from the restored OUT_DIR:\n{text}");
let run = Command::new(app.join("target/debug/app")).output().unwrap();
assert_eq!(String::from_utf8_lossy(&run.stdout).trim(), "42");
let other = temp.path().join("other");
write_project(&other);
let (ok, text) = mitts_build(&other, &cache);
assert!(
ok,
"build of another checkout from the shared store:\n{text}"
);
}