use std::path::Path;
fn main() {
println!("cargo::rerun-if-changed=src");
println!("cargo::rerun-if-changed=build.rs");
let mut found = Vec::new();
scan(Path::new("src"), &mut found);
if !found.is_empty() {
found.sort();
found.dedup();
panic!(
"compile-time environment lookups found: {}\n\
these would be embedded in the binary -- read them at runtime via crate::env instead",
found.join(", ")
);
}
}
fn scan(dir: &Path, found: &mut Vec<String>) {
let Ok(entries) = dir.read_dir() else { return };
for entry in entries.flatten() {
let path = entry.path();
if path.is_dir() {
scan(&path, found);
} else if path.extension().is_some_and(|ext| ext == "rs") {
let Ok(source) = std::fs::read_to_string(&path) else {
continue;
};
collect(&source, &path, found);
}
}
}
fn collect(source: &str, path: &Path, found: &mut Vec<String>) {
for (offset, _) in source.match_indices("env!(") {
let rest = source[offset + "env!(".len()..].trim_start();
let Some(rest) = rest.strip_prefix('"') else {
continue;
};
let Some(name) = rest.split('"').next() else {
continue;
};
if !name.starts_with("CARGO_") {
found.push(format!("{} in {}", name, path.display()));
}
}
}