rust-lang / rust

Empowering everyone to build reliable and efficient software.
https://www.rust-lang.org
Other
96.87k stars 12.52k forks source link

Consider dynamically link to `libgcc_s` when targeting `windows-gnu` #89919

Open Berrysoft opened 2 years ago

Berrysoft commented 2 years ago

Description

Rust now choose to statically link to libgcc_eh and libpthread when no -C prefer-dynamic is specified: https://github.com/rust-lang/rust/blob/1ddd4e6d7ed446934abd428a08e18535faef5e03/compiler/rustc_target/src/spec/windows_gnu_base.rs#L50-L58

It is because that some software end users may not have MinGW64 runtimes installed, and it may be complicated for developers to bundle the MinGW64 runtime. However, this case should have been correctly handled with -C target-feature=+crt-static.

Pros

Smaller binary size: We could simply link with the system MinGW64 runtime, and it will help reduce some of the binary size. The distributed binary will also benifit from newer MinGW64 runtime without recompiling.

No sidebacks when using crt-static: MinGW64 doesn't statically link to msvcrt due to license restrictions. Therefore the modification here won't make difference when using crt-static. It should perform as usual, and simply bundle the MinGW64 runtime.

Future exception safety: I've noticed the in design feature for future exception safety. Then it needs the rust binary to dynamically link to the MinGW64 runtime.

Behavior consistence: Most other targets only link to the unwind runtime statically when feature crt-static is on. We could set it on as default in the windows-gnu target, but leave the choice to the developers.

Cons

MISC breaking: Some crates may assume the original behavior, although I haven't found one.

Other notes

Not only the windows_gnu_base.rs should be modified, library/unwind/src/lib.rs should also be modified to properly deal with crt-static feature. Also, it should be investigated that where to link libpthread statically.

I came to this idea when developing with Rust and GTK. GTK depends on a lot of other libraries, for example, harfbuzz, which itself is written by C++ and links to libgcc_s. Therefore I needn't statically link to libgcc_eh, because anyway I need to ship the binaries with a libgcc. However, I couldn't find a switch to turn it off. I couldn't use -C prefer-dynamic, because I don't want to dynamically link to libstd-xxxxxxx, which only increases the final binaries size. In addition, some crates, for example, hyper, blocks the prefer-dynamic build, because of its (maybe wrongly written) crate-type.

petrochenkov commented 2 years ago

However, I couldn't find a switch to turn it off.

You've probably already noticed, but if you link any (possibly dummy) dylib into the executable, then (with the current compiler) the mingw target will switch to linking libgcc_s dynamically, so a workaround does exist.

Berrysoft commented 1 year ago

@petrochenkov

if you link any (possibly dummy) dylib into the executable...

Would you explain it clearer? How do I link a dylib into the executable? If I simply link a dll with #[link(name="foo")], libgcc_s won't be linked dynamically.

Berrysoft commented 1 year ago

I've re-read the code and find out that I cannot switch to linking libgcc_s dynamically by linking a dll. If I link to a dylib crate, libstd of Rust will also be dynamically linked in, which is not what I would like.

@petrochenkov I'm asking to dynamically linking to libgcc_s when linking to a C/C++ dll, for example, libgtk or libQtCore. I don't want to dynamically link a libstd because it is too large.