Rust on Windows with clang (LLVM) or gcc

I read this which discusses need to build C/C++ dependencies.

I gather that general development requires some external dependencies that require the additional tools, however, to establish a reference point, can pure rust code be written and built without llvm/gnu/msvc tools?

Can LLVM e.g. mingw be used on windows with Rust?

Is information up to date? I.e. Perhaps now, rust has more stand-alone crates that don't require these other language tools?

One of my goals is to get away from visual studio / msvc licensing requirements. If you read the VS/msvc licenses carefully, users are expected to use Visual Studio unless simply building open source dependencies. So that's another reason that knowing why rust needs these tools is helpful. But for C/C++ development in general, I plan to use mingw, with llvm preferred but gcc also OK.

Thank You

1 Like

If you want to develop on Windows, but without the Microsoft toolchains, I think your best bet is to use WSL.

I program with Rust on windows using the x86_64-pc-windows-gnu target.

It's pretty easy and you don't need msvc.
You just need:

then install the rights tools:
pacman -S mingw-w64-ucrt-x86_64-gcc
add C:\msys64\ucrt64\bin to your path

Then it works perfectly (for me).

1 Like

Thank you but I don't think that option supports use of the Windows API.

Thank you for information!

Apparently, llvm is a lower Tier? Interesting information:
[Rustup packages availability on x86_64-pc-windows-gnu]
[Rustup packages availability on x86_64-pc-windows-gnullvm]

This concurs with use of gcc. Does ...windows-gnullvm... correspond to clang?

clang itself is a compiler frontend (for C/C++ language), it is not an ABI specifier, so it is ambiguous when we talk about ABIs. e.g., there's clang-cl which uses the msvc ABI (and can be used with Visual Studio), and there's also clang from the msys2/mingw project, which uses the gnu ABI.

the rust target triplet -windows-gnullvm is similar to -windows-gnu, in that it uses the gnu ABI. the difference is it links against the "modern" ucrt as the C runtime (as opposed to the very old msvcrt), and it uses various LLVM tools/libraries instead of GCC/Binutils.

as of now, this target is still "tier2 without host tools", meaning it can only be cross-compiled.

for Windows target, although it is doable in theory, I strongly discourage cross-compilation. IMO, the preferred toolchain should be the -windows-msvc triplets, but if you don't want -windows-msvc, the alternative -windows-gnu is very good too.

for "pure" rust programs, the experience is mostly the same. even the official windows-rs crate by microsoft supports both targets equally.

the most significant difference between the two, IMO, is when you need some ffi libraries:

  • when using -msvc, the vcpkg tool is very handy and "just works" most of the time.
  • when using -gnu, the best option is usually pacman (and probably integration with pkg-config) of the msys2/mingw project.
  • or in both cases, you can always build from source, if you don't like "package managers".
2 Likes

gnu ABI .. links against the "modern" ucrt

gnu and clang (not clang-cl) have different ABIs?

...LVM tools/libraries

Such as lld, clang-tidy, clang-format ?

when using -msvc, the vcpkg tool is very handy and "just works" most of the time.

The problem for me is the Microsoft license

Thanks kindly for all the information including the great details about vcpkg vs pacman.

for the msys2/mingw project, gcc and clang have the same ABI, and it is called the GNU ABI. if you didn't already, you can read the chapter about Windows of the rustup book.

lld maybe, clang-tidy/clang-format no.

clang-tidy and clang-format are frontend tools based on libclang, which is a language frontend for the C/C++ family. rust only uses the llvm backends.

I don't know the exact details, but the llvm tools that I can think of probably include various "sanitizers" (such as ASan, UBSan), performance profilers, etc.

So gnullvm uses the ucrt? The ucrt is what I'm interested in. I prefer not to use an obsolete c lib. To confirm, currently, the standard gnu toolset for use with Rust on Windows, x86_64-pc-windows-gnu, uses the old msvcrt?

Do Rust crates lessen the importance of the particular crt because they (standard Rust crates) reduce much of the need for use of crt functions?

Thank You!

unfortunately, last time I checked (about half a year ago), it was the case, and I'm pretty sure it still is true as of now. although the msys2 project announced the change of the default environment to ucrt a long time ago.

