The #[cfg(target_env = "gnu")] attribute in build.rs checks the host compiler environment, not the build target. On MSVC-hosted Rust targeting x86_64-pc-windows-gnu, this was silently false, causing: 1. WebView2Loader static linking swap to never run 2. Resource compilation fix (windres COFF output) to never run embed-resource finds MSVC's rc.exe via Windows SDK and produces .res files that GNU ld can't link. Fix: detect .res format (null header) and re-compile with MinGW windres --output-format=coff.
135 lines
4.7 KiB
Rust
135 lines
4.7 KiB
Rust
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
|
|
),
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|