1
Fork 0

Auto merge of #111698 - Amanieu:force-static-lib, r=petrochenkov

Force all native libraries to be statically linked when linking a static binary

Previously, `#[link]` without an explicit `kind = "static"` would confuse the linker and end up producing a dynamically linked library because of the `-Bdynamic` flag. However this binary would not work correctly anyways since it was linked with startup code for a static binary.

This PR solves this by forcing all native libraries to be statically linked when the output is a static binary that cannot link to dynamic libraries anyways.

Fixes #108878
Fixes #102993
This commit is contained in:
bors 2023-06-07 22:02:24 +00:00
commit f383703e32
3 changed files with 47 additions and 6 deletions

View file

@ -2097,7 +2097,14 @@ fn linker_with_args<'a>(
cmd.add_as_needed(); cmd.add_as_needed();
// Local native libraries of all kinds. // 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. // Upstream rust crates and their non-dynamic native libraries.
add_upstream_rust_crates( add_upstream_rust_crates(
@ -2107,10 +2114,18 @@ fn linker_with_args<'a>(
codegen_results, codegen_results,
crate_type, crate_type,
tmpdir, tmpdir,
link_output_kind,
); );
// Dynamic native libraries from upstream crates. // 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. // Link with the import library generated for any raw-dylib functions.
for (raw_dylib_name, raw_dylib_imports) in for (raw_dylib_name, raw_dylib_imports) in
@ -2365,6 +2380,7 @@ fn add_native_libs_from_crate(
cnum: CrateNum, cnum: CrateNum,
link_static: bool, link_static: bool,
link_dynamic: bool, link_dynamic: bool,
link_output_kind: LinkOutputKind,
) { ) {
if !sess.opts.unstable_opts.link_native_libraries { if !sess.opts.unstable_opts.link_native_libraries {
// If `-Zlink-native-libraries=false` is set, then the assumption is that an // If `-Zlink-native-libraries=false` is set, then the assumption is that an
@ -2444,8 +2460,16 @@ fn add_native_libs_from_crate(
} }
} }
NativeLibKind::Unspecified => { NativeLibKind::Unspecified => {
if link_dynamic { // If we are generating a static binary, prefer static library when the
cmd.link_dylib(name, verbatim, true); // 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 } => { NativeLibKind::Framework { as_needed } => {
@ -2472,6 +2496,7 @@ fn add_local_native_libraries(
archive_builder_builder: &dyn ArchiveBuilderBuilder, archive_builder_builder: &dyn ArchiveBuilderBuilder,
codegen_results: &CodegenResults, codegen_results: &CodegenResults,
tmpdir: &Path, tmpdir: &Path,
link_output_kind: LinkOutputKind,
) { ) {
if sess.opts.unstable_opts.link_native_libraries { if sess.opts.unstable_opts.link_native_libraries {
// User-supplied library search paths (-L on the command line). These are the same paths // User-supplied library search paths (-L on the command line). These are the same paths
@ -2501,6 +2526,7 @@ fn add_local_native_libraries(
LOCAL_CRATE, LOCAL_CRATE,
link_static, link_static,
link_dynamic, link_dynamic,
link_output_kind,
); );
} }
@ -2511,6 +2537,7 @@ fn add_upstream_rust_crates<'a>(
codegen_results: &CodegenResults, codegen_results: &CodegenResults,
crate_type: CrateType, crate_type: CrateType,
tmpdir: &Path, tmpdir: &Path,
link_output_kind: LinkOutputKind,
) { ) {
// All of the heavy lifting has previously been accomplished by the // All of the heavy lifting has previously been accomplished by the
// dependency_format module of the compiler. This is just crawling the // dependency_format module of the compiler. This is just crawling the
@ -2588,6 +2615,7 @@ fn add_upstream_rust_crates<'a>(
cnum, cnum,
link_static, link_static,
link_dynamic, link_dynamic,
link_output_kind,
); );
} }
} }
@ -2598,6 +2626,7 @@ fn add_upstream_native_libraries(
archive_builder_builder: &dyn ArchiveBuilderBuilder, archive_builder_builder: &dyn ArchiveBuilderBuilder,
codegen_results: &CodegenResults, codegen_results: &CodegenResults,
tmpdir: &Path, tmpdir: &Path,
link_output_kind: LinkOutputKind,
) { ) {
let search_path = OnceCell::new(); let search_path = OnceCell::new();
for &cnum in &codegen_results.crate_info.used_crates { for &cnum in &codegen_results.crate_info.used_crates {
@ -2626,6 +2655,7 @@ fn add_upstream_native_libraries(
cnum, cnum,
link_static, link_static,
link_dynamic, link_dynamic,
link_output_kind,
); );
} }
} }

View file

@ -675,6 +675,17 @@ impl LinkOutputKind {
_ => return None, _ => 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 { impl fmt::Display for LinkOutputKind {

View file

@ -58,8 +58,8 @@ Example: `-l static:+whole-archive=mylib`.
The kind of library and the modifiers can also be specified in a [`#[link]` 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][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, attribute or on the command-line, it will link a dynamic library by default,
otherwise it will use a static library. If the kind is specified on the 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. 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 The name used in a `link` attribute may be overridden using the form `-l