yes, to some extent. "pure" rust code typically uses rust's standard library, most of them doesn't need direct interface with crt. and rust's standard library is fairly well designed and portable across various operating systems.

but at the end of the day, rust's standard library itself is built on top of libc, which can be thought of as rust bindings to (a subset of) the crt. and for -windows-gnu targets, that crt is (unfortunately) the legacy mscvrt.

but that should be considered an implementation detail, and I believe the rust standard library has been carefully written to work around the legacy stuff, and re-implemented many crt features when neccessary (e.g. it is known to be bad or broken ). so it is not a concern in practice.

...unfortunately, last time I checked (about half a year ago), it was the case,

Yes, this links from mingw-w64 site and the readme is explicit that it uses msvcrt.

rust's standard library itself is built on top of libc

Makes sense. Although perhaps some is replaced by pure Rust, e.g. memcpy() strcpy(), the list is quite long, I know. The goal of a safe language system is to gradually become free of all unsafe language code and libs, so I imagine the plan is for Rust to eventually be independent of all C/C++ libraries. Although, as I see that you mentioned, Rust's wrappers could use them more safely until full rewrite, e.g. bounds checks before calls into libc. Logical.

This uses ucrt but if Rust standard crate(s) builds on msvcrt, then perhaps compatibility issue? I.e. Given what we've discussed here, it's best to avoid a toolchain that uses ucrt?

I'll look into Msys2 a bit more. This is all very helpful. I'm not overly concerned about msvcrt for Rust but I like to learn about the various options in general.

Based on the posts here, the default toolchain with CLion, mingw gnu, is probably ideal, true?

I'm also considering Linux because I'm interested in Linux (my code base was ported from Linux to Windows) and from what I am learning, Linux appears not to have the crt and ABI differences between clang and gcc as Windows does.

I don't know for sure, I have not used the llvm-mingw toolchain myself.

based on the discussion in #72241 and this document, my understanding is that, it is possible to use make a native rust toolchain work with llvm-mingw, but it is not supported by rustup, you need to do quite a lot of work yourself (bootstrapping??). however, use it for cross compilation is fine.

I don't use CLion, but IMO it probably is. the thing is, if you are targeting Windows while not wanting msvc, mingw is the only viable alternative (that is native on Windows). due to the way libc works on Windows, you cannot mix different runtimes (e.g. msvcrt and ucrt, forget about those vcredist).

although ucrt might be a better implementation, it's relative new to the mingw ecosystem. unless you are are absolutely certain every piece of code is written directly using libc (without third party dependencies), I would argue msvcrt has a better choice to work, purely from a compatibility perspective.

and personally, I generally prefer the "default" provision if it "just works". I don't like to dig into the "customizable" rabbit hole, unless there's an absolute need for it.

the difference is not in the C compilers per se (clang vs gcc), it is the C runtimes (a.k.a. libc, which determine the "env" or "abi" part of the target triple). on Windows, we have -msvc vs -gnu (vs -gnullvm); on Linux, we have mainly -gnu vs -musl, (there are many other environments too, mostly for specific hardware or embedded systems, such as -androideabi, -uclibc, etc.).

but again, unless you are targeting a very specific platform, the default works just fine, which is most likely either x86_64-unknown-linux-gnu or aarch64-unknown-linux-gnu for linux based PC and servers these days.

Hi,

Apparently the linker is the key tool that has been needed from the msvc toolset, and progress has been made to use the llvm lld linker. Presumably, lld works with the msvc-compatible API that is produced by Rust compiler on Windows. Also, I think that the C runtime libraries can be either statically linked or the msvc redistributable can be used.

Use lld by default on x64 msvc windows · Issue #71520 · rust-lang/rust

Windows support — lld 21.0.0git documentation

Can anyone confirm that the llvm lld linker eliminates the need for msvc build tools to build Rust code on Windows?

unfortunately no, not for the msvc abi, if microsoft documentation is accurate: although ucrt is part of of the OS since Windows 10, the code that implement CRT initialization and termination is part of Visual C++ (i.e. they are not in the Windows SDK).

