From 0304e0a5b0fafa1b3be46207c4651709eec478c5 Mon Sep 17 00:00:00 2001 From: Amanieu d'Antras Date: Wed, 17 May 2023 23:53:04 +0200 Subject: [PATCH] Force all native libraries to be statically linked when linking a static binary --- compiler/rustc_codegen_ssa/src/back/link.rs | 38 ++++++++++++++++++--- compiler/rustc_target/src/spec/mod.rs | 11 ++++++ src/doc/rustc/src/command-line-arguments.md | 4 +-- 3 files changed, 47 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index ea06cb02d8baf..91598e8d879ee 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -2129,7 +2129,14 @@ fn linker_with_args<'a>( cmd.add_as_needed(); // Local native libraries of all kinds. - add_local_native_libraries(cmd, sess, archive_builder_builder, codegen_results, tmpdir); + add_local_native_libraries( + cmd, + sess, + archive_builder_builder, + codegen_results, + tmpdir, + link_output_kind, + ); // Upstream rust crates and their non-dynamic native libraries. add_upstream_rust_crates( @@ -2139,10 +2146,18 @@ fn linker_with_args<'a>( codegen_results, crate_type, tmpdir, + link_output_kind, ); // Dynamic native libraries from upstream crates. - add_upstream_native_libraries(cmd, sess, archive_builder_builder, codegen_results, tmpdir); + add_upstream_native_libraries( + cmd, + sess, + archive_builder_builder, + codegen_results, + tmpdir, + link_output_kind, + ); // Link with the import library generated for any raw-dylib functions. for (raw_dylib_name, raw_dylib_imports) in @@ -2397,6 +2412,7 @@ fn add_native_libs_from_crate( cnum: CrateNum, link_static: bool, link_dynamic: bool, + link_output_kind: LinkOutputKind, ) { if !sess.opts.unstable_opts.link_native_libraries { // If `-Zlink-native-libraries=false` is set, then the assumption is that an @@ -2476,8 +2492,16 @@ fn add_native_libs_from_crate( } } NativeLibKind::Unspecified => { - if link_dynamic { - cmd.link_dylib(name, verbatim, true); + // If we are generating a static binary, prefer static library when the + // link kind is unspecified. + if !link_output_kind.can_link_dylib() && !sess.target.crt_static_allows_dylibs { + if link_static { + cmd.link_staticlib(name, verbatim) + } + } else { + if link_dynamic { + cmd.link_dylib(name, verbatim, true); + } } } NativeLibKind::Framework { as_needed } => { @@ -2504,6 +2528,7 @@ fn add_local_native_libraries( archive_builder_builder: &dyn ArchiveBuilderBuilder, codegen_results: &CodegenResults, tmpdir: &Path, + link_output_kind: LinkOutputKind, ) { if sess.opts.unstable_opts.link_native_libraries { // User-supplied library search paths (-L on the command line). These are the same paths @@ -2533,6 +2558,7 @@ fn add_local_native_libraries( LOCAL_CRATE, link_static, link_dynamic, + link_output_kind, ); } @@ -2543,6 +2569,7 @@ fn add_upstream_rust_crates<'a>( codegen_results: &CodegenResults, crate_type: CrateType, tmpdir: &Path, + link_output_kind: LinkOutputKind, ) { // All of the heavy lifting has previously been accomplished by the // dependency_format module of the compiler. This is just crawling the @@ -2620,6 +2647,7 @@ fn add_upstream_rust_crates<'a>( cnum, link_static, link_dynamic, + link_output_kind, ); } } @@ -2630,6 +2658,7 @@ fn add_upstream_native_libraries( archive_builder_builder: &dyn ArchiveBuilderBuilder, codegen_results: &CodegenResults, tmpdir: &Path, + link_output_kind: LinkOutputKind, ) { let search_path = OnceCell::new(); for &cnum in &codegen_results.crate_info.used_crates { @@ -2658,6 +2687,7 @@ fn add_upstream_native_libraries( cnum, link_static, link_dynamic, + link_output_kind, ); } } diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index ba4b89c9ea10b..e1915e16e2002 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -596,6 +596,17 @@ impl LinkOutputKind { _ => return None, }) } + + pub fn can_link_dylib(self) -> bool { + match self { + LinkOutputKind::StaticNoPicExe | LinkOutputKind::StaticPicExe => false, + LinkOutputKind::DynamicNoPicExe + | LinkOutputKind::DynamicPicExe + | LinkOutputKind::DynamicDylib + | LinkOutputKind::StaticDylib + | LinkOutputKind::WasiReactorExe => true, + } + } } impl fmt::Display for LinkOutputKind { diff --git a/src/doc/rustc/src/command-line-arguments.md b/src/doc/rustc/src/command-line-arguments.md index 3be4382b0a3aa..da3f4cba214ab 100644 --- a/src/doc/rustc/src/command-line-arguments.md +++ b/src/doc/rustc/src/command-line-arguments.md @@ -58,8 +58,8 @@ Example: `-l static:+whole-archive=mylib`. The kind of library and the modifiers can also be specified in a [`#[link]` attribute][link-attribute]. If the kind is not specified in the `link` -attribute or on the command-line, it will link a dynamic library if available, -otherwise it will use a static library. If the kind is specified on the +attribute or on the command-line, it will link a dynamic library by default, +except when building a static executable. If the kind is specified on the command-line, it will override the kind specified in a `link` attribute. The name used in a `link` attribute may be overridden using the form `-l