Skip to content

Commit 80f1285

Browse files
committed
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-cl`, 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.
1 parent 2723abb commit 80f1285

File tree

2 files changed

+20
-12
lines changed

2 files changed

+20
-12
lines changed

BUILDING.md

+3-1
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,11 @@ edition of Visual Studio, like Community, Standard, or Enterprise). The
2222
“Desktop development with C++” workflow must be installed. Visual Studio
2323
2022 Version 17.5 is supported; earlier versions of Visual Studio may work.
2424

25+
### (Cross-)compiling to Windows ARM64
26+
2527
For Windows ARM64 targets (aarch64-pc-windows-msvc), the Visual Studio Build
2628
Tools “VS 2022 C++ ARM64 build tools” and "clang" components must be installed.
27-
Add Microsoft's provided version of `clang` to `%PATH%`, which will allow the
29+
Add Microsoft's provided version of `clang-cl` to `%PATH%`, which will allow the
2830
build to work in GitHub Actions without installing anything:
2931
```
3032
$env:Path += ";C:\Program Files (x86)\Microsoft Visual Studio\2022\Enterprise\VC\Tools\Llvm\x64\bin"

build.rs

+17-11
Original file line numberDiff line numberDiff line change
@@ -148,10 +148,8 @@ fn cpp_flags(compiler: &cc::Tool) -> &'static [&'static str] {
148148
NON_MSVC_FLAGS
149149
} else {
150150
static MSVC_FLAGS: &[&str] = &[
151+
"/std:c11",
151152
"/Gy", // Enable function-level linking.
152-
"/Zc:wchar_t",
153-
"/Zc:forScope",
154-
"/Zc:inline",
155153
// Warnings.
156154
"/Wall",
157155
"/wd4127", // C4127: conditional expression is constant
@@ -162,6 +160,11 @@ fn cpp_flags(compiler: &cc::Tool) -> &'static [&'static str] {
162160
"/wd4820", // C4820: <struct>: <n> bytes padding added after <name>
163161
"/wd5045", /* C5045: Compiler will insert Spectre mitigation for memory load if
164162
* /Qspectre switch specified */
163+
"-Wno-declaration-after-statement",
164+
"-Wno-pre-c11-compat",
165+
"-Wno-reserved-macro-identifier", // Stuff in asm_base.h
166+
"-Wno-switch-default",
167+
"-Wno-unsafe-buffer-usage",
165168
];
166169
MSVC_FLAGS
167170
}
@@ -559,9 +562,15 @@ fn obj_path(out_dir: &Path, src: &Path) -> PathBuf {
559562

560563
fn configure_cc(c: &mut cc::Build, target: &Target, c_root_dir: &Path, include_dir: &Path) {
561564
let compiler = c.get_compiler();
562-
// FIXME: On Windows AArch64 we currently must use Clang to compile C code
563-
let compiler = if target.os == WINDOWS && target.arch == AARCH64 && !compiler.is_like_clang() {
564-
let _ = c.compiler("clang");
565+
let is_msvc_not_clang_cl = compiler.is_like_msvc() && !compiler.is_like_clang_cl();
566+
567+
// FIXME: On Windows AArch64, ring C code cannot be compiled using cl.exe, but must be compiled
568+
// using the LLVM toolchain. Use clang-cl, which is compatible with flags that are already in
569+
// place (i.e. custom CFLAGS that the user provided to cc).
570+
let compiler = if target.os == WINDOWS && target.arch == AARCH64 && is_msvc_not_clang_cl {
571+
// FIXME: This requires clang-cl to be available in PATH, regardless of any explicit
572+
// or custom path that the user might have provided to cc via the CC flag.
573+
c.compiler("clang-cl");
565574
c.get_compiler()
566575
} else {
567576
compiler
@@ -584,11 +593,8 @@ fn configure_cc(c: &mut cc::Build, target: &Target, c_root_dir: &Path, include_d
584593
let _ = c.define("NDEBUG", None);
585594
}
586595

587-
if target.arch == X86 {
588-
let is_msvc_not_clang_cl = compiler.is_like_msvc() && !compiler.is_like_clang_cl();
589-
if !is_msvc_not_clang_cl {
590-
let _ = c.flag("-msse2");
591-
}
596+
if target.arch == X86 && !is_msvc_not_clang_cl {
597+
let _ = c.flag("-msse2");
592598
}
593599

594600
// Allow cross-compiling without a target sysroot for these targets.

0 commit comments

Comments
 (0)