Skip to content
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

rustc cannot find MSVC on Windows arm64 #83043

Closed
Alovchin91 opened this issue Mar 11, 2021 · 24 comments
Closed

rustc cannot find MSVC on Windows arm64 #83043

Alovchin91 opened this issue Mar 11, 2021 · 24 comments
Labels
O-windows-msvc Toolchain: MSVC, Operating system: Windows

Comments

@Alovchin91
Copy link

Alovchin91 commented Mar 11, 2021

Problem

When building Rust projects on Windows 10 arm64, rustc cannot find MSVC installation to use tools like link.exe.
The reason is because Visual Studio Installer doesn't properly register the installation on arm64.

To determine MSVC installation, rustc uses the great cc-rs crate which itself uses the SetupConfiguration COM component (Microsoft.VisualStudio.Setup.Configuration.Native.dll) to determine the path of Visual Studio (or Visual C++ Build Tools) installation. On Windows 10 arm64, it fails to create an instance of a COM class.

Steps

  1. Install aarch64-pc-windows-msvc toolchain on a Windows 10 arm64 machine
  2. Open cmd.exe and navigate to a Rust project
  3. Run cargo build

Possible Solution(s)

The issue happens because on arm64 VS Installer doesn't register the COM component. To be more precise, it registers the x86 version of the COM component, but there is no arm64 version. Unfortunately Microsoft is not willing to fix the issue, even though it was reported twice, with the reason being that Visual Studio doesn't support running on arm64.

A (rather easy) workaround to the issue is to always run cargo/rustc within the x86_arm64 Developer Console. To do this, the user has to call vcvarsx86_arm64.bat before doing anything else in the console. This way, cc-rs can determine Visual Studio installation from the environment variables.

For rustc itself, a solution could be to first attempt searching in the known VS Installer path (%ProgramFiles(x86)%\Microsoft Visual Studio\Installer) for vswhere.exe on arm64 Windows and, if found, running it to get information about the installed VS instances.

Another option could be spawning a dedicated x86-emulated process that would be able to use the x86 COM component and give the information back to rustc, though this option seems to be an overkill 😅

Meta

rustc --version --verbose:

rustc 1.50.0 (cb75ad5db 2021-02-10)
binary: rustc
commit-hash: cb75ad5db02783e8b0222fee363c5f63f7e2cf5b
commit-date: 2021-02-10
host: aarch64-pc-windows-msvc
release: 1.50.0

Environment:

  • Windows 10 arm64 (20H2)
  • aarch64-pc-windows-msvc toolchain
@ehuss ehuss transferred this issue from rust-lang/cargo Mar 12, 2021
@ehuss
Copy link
Contributor

ehuss commented Mar 12, 2021

Transferred to rust-lang/rust. Cargo isn't responsible for finding or running the linker, that is all done inside rustc.

@Alovchin91 Alovchin91 changed the title Cargo cannot find MSVC on Windows arm64 rustc cannot find MSVC on Windows arm64 Mar 13, 2021
@Alovchin91
Copy link
Author

Alovchin91 commented Mar 13, 2021

Yes, sorry, you're right. For some reason I was sure I found the corresponding code in cargo, but it indeed appears to be in rustc. Thanks!

I'll update the original post accordingly.

@Alovchin91
Copy link
Author

Alovchin91 commented Mar 13, 2021

@alexcrichton Hi, do you think it's best to fix it in rustc or in cc-rs itself? It doesn't feel right to run external processes from a library (cc-rs), but at the same time fixing it in rustc won't fix it for all the other crates that might use it to find MSVC tools 🤔 Given C++ Build Tools 2019 installation, I cannot seem to find any trace of it in the registry.

@alexcrichton
Copy link
Member

I think the best solution would be to update cc to work on arm64 Windows. I don't have a machine myself to test on, though, so I don't know what that would entail. Ideally, though, it would not involve invoking external processes.

@rbtcollins
Copy link
Contributor

I reached out on twitter to MS and established a dialogue - thread here - https://twitter.com/rbtcollins/status/1371451812209909761

@Alovchin91
Copy link
Author

Thanks @rbtcollins !

@alexcrichton I have a machine so it shouldn't be a problem for me to implement the solution. The issue is that apparently there are only 2 ways to get this info, one is the COM component which is not available for an arm64 process, and the other one is vswhere.exe - which in turn uses the same COM component but from an emulated x86 process which works.

Unfortunately, the registry doesn't contain any information about VS16, so the only other way to refrain from calling vswhere.exe is probably just guessing the path for now 🤷

@rbtcollins
Copy link
Contributor

@Alovchin91 good to hear you've got hardware - I did read the bug and links before reaching out on twitter: I've found clear communication can get an effective dialogue happening. Over to you two now :).

@alexcrichton
Copy link
Member

Ah this sounds somewhat familiar, thanks for the info @Alovchin91!

If that's the case then it seems fine to go ahead and just spawn vswhere.exe and run that. I think it's always possible to bypass that execution by setting the right environment variables, and we could possibly have cargo or something similar set the env vars to ensure it's set only once for a whole compilation.

@Alovchin91
Copy link
Author

Alovchin91 commented Mar 16, 2021

Yes, it's actually the only way to run arm64 cargo/rustc on Windows now - using the vsvars.bat which sets the proper environment variables.

I also think that rustc could set the environment variables, though I'd probably call them something special (e.g. RUSTC_LINK_PATH or similar). Or maybe cc-rs should set those? 🤔

I think we could use the following approach then:

  1. Check if the vsvars variables are set (current)

  2. Check if RUSTC/CC_RS env variables are set (new)

  3. Check if the COM component is present (current)

  4. Go find and call vswhere.exe (new)

