fix: build.rs cfg() checks HOST not TARGET - use CARGO_CFG_TARGET_ENV

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.
This commit is contained in:
Your Name
2026-02-18 18:53:33 +02:00
parent 8a04edc2bc
commit d26b73288d

View File

@@ -9,17 +9,70 @@ fn main() {
// On GNU targets, replace the WebView2Loader import library with the static
// library so the loader is baked into the exe — no DLL to ship.
#[cfg(target_env = "gnu")]
if std::env::var("CARGO_CFG_TARGET_ENV").as_deref() == Ok("gnu") {
swap_webview2_to_static();
}
tauri_build::build()
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.
#[cfg(target_env = "gnu")]
fn swap_webview2_to_static() {
use std::fs;
use std::path::PathBuf;