use std::env;
use std::fs;
use std::io;
use std::path::PathBuf;
use std::process::Command;
fn main() -> io::Result<()> {
println!("cargo:rerun-if-changed=build.rs");
println!("cargo:rerun-if-changed=icon.ico");
println!("cargo:rerun-if-changed=app.manifest");
println!("cargo:rerun-if-changed=app.debug.manifest");
println!("cargo:rerun-if-env-changed=APP_VERSION");
let version = env::var("APP_VERSION").unwrap_or_else(|_| {
let mut v = String::from("v0.0.0-local");
if cfg!(target_os = "windows") {
if let Ok(output) = Command::new("powershell")
.args(["-NoProfile", "-Command", "Get-Date -Format 'vyyyy.MM.dd-HHmm'"])
.output()
{
if output.status.success() {
if let Ok(s) = String::from_utf8(output.stdout) {
let trimmed = s.trim();
if !trimmed.is_empty() {
v = trimmed.to_string();
}
}
}
}
}
v
});
println!("cargo:rustc-env=APP_VERSION={}", version);
#[cfg(target_os = "windows")]
compile_resources()?;
Ok(())
}
#[cfg(target_os = "windows")]
fn compile_resources() -> io::Result<()> {
let out_dir = PathBuf::from(env::var("OUT_DIR").unwrap());
let profile = env::var("PROFILE").unwrap_or_else(|_| "debug".to_string());
let manifest = if profile == "release" {
"app.manifest"
} else {
"app.debug.manifest"
};
let manifest_dir = PathBuf::from(env::var("CARGO_MANIFEST_DIR").unwrap());
let icon_path = manifest_dir.join("icon.ico");
let manifest_path = manifest_dir.join(manifest);
let rc_content = format!(
r#"// Auto-generated resource file - CompactRS
// Icon resource (ID 1)
1 ICON "{}"
// Manifest resource (ID 1, type 24 = RT_MANIFEST)
1 24 "{}"
"#,
icon_path.to_string_lossy().replace('\\', "\\\\"),
manifest_path.to_string_lossy().replace('\\', "\\\\")
);
let rc_path = out_dir.join("resource.rc");
fs::write(&rc_path, &rc_content)?;
let rc_exe = find_rc_exe().ok_or_else(|| {
io::Error::new(io::ErrorKind::NotFound, "Could not find rc.exe")
})?;
let res_path = out_dir.join("resource.res");
let status = Command::new(&rc_exe)
.arg("/nologo")
.arg("/fo")
.arg(&res_path)
.arg(&rc_path)
.status()?;
if !status.success() {
return Err(io::Error::new(
io::ErrorKind::Other,
format!("rc.exe failed with exit code: {:?}", status.code()),
));
}
println!("cargo:rustc-link-arg-bins={}", res_path.to_string_lossy());
println!("cargo:rustc-link-arg=/ENTRY:WinMainCRTStartup");
println!("cargo:rustc-link-arg=/SUBSYSTEM:WINDOWS");
#[cfg(target_env = "msvc")]
{
println!("cargo:rustc-link-lib=vcruntime");
println!("cargo:rustc-link-lib=ucrt");
}
if profile == "release" {
println!("cargo:rustc-link-arg=/EMITPOGOPHASEINFO"); println!("cargo:rustc-link-arg=/DEBUG:NONE"); }
Ok(())
}
#[cfg(target_os = "windows")]
fn find_rc_exe() -> Option<PathBuf> {
let program_files_x86 = env::var("ProgramFiles(x86)").unwrap_or_else(|_| "C:\\Program Files (x86)".to_string());
let sdk_base = PathBuf::from(program_files_x86).join("Windows Kits\\10\\bin");
if sdk_base.exists() {
if let Ok(entries) = fs::read_dir(&sdk_base) {
let mut versions: Vec<_> = entries
.filter_map(|e| e.ok())
.filter(|e| e.path().is_dir())
.filter(|e| e.file_name().to_string_lossy().starts_with("10."))
.collect();
versions.sort_by(|a, b| b.file_name().cmp(&a.file_name()));
for version in versions {
let rc_path = version.path().join("x64\\rc.exe");
if rc_path.exists() {
return Some(rc_path);
}
}
}
}
if Command::new("rc.exe").arg("/?").output().is_ok() {
return Some(PathBuf::from("rc.exe"));
}
None
}