-
Notifications
You must be signed in to change notification settings - Fork 12.8k
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 always links against non-debug Windows runtime #39016
Comments
Would there be any objection to doing something like: #[cfg(all(target_env = "msvc", debug))] // " if " -- appease style checker
#[link(name = "msvcrtd")]
extern {}
#[cfg(all(target_env = "msvc", not(debug_assertions)))] // " if " -- appease style checker
#[link(name = "msvcrt")]
extern {} cc @retep998 |
We already have a feature for choosing whether to link the static or dynamic CRT. It would be a fairly trivial matter to add another feature to choose whether to link the debug or release CRT (which I did suggest but nobody seemed to notice). I'd rather not tie this sort of thing to whether optimizations are enabled. |
#37545 landed, what is needed to make some progress on this? |
This cost me a couple of days debugging why debugmozjs builds of mozjs_sys were failing with link errors under msvc. |
Would love to be able to configure this as well for c++ code. |
It would make sense to transfer this issue to https://github.com/rust-lang/libc now that the responsible code is in that repository, but I don't have the permissions to do so. |
cc @alexcrichton @retep998 @newpavlov - please review the libc C PR at: rust-lang/libc#1433 - I'm not sure how this will interact with linking libc both via libstd and crates.io, what happens if the features are different in each, what happens if the binary is |
Solving this issue requires changes both in rust and libc. |
Since libstd depends on libc, and libc would need to be compiled differently for debug and release on windows, wouldn't we need to ship two libstds one for debug and one for release ? |
Only if there are actual changes to the bindings in libc depending on debug vs release. Simply linking to a different CRT is already handled in std's libc using deferred linking decisions. |
This looks like a pretty big footgun, and it can cause mysterious runtime error taking people lots of time to figure out. Until this gets fixed, there should probably be some document / compiler message warning about this, so that people know that they need to have their C/C++ program always link against the non-debug crt. |
I'm curious how this can be done cleanly, when the base windows target itself adds |
The glue is done using the [cxx crate](https://cxx.rs/) on the Rust side. As a proof-of-concept, only a small console command (`rust_version`) printing the currently used Rust version was added. You can generate and open the Rust documentation using `DDNET_TEST_NO_LINK=1 cargo doc --open`. You can run the Rust tests using `cmake --build <build dir> --target run_rust_tests`, they're automatically included in the `run_tests` target as well. Rust tests don't work on Windows in debug mode on Windows because Rust cannot currently link with the debug version of the C stdlib on Windows: rust-lang/rust#39016. --- The stuff in `src/rust-bridge` is generated using ``` cxxbridge src/engine/shared/rust_version.rs --output src/rust-bridge/engine/shared/rust_version.cpp --output src/rust-bridge/engine/shared/rust_version.h cxxbridge src/engine/console.rs --output src/rust-bridge/cpp/console.cpp --output src/rust-bridge/cpp/console.h ```
The glue is done using the [cxx crate](https://cxx.rs/) on the Rust side. As a proof-of-concept, only a small console command (`rust_version`) printing the currently used Rust version was added. You can generate and open the Rust documentation using `DDNET_TEST_NO_LINK=1 cargo doc --open`. You can run the Rust tests using `cmake --build <build dir> --target run_rust_tests`, they're automatically included in the `run_tests` target as well. Rust tests don't work on Windows in debug mode on Windows because Rust cannot currently link with the debug version of the C stdlib on Windows: rust-lang/rust#39016. --- The stuff in `src/rust-bridge` is generated using ``` cxxbridge src/engine/shared/rust_version.rs --output src/rust-bridge/engine/shared/rust_version.cpp --output src/rust-bridge/engine/shared/rust_version.h cxxbridge src/engine/console.rs --output src/rust-bridge/cpp/console.cpp --output src/rust-bridge/cpp/console.h ```
5599: Add support for Rust code in DDNet r=def- a=heinrich5991 The glue is done using the [cxx crate](https://cxx.rs/) on the Rust side. As a proof-of-concept, only a small console command (`rust_version`) printing the currently used Rust version was added. You can generate and open the Rust documentation using `DDNET_TEST_NO_LINK=1 cargo doc --open`. You can run the Rust tests using `cmake --build <build dir> --target run_rust_tests`, they're automatically included in the `run_tests` target as well. Rust tests don't work on Windows in debug mode on Windows because Rust cannot currently link with the debug version of the C stdlib on Windows: rust-lang/rust#39016. --- The stuff in `src/rust-bridge` is generated using ``` cxxbridge src/engine/shared/rust_version.rs --output src/rust-bridge/engine/shared/rust_version.cpp --output src/rust-bridge/engine/shared/rust_version.h cxxbridge src/engine/console.rs --output src/rust-bridge/cpp/console.cpp --output src/rust-bridge/cpp/console.h ``` Co-authored-by: heinrich5991 <[email protected]>
I really want to find a way forward here as it's a common issue when trying to integrate Rust with existing C/C++ builds. I do find it slightly odd that linking the C runtime is the responsibility of the libc crate on Windows. That seems unusual compared to other platforms? But ok, I can live with that. @petrochenkov suggested adding a feature in people's So to sum up I think to do this outside of rustc will require changes to:
Is that right? Btw, there should also be an option to not link a CRT. This is the default for |
Hitting this issue in Chromium: https://bugs.chromium.org/p/chromium/issues/detail?id=1434719 |
Rust by default links with the default MSVCRT, (dynamic, release). MSVCRT's cannot be mixed, so if Meson compiles a C or C++ library and links it with the debug MSVCRT, then tries to link that with the Rust library there will be failures. There is no built-in way to fix this for rustc, so as a workaround we inject the correct arguments early in the linker line (before any libs at least) to change the runtime. This seems to work and is recommended as workaround in the upstream rust bug report: rust-lang/rust#39016. Given that this bug report has been opened since 2017, it seems unlikely to be fixed anytime soon, and affects all (currently) released versions of Rust.
Rust by default links with the default MSVCRT, (dynamic, release). MSVCRT's cannot be mixed, so if Meson compiles a C or C++ library and links it with the debug MSVCRT, then tries to link that with the Rust library there will be failures. There is no built-in way to fix this for rustc, so as a workaround we inject the correct arguments early in the linker line (before any libs at least) to change the runtime. This seems to work and is recommended as workaround in the upstream rust bug report: rust-lang/rust#39016. Given that this bug report has been opened since 2017, it seems unlikely to be fixed anytime soon, and affects all (currently) released versions of Rust.
Rust by default links with the default MSVCRT, (dynamic, release). MSVCRT's cannot be mixed, so if Meson compiles a C or C++ library and links it with the debug MSVCRT, then tries to link that with the Rust library there will be failures. There is no built-in way to fix this for rustc, so as a workaround we inject the correct arguments early in the linker line (before any libs at least) to change the runtime. This seems to work and is recommended as workaround in the upstream rust bug report: rust-lang/rust#39016. Given that this bug report has been opened since 2017, it seems unlikely to be fixed anytime soon, and affects all (currently) released versions of Rust.
Rust by default links with the default MSVCRT, (dynamic, release). MSVCRT's cannot be mixed, so if Meson compiles a C or C++ library and links it with the debug MSVCRT, then tries to link that with the Rust library there will be failures. There is no built-in way to fix this for rustc, so as a workaround we inject the correct arguments early in the linker line (before any libs at least) to change the runtime. This seems to work and is recommended as workaround in the upstream rust bug report: rust-lang/rust#39016. Given that this bug report has been opened since 2017, it seems unlikely to be fixed anytime soon, and affects all (currently) released versions of Rust.
Rust by default links with the default MSVCRT, (dynamic, release). MSVCRT's cannot be mixed, so if Meson compiles a C or C++ library and links it with the debug MSVCRT, then tries to link that with the Rust library there will be failures. There is no built-in way to fix this for rustc, so as a workaround we inject the correct arguments early in the linker line (before any libs at least) to change the runtime. This seems to work and is recommended as workaround in the upstream rust bug report: rust-lang/rust#39016. Given that this bug report has been opened since 2017, it seems unlikely to be fixed anytime soon, and affects all (currently) released versions of Rust.
Rust by default links with the default MSVCRT, (dynamic, release). MSVCRT's cannot be mixed, so if Meson compiles a C or C++ library and links it with the debug MSVCRT, then tries to link that with the Rust library there will be failures. There is no built-in way to fix this for rustc, so as a workaround we inject the correct arguments early in the linker line (before any libs at least) to change the runtime. This seems to work and is recommended as workaround in the upstream rust bug report: rust-lang/rust#39016. Given that this bug report has been opened since 2017, it seems unlikely to be fixed anytime soon, and affects all (currently) released versions of Rust.
Rust by default links with the default MSVCRT, (dynamic, release). MSVCRT's cannot be mixed, so if Meson compiles a C or C++ library and links it with the debug MSVCRT, then tries to link that with the Rust library there will be failures. There is no built-in way to fix this for rustc, so as a workaround we inject the correct arguments early in the linker line (before any libs at least) to change the runtime. This seems to work and is recommended as workaround in the upstream rust bug report: rust-lang/rust#39016. Given that this bug report has been opened since 2017, it seems unlikely to be fixed anytime soon, and affects all (currently) released versions of Rust.
Rust by default links with the default MSVCRT, (dynamic, release). MSVCRT's cannot be mixed, so if Meson compiles a C or C++ library and links it with the debug MSVCRT, then tries to link that with the Rust library there will be failures. There is no built-in way to fix this for rustc, so as a workaround we inject the correct arguments early in the linker line (before any libs at least) to change the runtime. This seems to work and is recommended as workaround in the upstream rust bug report: rust-lang/rust#39016. Given that this bug report has been opened since 2017, it seems unlikely to be fixed anytime soon, and affects all (currently) released versions of Rust.
Rust by default links with the default MSVCRT, (dynamic, release). MSVCRT's cannot be mixed, so if Meson compiles a C or C++ library and links it with the debug MSVCRT, then tries to link that with the Rust library there will be failures. There is no built-in way to fix this for rustc, so as a workaround we inject the correct arguments early in the linker line (before any libs at least) to change the runtime. This seems to work and is recommended as workaround in the upstream rust bug report: rust-lang/rust#39016. Given that this bug report has been opened since 2017, it seems unlikely to be fixed anytime soon, and affects all (currently) released versions of Rust.
Update on this: You can now use a build script (or other build method) to disable the default CRT for a binary. Then you can add back the one you want. However, you need to use a linker argument: For the dynamic CRT use: This can be done in a build script, for example: fn main() {
// Don't link the default CRT
println!("cargo::rustc-link-arg-bins=/nodefaultlib:msvcrt")`
// Link the debug CRT instead
println!("cargo::rustc-link-arg-bins=/defaultlib:msvcrtd")`
} Which isn't as nice as having a proper feature but it's at least serviceable. |
What is MSRV for this? |
1.79 |
Also note that if you do that, you need to make sure every C/C++ library you link against was built using the correct version of the CRT as well. If you end up mixing them then you're going to have a bad time with a lot of linker errors. |
When building rust-mozjs with debug symbols enabled, the underlying C++ library links against the debug Windows runtime (
msvcrtd.lib
) rather than the regular one (msvcrt.lib
). Unfortunately, rustc always links againstmsvcrt.lib
unconditionally:rust/src/vendor/libc/src/windows.rs
Line 150 in da2ce22
The text was updated successfully, but these errors were encountered: