Skip to content

Commit

Permalink
Fix cross compilation with clang-cl
Browse files Browse the repository at this point in the history
  • Loading branch information
Sporif authored and oconnor663 committed Nov 19, 2023
1 parent 92e4cd7 commit c7f7366
Show file tree
Hide file tree
Showing 2 changed files with 91 additions and 40 deletions.
68 changes: 49 additions & 19 deletions build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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");
}
Expand Down Expand Up @@ -293,5 +314,14 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
);
}

// 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(())
}
63 changes: 42 additions & 21 deletions c/blake3_c_rust_bindings/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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() {
Expand Down Expand Up @@ -73,20 +83,22 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
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
Expand Down Expand Up @@ -186,5 +198,14 @@ fn main() -> Result<(), Box<dyn std::error::Error>> {
);
}

// 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(())
}

0 comments on commit c7f7366

Please sign in to comment.