From c7f7366f323c9cd300bff949c2cd7de1eb7aa91d Mon Sep 17 00:00:00 2001 From: Sporif Date: Sun, 6 Mar 2022 01:17:13 +0000 Subject: [PATCH] Fix cross compilation with clang-cl --- build.rs | 68 ++++++++++++++++++++++--------- c/blake3_c_rust_bindings/build.rs | 63 ++++++++++++++++++---------- 2 files changed, 91 insertions(+), 40 deletions(-) diff --git a/build.rs b/build.rs index a5dfd0625..f2ee3e658 100644 --- a/build.rs +++ b/build.rs @@ -43,6 +43,23 @@ fn is_x86_64() -> bool { target_components()[0] == "x86_64" } +fn is_windows_target() -> bool { + env::var("CARGO_CFG_TARGET_OS").unwrap() == "windows" +} + +fn use_msvc_asm() -> bool { + // cc assumes if it is passed .asm and targetting MSVC that it can use the + // Microsoft assemblers, which isn't true when we're not on a Windows + // host, but are cross-compiling with clang-cl, so we explicitly check if + // we're on a Windows host (with the assumption they'll have the MSVC + // toolchain installed if they are, though that's not necessarily true) + if env::var("CARGO_CFG_TARGET_ENV").unwrap_or_default() == "gnu" { + false + } else { + env::var("HOST").unwrap_or_default().contains("-windows-") + } +} + fn is_x86_32() -> bool { let arch = &target_components()[0]; arch == "i386" || arch == "i586" || arch == "i686" @@ -161,14 +178,16 @@ fn build_sse2_sse41_avx2_assembly() { println!("cargo:rustc-cfg=blake3_sse41_ffi"); println!("cargo:rustc-cfg=blake3_avx2_ffi"); let mut build = new_build(); - if is_windows_msvc() { - build.file("c/blake3_sse2_x86-64_windows_msvc.asm"); - build.file("c/blake3_sse41_x86-64_windows_msvc.asm"); - build.file("c/blake3_avx2_x86-64_windows_msvc.asm"); - } else if is_windows_gnu() { - build.file("c/blake3_sse2_x86-64_windows_gnu.S"); - build.file("c/blake3_sse41_x86-64_windows_gnu.S"); - build.file("c/blake3_avx2_x86-64_windows_gnu.S"); + if is_windows_target() { + if use_msvc_asm() { + build.file("c/blake3_sse2_x86-64_windows_msvc.asm"); + build.file("c/blake3_sse41_x86-64_windows_msvc.asm"); + build.file("c/blake3_avx2_x86-64_windows_msvc.asm"); + } else { + build.file("c/blake3_sse2_x86-64_windows_gnu.S"); + build.file("c/blake3_sse41_x86-64_windows_gnu.S"); + build.file("c/blake3_avx2_x86-64_windows_gnu.S"); + } } else { // All non-Windows implementations are assumed to support // Linux-style assembly. These files do contain a small @@ -205,19 +224,21 @@ fn build_avx512_assembly() { assert!(is_x86_64()); println!("cargo:rustc-cfg=blake3_avx512_ffi"); let mut build = new_build(); - if is_windows_msvc() { - build.file("c/blake3_avx512_x86-64_windows_msvc.asm"); - } else { - if is_windows_gnu() { - build.file("c/blake3_avx512_x86-64_windows_gnu.S"); + let mut is_msvc = false; + if is_windows_target() { + if use_msvc_asm() { + build.file("c/blake3_avx512_x86-64_windows_msvc.asm"); + is_msvc = true; } else { - // All non-Windows implementations are assumed to support Linux-style - // assembly. These files do contain a small explicit workaround for - // macOS also. - build.file("c/blake3_avx512_x86-64_unix.S"); + build.file("c/blake3_avx512_x86-64_windows_gnu.S"); } - // Older versions of Clang require these flags, even for assembly. See - // https://github.com/BLAKE3-team/BLAKE3/issues/79. + } else { + build.file("c/blake3_avx512_x86-64_unix.S"); + } + + // Older versions of Clang require these flags, even for assembly. See + // https://github.com/BLAKE3-team/BLAKE3/issues/79. + if !is_msvc { build.flag("-mavx512f"); build.flag("-mavx512vl"); } @@ -293,5 +314,14 @@ fn main() -> Result<(), Box> { ); } + // When compiling with clang-cl for windows, it adds .asm files to the root + // which we need to delete so cargo doesn't get angry + if is_windows_target() && !use_msvc_asm() { + let _ = std::fs::remove_file("blake3_avx2_x86-64_windows_gnu.asm"); + let _ = std::fs::remove_file("blake3_avx512_x86-64_windows_gnu.asm"); + let _ = std::fs::remove_file("blake3_sse2_x86-64_windows_gnu.asm"); + let _ = std::fs::remove_file("blake3_sse41_x86-64_windows_gnu.asm"); + } + Ok(()) } diff --git a/c/blake3_c_rust_bindings/build.rs b/c/blake3_c_rust_bindings/build.rs index 624dbb971..357e1ab5b 100644 --- a/c/blake3_c_rust_bindings/build.rs +++ b/c/blake3_c_rust_bindings/build.rs @@ -13,6 +13,23 @@ fn is_x86_64() -> bool { target_components()[0] == "x86_64" } +fn is_windows_target() -> bool { + env::var("CARGO_CFG_TARGET_OS").unwrap() == "windows" +} + +fn use_msvc_asm() -> bool { + // cc assumes if it is passed .asm and targetting MSVC that it can use the + // Microsoft assemblers, which isn't true when we're not on a Windows + // host, but are cross-compiling with clang-cl, so we explicitly check if + // we're on a Windows host (with the assumption they'll have the MSVC + // toolchain installed if they are, though that's not necessarily true) + if env::var("CARGO_CFG_TARGET_ENV").unwrap_or_default() == "gnu" { + false + } else { + env::var("HOST").unwrap_or_default().contains("-windows-") + } +} + fn is_x86_32() -> bool { let arch = &target_components()[0]; arch == "i386" || arch == "i586" || arch == "i686" @@ -37,13 +54,6 @@ fn is_windows_msvc() -> bool { && target_components()[3] == "msvc" } -fn is_windows_gnu() -> bool { - // Some targets are only two components long, so check in steps. - target_components()[1] == "pc" - && target_components()[2] == "windows" - && target_components()[3] == "gnu" -} - fn new_build() -> cc::Build { let mut build = cc::Build::new(); if !is_windows_msvc() { @@ -73,20 +83,22 @@ fn main() -> Result<(), Box> { if is_x86_64() && !defined("CARGO_FEATURE_PREFER_INTRINSICS") { // On 64-bit, use the assembly implementations, unless the // "prefer_intrinsics" feature is enabled. - if is_windows_msvc() { - let mut build = new_build(); - build.file(c_dir_path("blake3_sse2_x86-64_windows_msvc.asm")); - build.file(c_dir_path("blake3_sse41_x86-64_windows_msvc.asm")); - build.file(c_dir_path("blake3_avx2_x86-64_windows_msvc.asm")); - build.file(c_dir_path("blake3_avx512_x86-64_windows_msvc.asm")); - build.compile("blake3_asm"); - } else if is_windows_gnu() { - let mut build = new_build(); - build.file(c_dir_path("blake3_sse2_x86-64_windows_gnu.S")); - build.file(c_dir_path("blake3_sse41_x86-64_windows_gnu.S")); - build.file(c_dir_path("blake3_avx2_x86-64_windows_gnu.S")); - build.file(c_dir_path("blake3_avx512_x86-64_windows_gnu.S")); - build.compile("blake3_asm"); + if is_windows_target() { + if use_msvc_asm() { + let mut build = new_build(); + build.file(c_dir_path("blake3_sse2_x86-64_windows_msvc.asm")); + build.file(c_dir_path("blake3_sse41_x86-64_windows_msvc.asm")); + build.file(c_dir_path("blake3_avx2_x86-64_windows_msvc.asm")); + build.file(c_dir_path("blake3_avx512_x86-64_windows_msvc.asm")); + build.compile("blake3_asm"); + } else { + let mut build = new_build(); + build.file(c_dir_path("blake3_sse2_x86-64_windows_gnu.S")); + build.file(c_dir_path("blake3_sse41_x86-64_windows_gnu.S")); + build.file(c_dir_path("blake3_avx2_x86-64_windows_gnu.S")); + build.file(c_dir_path("blake3_avx512_x86-64_windows_gnu.S")); + build.compile("blake3_asm"); + } } else { // All non-Windows implementations are assumed to support // Linux-style assembly. These files do contain a small @@ -186,5 +198,14 @@ fn main() -> Result<(), Box> { ); } + // When compiling with clang-cl for windows, it adds .asm files to the root + // which we need to delete so cargo doesn't get angry + if is_windows_target() && !use_msvc_asm() { + let _ = std::fs::remove_file("blake3_avx2_x86-64_windows_gnu.asm"); + let _ = std::fs::remove_file("blake3_avx512_x86-64_windows_gnu.asm"); + let _ = std::fs::remove_file("blake3_sse2_x86-64_windows_gnu.asm"); + let _ = std::fs::remove_file("blake3_sse41_x86-64_windows_gnu.asm"); + } + Ok(()) }