diff --git a/src-tauri/build.rs b/src-tauri/build.rs index 5f3480f0..5439d8cf 100644 --- a/src-tauri/build.rs +++ b/src-tauri/build.rs @@ -11,20 +11,27 @@ fn main() { let target_env = std::env::var("CARGO_CFG_TARGET_ENV").unwrap_or_default(); if target_os == "windows" && target_env == "gnu" { - let out_dir = std::env::var("OUT_DIR").unwrap(); - let obj_path = format!("{}/memset_shim.o", out_dir); + let out_dir = std::env::var("OUT_DIR").expect("OUT_DIR not set"); + let obj_path = format!("{out_dir}/memset_s_shim.o"); - cc::Build::new() - .file("memset_s_shim.c") - .define("WIN32", None) - .define("__WIN32__", None) - .out_dir(&out_dir) - .compile("memset_shim"); + // Compile directly to a .o file and link it as a positional linker arg. + // This sidesteps the static-archive ordering problem: a bare -l flag only + // pulls symbols that are already undefined at that point in the link, + // but libsodium's reference to memset_explicit comes later. A positional + // object file is always included unconditionally. + let compiler = cc::Build::new().get_compiler(); + let status = compiler + .to_command() + .args(["-DWIN32", "-D__WIN32__", "-c"]) + .arg("-o") + .arg(&obj_path) + .arg("memset_s_shim.c") + .status() + .expect("failed to invoke C compiler for memset_s_shim.c"); + assert!(status.success(), "failed to compile memset_s_shim.c"); println!("cargo:rerun-if-changed=memset_s_shim.c"); - // Directly link the object file instead of using -l flag - // This ensures the symbol is available regardless of link order - println!("cargo:rustc-link-arg={}", obj_path); + println!("cargo:rustc-link-arg={obj_path}"); } tauri_build::build()