From d44f9d1022718be41ec0a17d4946be60a0e24fae Mon Sep 17 00:00:00 2001 From: Marijn Suijten Date: Fri, 10 Jan 2025 14:38:46 +0100 Subject: [PATCH] build: Only replace `cl.exe` with `clang-cl` for ARM64 Windows builds When cross-compiling to Windows from Linux or similar, it's common to use the `clang-cl` driver from the LLVM toolchain which supports parsing `cl.exe`-like arguments. Ring however doesn't seem to compile for ARM64 Windows using `cl.exe`, and contains a `// FIXME`-style workaround to use `clang` to compile its C files instead. The command-line interface for `clang` isn't always compatible with that of `cl.exe` and `clang-cl`. There didn't seem to be any trouble with this yet, but when cross-compiling from Linux it's common to explicitly provide "sysroots" via `-vctoolsdir` and `-winsdkdir` in `CFLAGS`. In such a setup this workaround in `ring` would pass those arguments to `clang`, resulting in "unknown argument" errors. `cc-rs` can tell us exactly what compiler it found, and we can use this information to decide how to fill in this workaround. If the user was already compiling their code with `clang`, nothing has to be replaced. In the end, all this entails is changing the workaround to not compile with `clang`, but with `clang-cl` instead. --- BUILDING.md | 4 +++- Cargo.toml | 5 +++++ build.rs | 20 +++++++++++++++++--- 3 files changed, 25 insertions(+), 4 deletions(-) diff --git a/BUILDING.md b/BUILDING.md index 9143841cff..eaacef0537 100644 --- a/BUILDING.md +++ b/BUILDING.md @@ -22,9 +22,11 @@ edition of Visual Studio, like Community, Standard, or Enterprise). The “Desktop development with C++” workflow must be installed. Visual Studio 2022 Version 17.5 is supported; earlier versions of Visual Studio may work. +### (Cross-)compiling to Windows ARM64 + For Windows ARM64 targets (aarch64-pc-windows-msvc), the Visual Studio Build Tools “VS 2022 C++ ARM64 build tools” and "clang" components must be installed. -Add Microsoft's provided version of `clang` to `%PATH%`, which will allow the +Add Microsoft's provided version of `clang-cl` to `%PATH%`, which will allow the build to work in GitHub Actions without installing anything: ``` $env:Path += ";C:\Program Files (x86)\Microsoft Visual Studio\2022\Enterprise\VC\Tools\Llvm\x64\bin" diff --git a/Cargo.toml b/Cargo.toml index 494b708a8d..83deefe323 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -227,3 +227,8 @@ default-members = [ ".", "cavp" ] + +[patch.crates-io] +# https://github.com/rust-lang/cc-rs/pull/1357 +# https://github.com/rust-lang/cc-rs/pull/1358 +cc = { git = "https://github.com/rust-lang/cc-rs", rev = "cc342c5" } diff --git a/build.rs b/build.rs index 740bc27fa1..0e8323a873 100644 --- a/build.rs +++ b/build.rs @@ -147,6 +147,7 @@ fn cpp_flags(compiler: &cc::Tool) -> &'static [&'static str] { NON_MSVC_FLAGS } else { static MSVC_FLAGS: &[&str] = &[ + "/std:c11", "/Gy", // Enable function-level linking. "/Zc:wchar_t", "/Zc:forScope", @@ -547,9 +548,22 @@ fn obj_path(out_dir: &Path, src: &Path) -> PathBuf { fn configure_cc(c: &mut cc::Build, target: &Target, c_root_dir: &Path, include_dir: &Path) { let compiler = c.get_compiler(); - // FIXME: On Windows AArch64 we currently must use Clang to compile C code - let compiler = if target.os == WINDOWS && target.arch == AARCH64 && !compiler.is_like_clang() { - let _ = c.compiler("clang"); + // FIXME: On Windows AArch64, ring C code cannot be compiled using cl.exe, but must be compiled + // using the LLVM toolchain. + let compiler = if target.os == WINDOWS + && target.arch == AARCH64 + // If cl.exe is used, replace that with clang-cl which is most likely to be compatible with + // flags that are already in place (i.e. custom CFLAGS that the user provided to cc). + && matches!( + compiler.family(), + cc::ToolFamily::Msvc { + clang_cl: false, + .. + } + ) { + // FIXME: This requires clang-cl to be available in PATH, regardless of any explicit + // or custom path that the user might have provided to cc via the CC flag. + c.compiler("clang-cl"); c.get_compiler() } else { compiler