according to this page, these libraries are:

Library Characteristics Option Preprocessor directives
libcmt.lib Statically links the native CRT startup into your code. /MT _MT
libcmtd.lib Statically links the Debug version of the native CRT startup. Not redistributable. /MTd _DEBUG, _MT
msvcrt.lib Static library for the native CRT startup for use with DLL UCRT and vcruntime. /MD _MT, _DLL
msvcrtd.lib Static library for the Debug version of the native CRT startup for use with DLL UCRT and vcruntime. Not redistributable. /MDd _DEBUG, _MT, _DLL
msvcmrt.lib Static library for the mixed native and managed CRT startup for use with DLL UCRT and vcruntime. /clr
msvcmrtd.lib Static library for the Debug version of the mixed native and managed CRT startup for use with DLL UCRT and vcruntime. Not redistributable. /clr
msvcurt.lib Deprecated Static library for the pure managed CRT. /clr:pure
msvcurtd.lib Deprecated Static library for the Debug version of the pure managed CRT. Not redistributable. /clr:pure

EDIT:

I think in theory, rust can get rid of these libraries and implement its own intialization and termination for ucrt, but this would be a lot of work, and I don't know if it could cause compatibility issues with ffi code.

Interesting, thank you for such insightful detail.

Does use of another library such as MUSL solve the problem if the ucrt isn't used at all?
musl - Introduction

Even if ucrt is not used for an application (for example) but the msvc resdistributables are provided, would third-party libraries that are built with msvc and use ucrt still be unusable?

There's three kinds of libraries that may be referenced in a Windows build:

  • Windows APIs (CreateProcess, ReadFile etc) which you can directly use via windows crate but currently requires the SDK (removed by the currently unstable raw-dylib Rust feature), everything eventually uses these.
  • The CRT, implementations of the C runtime functions like strlen or fread, libc, libstdc, or musl on unix are common, and either MSVCRT or UCRT on Windows. You probably won't use this directly in Rust, but the Rust standard library is partly built on these so you need one unless you're going no_std. It mostly doesn't matter too much which you choose unless you're sharing resources from them across libraries which isn't a great idea anyway, but UCRT is less likely to have issues with more modern locale functionality and the like so it's preferred if possible.
  • The pain in the butt one: the compiler support runtime, which provides code that implements functionality directly related to the way code is emitted by the compiler, mostly unwind/exception handling stuff. This is fixed by the compiler/linker used, for gnu I believe this is thrown in with libc, but for msvc this is vcruntime, which comes with the VC build tools and is pretty much the only remaining non-permissively licensed library code, so it's effectively the licensing mechanism.

My recommendation is that it doesn't really matter much for pretty much anything you're going to be doing in Rust, but gnu is a reasonable default as it doesn't potentially raise licensing issues like msvc does. When gnullvm lands in a higher support tier and works out of the box, that should eliminate any technical benefit msvc has, so you'd probably only need to pick something else if you had to be compatible with some other library that wants to share resources like get a CRT FILE handle from you and read it.

1 Like

OK. Thanks kindly.

In the meantime, use of gnu mingw works? ...but any third-party libraries would also need to also be (or have already been) built with mingw?

Depends on the library, technically. Anything pure Rust doesn't care at all, if it's building eg C from source it should get correctly configured automatically, if it's using platform provided libraries is where things get a bit messier. The crate should ideally document how to set up whatever dependencies it has for all the platforms it supports, and gnu and msvc are essentially different platforms for that purpose.

Generally this just isn't a problem you'll run into, most libraries are pure and the popular ones that aren't are pretty good at hand-holding you through getting what you need.

Thanks all for the help. Even though the help resolves the questions, I would like to leave this topic open to allow for any updates (within the three months auto-close period) based on the dynamism and active development of the Rust infrastructure in this area.

LLVM (clang) is gcc compatible. Clang followed suit on Windows with an msvc cl.exe compatible compiler. I.e. replacement alternative for gcc on Linux and now the same for cl on windows. I imagine that the eventual solution to Rust on Windows without msvc dependency will use the clang msvc replacement toolchain (as we see the linker is apparently the first part of that transition).