-
Notifications
You must be signed in to change notification settings - Fork 779
build: Only replace cl.exe with clang-cl for ARM64 Windows builds
#2216
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
build: Only replace cl.exe with clang-cl for ARM64 Windows builds
#2216
Conversation
briansmith
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In ci.yml, we have (twice):
- if: ${{ matrix.target == 'aarch64-pc-windows-msvc' }}
run: |
echo "C:\Program Files (x86)\Microsoft Visual Studio\2019\Enterprise\VC\Tools\Llvm\x64\bin" >> $GITHUB_PATH
When using clang-cl, is this still necessary, or is clang-cl already in the path in GitHub actions?
If clang-cl is more common and clang-cl is already in the path, then we should remove this from ci.yml.
We should also update BUILDING.md "For Windows ARM64 targets..." to describe the updated situation.
build.rs
Outdated
| && !compiler.is_like_clang() | ||
| && !compiler.is_like_clang_cl() | ||
| { | ||
| c.compiler("clang"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we start defaulting to clang-cl instead?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps. If users are more commonly compiling for Windows MSVC than Windows GNU, arbitrarily replacing their requested compiler with clang-cl whose arguments are compatible with cl.exe seems a lot less error-prone than giving them the clang interface. Any cl.exe-specific argument in their CFLAGS (my issue: #2215) and this fails to compile.
Either way, overwriting compilers - which might have been carefully set up via CC environment flags etc (to not have to rely on PATH!) - seems very painful. As said below, having ring compile natively with cl.exe would be awesome. At least it's isolated to ARM64 Windows though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
At the time, cl.exe didn't have uint128_t and probably there were other issues too. Maybe BoringSSL actually made some changes upstream to avoid requiring uint128_t for the ECC code? If so, then we can probably start supporting cl.exe. Definitely, I would love it, and I think there's already an issue for it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cool - I'll try to cross-compile with cl.exe from my Windows X64 machine to find out and document what specifically is holding it back if at all.
At the same time I'm inquiring to get access to an ARM64 Windows machine soon, to test what happens when natively compiling on that machine.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
|
In the commit message:
here and elsewhere you use the word "overwrite" when I think "override" is the better word.
I suggest instead we say "When this is done,".
Most likely, we need to modify our compiler flag handling in build.rs to pass the correct flags to clang-cl.
IIRC, when I tried it, clang-cl couldn't compile the assembly source files, which is why we hard-code clang. We need to modify ci.yml to add the clang-cl-based configuration. I also think that, assuming it works "equally well," we should default to the clang-cl-based build (instead of clang) when we detect the C compiler is MSVC and the target is aarch64. |
clang-cl with clang for ARM64 Windows buildsclang-cl with clang for ARM64 Windows builds
This PR is solely about supporting a cross-compile from Linux (for #2215), and I have no clue about a "native" cross-compile from Windows->Windows (barring the architecture). If you want to know this for sure, I'd have to boot into a Windows machine for some experimentation. It seems very unlikely that
I don't think much is changing, or supposed to be changed here. All this PR really is about, is making the constraints for this As above, if we're "blindly" replacing the compiler command with The best course of action would be if this project could natively compile for |
Agreed. It doesn't overwrite the compiler, but it does "overwrite" or "overrule" a
NAK. I didn't introduce the idea of "overwrite the compiler with
As above, if we assume that user flags are more likely compatible with I do think we can be more strict here. We're going to expose the match compiler.family() {
// The workaround
ToolFamily::Msvc { clang_cl: false } => c.compiler("clang-cl"),
ToolFamily::Msvc { clang_cl: true } | ToolFamily::Clang { .. } => {},
ToolFamily::Gnu { .. } => todo!("Test this"),
}
Curious what that entails. For me it failed only because of warnings forced as errors in the Line 314 in d2e401f
Sure let's always use |
In the issue, you mentioned:
Of course, we require C99 at least, so we need to change build.rs to tell clang-cl to use the right version of C. You can see here we have: So, when the compiler is clang-cl, we need to pass the clang-cl equivalent of In the issue, you also mentioned:
Obviously, this is pretty concerning and I'd like to prioritize addressing it. The reason we have all of these warnings enabled in the .git build is precisely to ensure compatibility with the compilers we support. If we're adding support for a new compiler, as we are here with clang-cl, then we need to have CI test this configuration. Which means doing the |
It is introduced by the subject line "Don't override clang-cl with clang for ARM64 Windows builds." |
59f3144 to
9608023
Compare
This comment was marked as resolved.
This comment was marked as resolved.
clang-cl with clang for ARM64 Windows buildscl.exe with clang-cl for ARM64 Windows builds
| 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" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this where clang-cl lives?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's part of the LLVM toolchain. On Linux machines, yes. On Windows: probably?
build.rs
Outdated
| let compiler = if target.os == WINDOWS && target.arch == AARCH64 && !compiler.is_like_clang() { | ||
| let _ = c.compiler("clang"); | ||
| c.get_compiler() | ||
| // FIXME: On Windows AArch64 we currently must use LLVM (clang-cl) to compile C code |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should say "clang or clang-cl" instead of "clang-cl" here. I think we should add a comment "If the compiler is MSVC, switch to clang-cl so that CFLAGS, etc., are more likely to be compatible."
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I had that at first, but considered that the weight is mostly on the file being compiled via an LLVM toolchain. Whether the compiler/argument "driver" is clang or clang-cl doesn't matter, but you're right that I could comment this better in the match arms.
|
I've rewritten the patch and description:
Note that this means we have the following targets to add to CI:
|
9608023 to
ac6451a
Compare
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## main #2216 +/- ##
==========================================
+ Coverage 97.02% 97.16% +0.13%
==========================================
Files 160 158 -2
Lines 20391 20330 -61
Branches 458 455 -3
==========================================
- Hits 19785 19754 -31
+ Misses 498 471 -27
+ Partials 108 105 -3 ☔ View full report in Codecov by Sentry. |
ac6451a to
3fac180
Compare
Going all the way back to this, I'm confused by the CI setup: For the For the "twice" case you mentioned, in |
3fac180 to
d44f9d1
Compare
d44f9d1 to
ce7d500
Compare
This comment was marked as resolved.
This comment was marked as resolved.
ce7d500 to
80f1285
Compare
|
Regarding availability of Before however, our |
0c55005 to
b16e53e
Compare
612555f to
f3ac558
Compare
|
@briansmith At this stage this PR is a hand full of buildflag changes only and we've been running with it (and cross compiling with this PR) for about 6 months ourselves already. Would it be possible to get this merged into mainline or are there still significant objections to the content of the PR? |
a92005a to
e08508e
Compare
This comment was marked as outdated.
This comment was marked as outdated.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Your changes for which warnings to disable goes far too far - silencing all warnings being produced indiscriminately is not the way. The two extra warnings this PR now silences should really be errors from a Rust perspective because they are the compiler telling you about legitimate bugs. Using reserved identifiers the compiler may itself be using, accessing buffers in a way that it is finding via static analysis likely leads to a buffer overflow (this is what unsafe buffer usage implies).
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.
`is_msvc_not_clang_cl` is already defined above through a recent change.
`/Wall` is treated differently on `clang-cl` versus `cl.exe`, requiring different warnings to be configured.
e08508e to
2cc722a
Compare
|
We would love to see this merged into mainline as well in order to unblock some of our builds on the |
|
@briansmith is there anything we can do to further this PR? I could rebase it if it helps, but there are no conflicts at the moment. |
Fixes #2215
Caution
This change depends on rust-lang/cc-rs#1357.
When cross-compiling to Windows from Linux or similar, it's common to use the
clang-cldriver from the LLVM toolchain which supports parsingcl.exe-like arguments.Ring however doesn't seem to compile for ARM64 Windows using
cl.exe, and contains a// FIXME-style workaround to useclangto compile its C files instead.The command-line interface for
clangisn't always compatible with that ofcl.exeandclang-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-vctoolsdirand-winsdkdirinCFLAGS. In such a setup this workaround inringwould pass those arguments toclang, resulting in "unknown argument" errors.cc-rscan 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 withclang-cl, nothing has to be replaced. In the end, all this entails is changing the workaround to not compile withclang, but withclang-clinstead.