Skip to content

Enable windows-gnu target to link to libgcc dynamically. #90020

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

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 2 additions & 23 deletions compiler/rustc_target/src/spec/windows_gnu_base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,6 @@ pub fn opts() -> TargetOptions {
);

let mut late_link_args = LinkArgs::new();
let mut late_link_args_dynamic = LinkArgs::new();
let mut late_link_args_static = LinkArgs::new();
// Order of `late_link_args*` was found through trial and error to work with various
// mingw-w64 versions (not tested on the CI). It's expected to change from time to time.
let mingw_libs = vec![
Expand All @@ -39,25 +37,6 @@ pub fn opts() -> TargetOptions {
];
late_link_args.insert(LinkerFlavor::Gcc, mingw_libs.clone());
late_link_args.insert(LinkerFlavor::Lld(LldFlavor::Ld), mingw_libs);
let dynamic_unwind_libs = vec![
// If any of our crates are dynamically linked then we need to use
// the shared libgcc_s-dw2-1.dll. This is required to support
// unwinding across DLL boundaries.
"-lgcc_s".to_string(),
];
late_link_args_dynamic.insert(LinkerFlavor::Gcc, dynamic_unwind_libs.clone());
late_link_args_dynamic.insert(LinkerFlavor::Lld(LldFlavor::Ld), dynamic_unwind_libs);
let static_unwind_libs = vec![
// If all of our crates are statically linked then we can get away
// with statically linking the libgcc unwinding code. This allows
// binaries to be redistributed without the libgcc_s-dw2-1.dll
// dependency, but unfortunately break unwinding across DLL
// boundaries when unwinding across FFI boundaries.
"-lgcc_eh".to_string(),
"-l:libpthread.a".to_string(),
];
late_link_args_static.insert(LinkerFlavor::Gcc, static_unwind_libs.clone());
late_link_args_static.insert(LinkerFlavor::Lld(LldFlavor::Ld), static_unwind_libs);

TargetOptions {
os: "windows".to_string(),
Expand All @@ -81,8 +60,8 @@ pub fn opts() -> TargetOptions {
post_link_objects_fallback: crt_objects::post_mingw_fallback(),
crt_objects_fallback: Some(CrtObjectsFallback::Mingw),
late_link_args,
late_link_args_dynamic,
late_link_args_static,
crt_static_allows_dylibs: true,
crt_static_respected: true,
abi_return_struct_as_int: true,
emit_debug_gdb_scripts: false,
requires_uwtable: true,
Expand Down
4 changes: 2 additions & 2 deletions library/unwind/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,11 @@ cc = "1.0.69"

[features]

# Only applies for Linux and Fuchsia targets
# Only applies for MinGW, Linux and Fuchsia targets
# Static link to the in-tree build of llvm libunwind
llvm-libunwind = []

# Only applies for Linux and Fuchsia targets
# Only applies for MinGW, Linux and Fuchsia targets
# If crt-static is enabled, static link to `libunwind.a` provided by system
# If crt-static is disabled, dynamic link to `libunwind.so` provided by system
system-llvm-libunwind = []
26 changes: 26 additions & 0 deletions library/unwind/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,32 @@ extern "C" {}
#[link(name = "gcc_s", cfg(not(target_feature = "crt-static")))]
extern "C" {}

#[cfg(all(
windows,
target_env = "gnu",
not(feature = "llvm-libunwind"),
not(feature = "system-llvm-libunwind")
))]
#[link(name = "gcc_eh", kind = "static", modifiers = "-bundle", cfg(target_feature = "crt-static"))]
#[link(
name = "pthread",
kind = "static",
modifiers = "-bundle",
cfg(target_feature = "crt-static")
)]
#[link(name = "gcc_s", cfg(not(target_feature = "crt-static")))]
extern "C" {}

#[cfg(all(
windows,
target_env = "gnu",
not(feature = "llvm-libunwind"),
feature = "system-llvm-libunwind"
))]
#[link(name = "unwind", kind = "static", modifiers = "-bundle", cfg(target_feature = "crt-static"))]
#[link(name = "unwind", cfg(not(target_feature = "crt-static")))]
extern "C" {}

#[cfg(all(target_vendor = "fortanix", target_env = "sgx"))]
#[link(name = "unwind", kind = "static", modifiers = "-bundle")]
extern "C" {}
2 changes: 1 addition & 1 deletion src/test/run-make-fulldeps/foreign-exceptions/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ all: foo
$(call RUN,foo)

foo: foo.rs $(call NATIVE_STATICLIB,foo)
$(RUSTC) $< -lfoo $(EXTRARSCXXFLAGS)
$(RUSTC) $< -lfoo $(EXTRACXXFLAGS)

$(TMPDIR)/libfoo.o: foo.cpp
$(call COMPILE_OBJ_CXX,$@,$<)
18 changes: 0 additions & 18 deletions src/test/run-make-fulldeps/tools.mk
Original file line number Diff line number Diff line change
Expand Up @@ -105,28 +105,11 @@ ifdef IS_MSVC
else
EXTRACFLAGS := -lws2_32 -luserenv -lbcrypt
EXTRACXXFLAGS := -lstdc++
# So this is a bit hacky: we can't use the DLL version of libstdc++ because
# it pulls in the DLL version of libgcc, which means that we end up with 2
# instances of the DW2 unwinding implementation. This is a problem on
# i686-pc-windows-gnu because each module (DLL/EXE) needs to register its
# unwind information with the unwinding implementation, and libstdc++'s
# __cxa_throw won't see the unwinding info we registered with our statically
# linked libgcc.
#
# Now, simply statically linking libstdc++ would fix this problem, except
# that it is compiled with the expectation that pthreads is dynamically
# linked as a DLL and will fail to link with a statically linked libpthread.
#
# So we end up with the following hack: we link use static-nobundle to only
# link the parts of libstdc++ that we actually use, which doesn't include
# the dependency on the pthreads DLL.
EXTRARSCXXFLAGS := -l static-nobundle=stdc++
endif
else
ifeq ($(UNAME),Darwin)
EXTRACFLAGS := -lresolv
EXTRACXXFLAGS := -lc++
EXTRARSCXXFLAGS := -lc++
else
ifeq ($(UNAME),FreeBSD)
EXTRACFLAGS := -lm -lpthread -lgcc_s
Expand All @@ -140,7 +123,6 @@ ifeq ($(UNAME),OpenBSD)
else
EXTRACFLAGS := -lm -lrt -ldl -lpthread
EXTRACXXFLAGS := -lstdc++
EXTRARSCXXFLAGS := -lstdc++
endif
endif
endif
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,5 @@
PATH=$(SYSTEMROOT)/system32

all:
$(RUSTC) hello.rs
$(RUSTC) hello.rs -C target-feature=+crt-static
$(TMPDIR)/hello.exe
2 changes: 1 addition & 1 deletion src/test/run-make/issue-36710/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ all: foo
$(call RUN,foo)

foo: foo.rs $(call NATIVE_STATICLIB,foo)
$(RUSTC) $< -lfoo $(EXTRARSCXXFLAGS) --target $(TARGET)
$(RUSTC) $< -lfoo $(EXTRACXXFLAGS) --target $(TARGET)

$(TMPDIR)/libfoo.o: foo.cpp
$(call COMPILE_OBJ_CXX,$@,$<)