diff --git a/zstd-safe/zstd-sys/build.rs b/zstd-safe/zstd-sys/build.rs index b7f7e6b8..94cac29a 100644 --- a/zstd-safe/zstd-sys/build.rs +++ b/zstd-safe/zstd-sys/build.rs @@ -1,5 +1,6 @@ use std::ffi::OsStr; use std::path::{Path, PathBuf}; +use std::process::Command; use std::{env, fmt, fs}; #[cfg(feature = "bindgen")] @@ -210,7 +211,7 @@ fn compile_zstd() { // Hide symbols from resulting library, // so we can be used with another zstd-linking lib. // See https://github.com/gyscos/zstd-rs/issues/58 - if ! cfg!(target_env = "msvc") { + if !cfg!(target_env = "msvc") { config.flag("-fvisibility=hidden"); } config.define("XXH_PRIVATE_API", Some("")); @@ -263,6 +264,76 @@ fn cargo_print(content: &dyn fmt::Display) { } } +fn check_clang_wasm_support() { + // Use cc-rs to find the exact compiler it will use for this target, + // so we probe the same binary that compile_zstd() will invoke. + let compiler = cc::Build::new().get_compiler(); + let clang = compiler.path().to_string_lossy().to_string(); + + // We must attempt actual code generation (not just -fsyntax-only), + // because Apple clang can parse for wasm32 but cannot emit code for it. + let out_dir = PathBuf::from(env::var_os("OUT_DIR").unwrap()); + let test_obj = out_dir.join("__wasm_probe.o"); + + let output = Command::new(compiler.path()) + .args([ + "--target=wasm32-unknown-unknown", + "-x", "c", + "-c", // compile to object (exercises the backend) + "-o", + ]) + .arg(&test_obj) + .arg("-") // read from stdin + .stdin(std::process::Stdio::null()) + .output(); + + match output { + Err(e) => { + panic!( + "\n\n\ + Could not run `{}`: {}\n\ + \n\ + To build for wasm32-unknown-unknown on macOS you need LLVM's clang,\n\ + which ships with wasm32 target support. Fix:\n\ + \n\ + brew install llvm\n\ + export PATH=\"/opt/homebrew/opt/llvm/bin:$PATH\"\n\ + \n\ + Then re-run your build.\n", + clang, e + ); + } + Ok(out) => { + let stderr = String::from_utf8_lossy(&out.stderr); + if stderr + .contains("No available targets are compatible with triple") + { + panic!( + "\n\n\ + The `clang` on your PATH ({}) does not support\n\ + target `wasm32-unknown-unknown`.\n\ + \n\ + This is likely the Apple/Xcode clang, which omits wasm backends.\n\ + Fix by installing LLVM via Homebrew and prepending it to PATH:\n\ + \n\ + brew install llvm\n\ + export PATH=\"/opt/homebrew/opt/llvm/bin:$PATH\"\n\ + \n\ + Then re-run your build.\n\ + \n\ + Alternatively, pin the env var for just this build:\n\ + \n\ + CC=/opt/homebrew/opt/llvm/bin/clang cargo build \ + --target wasm32-unknown-unknown\n", + clang + ); + } + // Probe succeeded — clean up the test object + let _ = fs::remove_file(&test_obj); + } + } +} + fn main() { cargo_print(&"rerun-if-env-changed=ZSTD_SYS_USE_PKG_CONFIG"); @@ -270,6 +341,10 @@ fn main() { std::env::var("CARGO_CFG_TARGET_ARCH").unwrap_or_default(); let target_os = std::env::var("CARGO_CFG_TARGET_OS").unwrap_or_default(); + if target_arch == "wasm32" { + check_clang_wasm_support(); + } + if target_arch == "wasm32" || target_os == "hermit" { cargo_print(&"rustc-cfg=feature=\"std\""); }