-
Notifications
You must be signed in to change notification settings - Fork 77
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
Forcing +crt-static on windows: problematic with DLLs? #496
Comments
Currently looking into:
Slightly complicated by the fact that, as a build flag, we need this to interact with precise-builds inference (can't build --workspace if different packages in the workspace disagree on whether they want +crt-static), so now we would have inference-on-inference... |
Got some good clarification from windows devs over at https://toot.cat/@Gankra/111263387382919461 TL;DR -- it is still the case that if you want to dynamically link the windows crt, you really need to ship a redistributable to ensure everything's installed on the user's system. That said, if the user is a developer they probably already have one, so devtools like diesel's cli might be "kind of ok". Not a terribly compelling user story to "roll the dice". We should explore options for detecting the need for redistributables (whether +crt-static should be set), what version they used (with the post-build linkage checker), and then providing them as part of our installers. For the powershell installer we can probably fetch it from microsoft's servers at install-time? MSIs on the other hand probably want to vendor the redistributable installer, but I don't think cargo-wix knows how to do that, so we'll also want to teach it.
There was also a note of:
Which I don't fully comprehend the implications of yet (most magical interpretation is that we do not in fact ever need to ship redistributable installers, but that sounds too good to be true...). |
I would personally argue that a packaging tool should probably default to dynamic and ship .msis, rather than default to static and ship portable binaries. Once you're using other DLLs, it's fairly rare that you don't want everyone using the same CRT instance. As the owner of the redist, I also cannot recommend dynamic-UCRT-static-redist. For Rust dev-tools, if someone has installed rustc, you can assume they've installed the C++ toolset which gets you the redist (note: this was true when i last did rust, may not still be true) |
Just checking: is there weird licensing/legal implications about a powershell installer (equivalent of |
Additonal info: Much like on macOS, it is apparently just Cool And Normal to gobble up every dll you depend on and embed it in your application, see vcpkg (official microsoft tool) doing this: https://github.com/microsoft/vcpkg/blob/master/scripts/buildsystems/msbuild/applocal.ps1 This strategy bypasses the need to do things like "figure out what choco packages are needed at install-time", by basically just vendoring the DLLs those choco packages produced. You can even technically do this for crt stuff, although this is Poor Form, so there is an extremely cursed theoretical world where we ship .zips that contain a vendored crt dlls (so the zip on its own works), but then the ps1 installer deletes those and runs the proper redist installer. |
https://learn.microsoft.com/en-us/cpp/windows/redistributing-visual-cpp-files?view=msvc-170 is where all that information is. |
Yeah, basically. I don't think a general build system should try it. It kinda works for pure Rust because we don't use much of vcruntime. We do use some exception stuff but panicking between Rust cdylibs is already maybe a bit sketchy (e.g. if built with different Rust versions or even different compile) and throwing/catching C++ exceptions was right out (officially at least). Though I think the It's a bigger problem for mixed Rust/C++ code tho. |
Talked myself into starting with a very simplistic flag to opt back into the default rust behaviour of msvc==dynamic-libc. There's similar questions to answer around static vs dynamic musl, and we should Just Do the redist stuff if we're going to put much effort into dynamic linking on windows. So start simple, iterate from there. |
More details on the Hybrid CRT technique; basically statically linking vcruntime, but dynamically linking the UCRT. Doing hybrid CRT is theoretically as simple as using
There shouldn't be any issues with Hybrid CRT if DLLs always do the "proper" ABI marshalling, but it's extremely tempting for C++ libraries to skip doing that and just put STL types in their DLL interface. (I wonder how possible it is to do dynamic UCRT, static vcruntime, dynamic STL... probably not very.) Fun aside: The UCRT does cool PE tricks to version imports, working much like glibc symbol versioning, to back its compatibility. |
https://github.com/diesel-rs/diesel/actions/runs/6572883796/job/17854873471?pr=3833#step:9:271
https://stackoverflow.com/questions/3007312/resolving-lnk4098-defaultlib-msvcrt-conflicts-with
You can see
libcmt.lib
getting linked in, while cargo-dist turns on +crt-static on windows, as recommended by the Rust RFC:It's possible we should adjust our rule from "always +crt-static" to "+crt-static if there's no system dependencies" or "there's a config flag to turn of this behaviour" (I would have liked to emit this into a persistent/normal rust build config, but +crt-static is in a weird place where there's no right place to put it, really, especially with dynamic-vs-static musl sharing the same target triple while you could reasonably want to support both).
The text was updated successfully, but these errors were encountered: