fn main() { // Ensure MinGW tools are on PATH for build scripts (windres, dlltool, etc.) let mingw_bin = "C:/Users/lashman/mingw-w64/mingw64/bin"; if let Ok(current_path) = std::env::var("PATH") { std::env::set_var("PATH", format!("{};{}", mingw_bin, current_path)); } else { std::env::set_var("PATH", mingw_bin); } // On GNU targets, replace the WebView2Loader import library with the static // library so the loader is baked into the exe — no DLL to ship. if std::env::var("CARGO_CFG_TARGET_ENV").as_deref() == Ok("gnu") { swap_webview2_to_static(); } tauri_build::build(); // When targeting GNU, embed-resource may find MSVC's rc.exe (via Windows // SDK) and produce a .res file instead of COFF .o. GNU ld can't link .res // files. Fix: re-compile with windres if needed. // Note: cfg() in build scripts checks the HOST, not target. Use env var. if std::env::var("CARGO_CFG_TARGET_ENV").as_deref() == Ok("gnu") { fix_resource_lib(); } } /// If resource.lib is in .res format (produced by MSVC rc.exe), re-compile /// the .rc source with MinGW windres to produce a COFF object that GNU ld /// can link. fn fix_resource_lib() { use std::path::PathBuf; use std::process::Command; let out_dir = std::env::var("OUT_DIR").unwrap_or_default(); let out_path = PathBuf::from(&out_dir); let rc_file = out_path.join("resource.rc"); let lib_file = out_path.join("resource.lib"); if !rc_file.exists() || !lib_file.exists() { return; } // Check if the file is already COFF (starts with COFF machine type or // archive signature). A .res file starts with 0x00000000. if let Ok(header) = std::fs::read(&lib_file) { if header.len() >= 4 && header[0..4] == [0, 0, 0, 0] { // This is a .res file, not COFF — re-compile with windres let windres = "C:/Users/lashman/mingw-w64/mingw64/bin/windres.exe"; let status = Command::new(windres) .args([ "-i", &rc_file.to_string_lossy(), "-o", &lib_file.to_string_lossy(), "--output-format=coff", ]) .status(); match status { Ok(s) if s.success() => { println!("cargo:warning=Re-compiled resource.rc with windres (COFF output)"); } Ok(s) => { println!("cargo:warning=windres failed with exit code: {}", s); } Err(e) => { println!("cargo:warning=Failed to run windres: {}", e); } } } } } /// Replace `WebView2Loader.dll.lib` (dynamic import lib) with the contents of /// `WebView2LoaderStatic.lib` (static archive) in the webview2-com-sys build /// output. The linker then statically links the WebView2 loader code, removing /// the runtime dependency on WebView2Loader.dll. fn swap_webview2_to_static() { use std::fs; use std::path::PathBuf; let out_dir = std::env::var("OUT_DIR").unwrap_or_default(); // OUT_DIR = target/.../build/core-cooldown-HASH/out // We need: target/.../build/ (two levels up) let build_dir = PathBuf::from(&out_dir) .parent() // core-cooldown-HASH .and_then(|p| p.parent()) // build/ .map(|p| p.to_path_buf()); let build_dir = match build_dir { Some(d) => d, None => return, }; let target_arch = match std::env::var("CARGO_CFG_TARGET_ARCH") .unwrap_or_default() .as_str() { "x86_64" => "x64", "x86" => "x86", "aarch64" => "arm64", _ => return, }; let entries = match fs::read_dir(&build_dir) { Ok(e) => e, Err(_) => return, }; for entry in entries.flatten() { let name = entry.file_name(); let name = name.to_string_lossy(); if !name.starts_with("webview2-com-sys-") { continue; } let lib_dir = entry.path().join("out").join(target_arch); let import_lib = lib_dir.join("WebView2Loader.dll.lib"); let static_lib = lib_dir.join("WebView2LoaderStatic.lib"); if static_lib.exists() && import_lib.exists() { if let Ok(static_bytes) = fs::read(&static_lib) { match fs::write(&import_lib, &static_bytes) { Ok(_) => println!( "cargo:warning=Swapped WebView2Loader to static linking ({})", lib_dir.display() ), Err(e) => println!( "cargo:warning=Failed to swap WebView2Loader lib: {}", e ), } } } } }