use std::env;
use std::fs;
use std::path::{Path, PathBuf};
use std::time::{SystemTime, UNIX_EPOCH};
use toml::Value;
macro_rules! escape_newlines {
($s:expr) => {
$s.replace("\r\n", "\n").replace('\n', "\\n")
};
}
pub fn inject_build_metadata(project_dest_path: PathBuf) {
let manifest_dir =
PathBuf::from(env::var("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR not set"));
let dest_path = manifest_dir.join(&project_dest_path);
let destination_dir = dest_path.parent().unwrap();
fs::create_dir_all(&destination_dir).expect("Failed to create generated directory");
let build_target = env::var("TARGET").unwrap_or_else(|_| "unknown-target".to_string());
println!("cargo:rustc-env=BUILD_TARGET={}", build_target);
let build_time_utc = SystemTime::now()
.duration_since(UNIX_EPOCH)
.expect("Time went backwards")
.as_secs()
.to_string();
println!("cargo:rustc-env=BUILD_TIME_UTC={}", build_time_utc);
if let Some(license_path) = get_license_file_path(&manifest_dir) {
if let Ok(license_content) = fs::read_to_string(&license_path) {
println!(
"cargo:rustc-env=LICENSE_CONTENT={}",
escape_newlines!(license_content)
);
}
}
const CONTENTS: &[u8] = include_bytes!("inject_build_metadata.struct.rs");
if let Ok(existing_contents) = fs::read(&dest_path) {
if existing_contents == CONTENTS {
println!(
"No changes to {}; skipping file write.",
dest_path.display()
);
} else {
fs::write(&dest_path, CONTENTS).expect("Failed to write metadata file");
}
} else {
fs::write(&dest_path, CONTENTS).expect("Failed to write metadata file");
}
println!("cargo:rerun-if-changed=Cargo.toml");
println!("cargo:rerun-if-changed=inject.rs");
if let Some(license_path) = get_license_file_path(&manifest_dir) {
println!("cargo:rerun-if-changed={}", license_path.display());
}
}
pub fn get_cargo_field(manifest_dir: &Path, field: &str) -> Option<String> {
let cargo_toml_path = manifest_dir.join("Cargo.toml");
let cargo_toml_content = fs::read_to_string(&cargo_toml_path).ok()?;
let cargo_toml: Value = toml::from_str(&cargo_toml_content).ok()?;
cargo_toml
.get("package")?
.get(field)?
.as_str()
.map(|s| s.to_string())
}
pub fn get_license_file_path(manifest_dir: &Path) -> Option<PathBuf> {
get_cargo_field(manifest_dir, "license-file").map(|rel_path| manifest_dir.join(rel_path))
}