This could also slightly improve the speed on non-arm64 Windows because of p.2 preventing the creation of a COM object.

What do you think?

@alexcrichton
Copy link
Member

Seems reasonable to me!

@Alovchin91
Copy link
Author

Alovchin91 commented Mar 23, 2021

Okay, so I've implemented a big part of the functionality I think:

https://github.com/Alovchin91/cc-rs/compare/alovchin91/win-arm64

The only thing that's left is the environment variable(s).

And now I have a few questions:

  • It looks like std::env::set_var() sets the variable for the current process only. While I understand the usefulness of caching the result for the current process (e.g. for calling find_vs_version() and find_tool() sequentially or repeatedly), wouldn't it be better to cache the list of instances that we've found in a Once value?

  • The current implementation uses vswhere's functionality to make sure a specific component is installed (-requires <component-id>). While the crate is called cc-rs so we're apparently looking for C/C++ tools, is it something that we really want?

  • vswhere has a -latest switch which together with the -requires switch would allow us to find the exact instance containing the component. Should we use that instead of listing all the installed instances? Or is there any other value in having a list? We could say that it's useful for the case when an instance is broken and thus we cannot find the file even if the component is there, but how rare is such a case?

Also an important point: I'm an enthusiast-level Rust programmer so a thorough code review would be very welcome 😄

@alexcrichton
Copy link
Member

Nice! I agree that set_var should be avoided, and for now I think it's fine to eschew caching and we can add it in if necessary in the future. Otherwise though I don't know a ton about vswhere or all the various flags, so I'm mostly trusting you to figure out good defaults. I don't have a ton to offer in that realm in terms of advice.

@Alovchin91
Copy link
Author

Alovchin91 commented Mar 26, 2021

Sounds good to me! I'll check which option would be the sanest and the simplest code wise and will prepare a PR 👍

@Alovchin91
Copy link
Author

Sorry for the delay; I have opened a Pull Request for cc-rs to use vswhere.exe as a last resort in finding VS2015+ instances:

rust-lang/cc-rs#597

Please give it a strict review 😅 whenever you have time :)

ChrisDenton added a commit to ChrisDenton/rust that referenced this issue May 24, 2021
Recent commits to cc have helped to address rust-lang#83043 and rust-lang#43468
Dylan-DPC-zz pushed a commit to Dylan-DPC-zz/rust that referenced this issue May 26, 2021
Update cc

Recent commits have improved `cc`'s finding of MSVC tools on Windows. In particular it should help to address these issues: rust-lang#83043 and rust-lang#43468
Dylan-DPC-zz pushed a commit to Dylan-DPC-zz/rust that referenced this issue May 27, 2021
Update cc

Recent commits have improved `cc`'s finding of MSVC tools on Windows. In particular it should help to address these issues: rust-lang#83043 and rust-lang#43468
Dylan-DPC-zz pushed a commit to Dylan-DPC-zz/rust that referenced this issue May 27, 2021
Update cc

Recent commits have improved `cc`'s finding of MSVC tools on Windows. In particular it should help to address these issues: rust-lang#83043 and rust-lang#43468
@JohnTitor
Copy link
Member

@ChrisDenton So, #85649 fixed this issue?

@Alovchin91
Copy link
Author

@JohnTitor I'm going to check that today. There was another commit to cc-rs to further improve this, so it might need to be updated again: rust-lang/cc-rs#605

@JohnTitor
Copy link
Member

@Alovchin91 Nice! If rust-lang/cc-rs#597 and rust-lang/cc-rs#605 can close this issue, we need a new release to include the latter.

@Alovchin91
Copy link
Author

@JohnTitor Would the GitHub PR pipeline produce a runnable build? I've never bootstrapped the compiler before and I'm a bit afraid it would take me another week to get it right 😅

@JohnTitor
Copy link
Member

Hmm, IIRC the GHA itself doesn't, but we upload the build artifacts to s3 so it may be possible. But it needs t-infra's help and I'm not sure how hard it is.
The easiest way I think is to update cc crate and try to use a nightly. At least rust-lang/cc-rs#605 fixes one issue and it's worth doing so.
@alexcrichton Any thoughts on this?

@alexcrichton
Copy link
Member

I just published 1.0.69 to make sure all recent changes are published as well.

@JohnTitor
Copy link
Member

Thanks! Opened #87099 to upgrade the cc crate.

JohnTitor added a commit to JohnTitor/rust that referenced this issue Jul 13, 2021
…richton

Upgrade `cc` crate to 1.0.69

This pulls another fix for rust-lang#83043, i.e., rust-lang/cc-rs#605.
r? `@alexcrichton`
JohnTitor added a commit to JohnTitor/rust that referenced this issue Jul 14, 2021
…richton

Upgrade `cc` crate to 1.0.69

This pulls another fix for rust-lang#83043, i.e., rust-lang/cc-rs#605.
r? ``@alexcrichton``
@Alovchin91
Copy link
Author

Sorry for the late reply,

I have used the latest beta (rustc 1.55.0-beta.3 (53fd98ca7 2021-07-31)) to successfully build rustup and tests, so I think this can be pronounced done 🙂

Shall there be future work (e.g. using x64-emulated MSVC on Windows 11 as x64 emulation is significantly faster than x86), I believe it can be tracked in cc-rs repo from now on?

@ChrisDenton ChrisDenton added the O-windows-msvc Toolchain: MSVC, Operating system: Windows label Oct 27, 2022
@ChrisDenton
Copy link
Member

Sounds like a plan.

@Alovchin91
Copy link
Author

Heads up: rust-lang/cc-rs#732

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
O-windows-msvc Toolchain: MSVC, Operating system: Windows
Projects
None yet
Development

No branches or pull requests

6 participants