Skip to content
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

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

Merged
merged 1 commit into from
Jun 8, 2023
Merged
Show file tree
Hide file tree
Changes from all 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
38 changes: 34 additions & 4 deletions compiler/rustc_codegen_ssa/src/back/link.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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 } => {
Expand All @@ -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
Expand Down Expand Up @@ -2533,6 +2558,7 @@ fn add_local_native_libraries(
LOCAL_CRATE,
link_static,
link_dynamic,
link_output_kind,
);
}

Expand All @@ -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
Expand Down Expand Up @@ -2620,6 +2647,7 @@ fn add_upstream_rust_crates<'a>(
cnum,
link_static,
link_dynamic,
link_output_kind,
);
}
}
Expand All @@ -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 {
Expand Down Expand Up @@ -2658,6 +2687,7 @@ fn add_upstream_native_libraries(
cnum,
link_static,
link_dynamic,
link_output_kind,
);
}
}
Expand Down
11 changes: 11 additions & 0 deletions compiler/rustc_target/src/spec/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
4 changes: 2 additions & 2 deletions src/doc/rustc/src/command-line-arguments.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The previous wording was right in the sense that -Bdynamic with ld-like linkers is only a preference for a dynamic library, not a requirement, so a static library can be linked even despite kind=dylib if there's no dynamic version of it.

That's what I called "too platform specific" above.
That's why I also suggested to document things in terms of the inferred kind and not in terms of actually linked libraries.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Based on my experiments, this isn't actually a preference: the linker will not search for static libraries if -Bdynamic is specified.

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
Expand Down