diff --git a/compiler/rustc_metadata/src/dependency_format.rs b/compiler/rustc_metadata/src/dependency_format.rs index 590a7374d11..72b208a7132 100644 --- a/compiler/rustc_metadata/src/dependency_format.rs +++ b/compiler/rustc_metadata/src/dependency_format.rs @@ -91,9 +91,22 @@ fn calculate_type(tcx: TyCtxt<'_>, ty: CrateType) -> DependencyList { // // Treat cdylibs and staticlibs similarly. If `-C prefer-dynamic` is set, // the caller may be code-size conscious, but without it, it makes sense - // to statically link a cdylib or staticlib. - CrateType::Dylib | CrateType::Cdylib | CrateType::Staticlib => { - if sess.opts.cg.prefer_dynamic { Linkage::Dynamic } else { Linkage::Static } + // to statically link a cdylib or staticlib. For staticlibs we use + // `-Z staticlib-prefer-dynamic` for now. This may be merged into + // `-C prefer-dynamic` in the future. + CrateType::Dylib | CrateType::Cdylib => { + if sess.opts.cg.prefer_dynamic { + Linkage::Dynamic + } else { + Linkage::Static + } + } + CrateType::Staticlib => { + if sess.opts.unstable_opts.staticlib_prefer_dynamic { + Linkage::Dynamic + } else { + Linkage::Static + } } // If the global prefer_dynamic switch is turned off, or the final @@ -123,9 +136,10 @@ fn calculate_type(tcx: TyCtxt<'_>, ty: CrateType) -> DependencyList { // Static executables must have all static dependencies. // If any are not found, generate some nice pretty errors. - if ty == CrateType::Executable - && sess.crt_static(Some(ty)) - && !sess.target.crt_static_allows_dylibs + if (ty == CrateType::Staticlib && !sess.opts.unstable_opts.staticlib_allow_rdylib_deps) + || (ty == CrateType::Executable + && sess.crt_static(Some(ty)) + && !sess.target.crt_static_allows_dylibs) { for &cnum in tcx.crates(()).iter() { if tcx.dep_kind(cnum).macros_only() { diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 631dd0a2146..0743392b19a 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -1709,6 +1709,10 @@ options! { #[rustc_lint_opt_deny_field_access("use `Session::stack_protector` instead of this field")] stack_protector: StackProtector = (StackProtector::None, parse_stack_protector, [TRACKED], "control stack smash protection strategy (`rustc --print stack-protector-strategies` for details)"), + staticlib_allow_rdylib_deps: bool = (false, parse_bool, [TRACKED], + "allow staticlibs to have rust dylib dependencies"), + staticlib_prefer_dynamic: bool = (false, parse_bool, [TRACKED], + "prefer dynamic linking to static linking for staticlibs (default: no)"), strict_init_checks: bool = (false, parse_bool, [TRACKED], "control if mem::uninitialized and mem::zeroed panic on more UB"), strip: Strip = (Strip::None, parse_strip, [UNTRACKED], diff --git a/tests/run-make/staticlib-dylib-linkage/Makefile b/tests/run-make/staticlib-dylib-linkage/Makefile index faa45243104..fd76f6c5578 100644 --- a/tests/run-make/staticlib-dylib-linkage/Makefile +++ b/tests/run-make/staticlib-dylib-linkage/Makefile @@ -2,7 +2,9 @@ include ../tools.mk all: $(RUSTC) -C prefer-dynamic bar.rs - $(RUSTC) foo.rs --crate-type staticlib --print native-static-libs 2>&1 | grep 'note: native-static-libs: ' | sed 's/note: native-static-libs: \(.*\)/\1/' > $(TMPDIR)/libs.txt + $(RUSTC) foo.rs --crate-type staticlib --print native-static-libs \ + -Z staticlib-allow-rdylib-deps 2>&1 | grep 'note: native-static-libs: ' \ + | sed 's/note: native-static-libs: \(.*\)/\1/' > $(TMPDIR)/libs.txt cat $(TMPDIR)/libs.txt ifdef IS_MSVC