extern crate cc; fn find_assembly( arch: &str, endian: &str, os: &str, env: &str, masm: bool, ) -> Option<(&'static str, bool)> { match (arch, endian, os, env) { // The implementations for stack switching exist, but, officially, doing so without Fibers // is not supported in Windows. For x86_64 the implementation actually works locally, // but failed tests in CI (???). Might want to have a feature for experimental support // here. ("x86", _, "windows", "msvc") => { if masm { Some(("src/arch/x86_msvc.asm", false)) } else { Some(("src/arch/x86_windows_gnu.s", false)) } } ("x86_64", _, "windows", "msvc") => { if masm { Some(("src/arch/x86_64_msvc.asm", false)) } else { Some(("src/arch/x86_64_windows_gnu.s", false)) } } ("arm", _, "windows", "msvc") => Some(("src/arch/arm_armasm.asm", false)), ("aarch64", _, "windows", "msvc") => { if masm { Some(("src/arch/aarch64_armasm.asm", false)) } else { Some(("src/arch/aarch_aapcs64.s", false)) } } ("x86", _, "windows", _) => Some(("src/arch/x86_windows_gnu.s", false)), ("x86_64", _, "windows", _) => Some(("src/arch/x86_64_windows_gnu.s", false)), ("x86", _, _, _) => Some(("src/arch/x86.s", true)), ("x86_64", _, _, _) => Some(("src/arch/x86_64.s", true)), ("arm", _, _, _) => Some(("src/arch/arm_aapcs.s", true)), ("aarch64", _, _, _) => Some(("src/arch/aarch_aapcs64.s", true)), ("powerpc", _, _, _) => Some(("src/arch/powerpc32.s", true)), ("powerpc64", "little", _, _) => Some(("src/arch/powerpc64_openpower.s", true)), ("powerpc64", _, _, _) => Some(("src/arch/powerpc64.s", true)), ("s390x", _, _, _) => Some(("src/arch/zseries_linux.s", true)), ("mips", _, _, _) => Some(("src/arch/mips_eabi.s", true)), ("mips64", _, _, _) => Some(("src/arch/mips64_eabi.s", true)), ("sparc64", _, _, _) => Some(("src/arch/sparc64.s", true)), ("sparc", _, _, _) => Some(("src/arch/sparc_sysv.s", true)), ("riscv32", _, _, _) => Some(("src/arch/riscv.s", true)), ("riscv64", _, _, _) => Some(("src/arch/riscv64.s", true)), ("wasm32", _, _, _) => Some(("src/arch/wasm32.o", true)), _ => None, } } fn main() { let arch = ::std::env::var("CARGO_CFG_TARGET_ARCH").unwrap(); let env = ::std::env::var("CARGO_CFG_TARGET_ENV").unwrap(); let os = ::std::env::var("CARGO_CFG_TARGET_OS").unwrap(); let endian = ::std::env::var("CARGO_CFG_TARGET_ENDIAN").unwrap(); // We are only assembling a single file and any flags in the environment probably // don't apply in this case, so we don't want to use them. Unfortunately, cc // doesn't provide a way to clear/ignore flags set from the environment, so // we manually remove them instead for key in std::env::vars().filter_map(|(k, _)| if k.contains("CFLAGS") { Some(k) } else { None }) { std::env::remove_var(key); } let mut cfg = cc::Build::new(); let msvc = cfg.get_compiler().is_like_msvc(); let asm = if let Some((asm, canswitch)) = find_assembly(&arch, &endian, &os, &env, msvc) { println!("cargo:rustc-cfg=asm"); if canswitch { println!("cargo:rustc-cfg=switchable_stack") } asm } else { println!( "cargo:warning=Target {}-{}-{} has no assembly files!", arch, os, env ); return; }; if !msvc { cfg.flag("-xassembler-with-cpp"); cfg.define(&*format!("CFG_TARGET_OS_{}", os), None); cfg.define(&*format!("CFG_TARGET_ARCH_{}", arch), None); cfg.define(&*format!("CFG_TARGET_ENV_{}", env), None); } // For wasm targets we ship a precompiled `*.o` file so we just pass that // directly to `ar` to assemble an archive. Otherwise we're actually // compiling the source assembly file. if asm.ends_with(".o") { cfg.object(asm); } else { cfg.file(asm); } cfg.compile("libpsm_s.a"); }