Skip to content

Commit cb1319d

Browse files
committed
Link std statically in rustc_driver
1 parent 6a92312 commit cb1319d

File tree

9 files changed

+74
-17
lines changed

9 files changed

+74
-17
lines changed

compiler/rustc/src/main.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
#![feature(unix_sigpipe)]
2+
// We need this feature as it changes `dylib` linking behavior and allows us to link to `rustc_driver`.
3+
#![feature(rustc_private)]
24

35
// A note about jemalloc: rustc uses jemalloc when built for CI and
46
// distribution. The obvious way to do this is with the `#[global_allocator]`

compiler/rustc_metadata/src/dependency_format.rs

Lines changed: 36 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ use crate::errors::{
5757
NonStaticCrateDep, RequiredPanicStrategy, RlibRequired, RustcLibRequired, TwoPanicRuntimes,
5858
};
5959

60-
use rustc_data_structures::fx::FxHashMap;
60+
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
6161
use rustc_hir::def_id::CrateNum;
6262
use rustc_middle::middle::dependency_format::{Dependencies, DependencyList, Linkage};
6363
use rustc_middle::ty::TyCtxt;
@@ -158,25 +158,49 @@ fn calculate_type(tcx: TyCtxt<'_>, ty: CrateType) -> DependencyList {
158158
Linkage::Dynamic | Linkage::IncludedFromDylib => {}
159159
}
160160

161+
let all_dylibs = || {
162+
tcx.crates(()).iter().filter(|&&cnum| {
163+
!tcx.dep_kind(cnum).macros_only() && tcx.used_crate_source(cnum).dylib.is_some()
164+
})
165+
};
166+
167+
let mut upstream_in_dylibs = FxHashSet::default();
168+
169+
if tcx.features().rustc_private {
170+
// We need this to prevent users of `rustc_driver` from linking to dynamically to `std`
171+
// which does not work as `std` is also statically linked into `rustc_driver`.
172+
173+
// Find all libraries statically linked to upstream dylibs.
174+
for &cnum in all_dylibs() {
175+
let deps = tcx.dylib_dependency_formats(cnum);
176+
for &(depnum, style) in deps.iter() {
177+
if let RequireStatic = style {
178+
upstream_in_dylibs.insert(depnum);
179+
}
180+
}
181+
}
182+
}
183+
161184
let mut formats = FxHashMap::default();
162185

163186
// Sweep all crates for found dylibs. Add all dylibs, as well as their
164187
// dependencies, ensuring there are no conflicts. The only valid case for a
165188
// dependency to be relied upon twice is for both cases to rely on a dylib.
166-
for &cnum in tcx.crates(()).iter() {
167-
if tcx.dep_kind(cnum).macros_only() {
189+
for &cnum in all_dylibs() {
190+
if upstream_in_dylibs.contains(&cnum) {
191+
info!("skipping dylib: {}", tcx.crate_name(cnum));
192+
// If this dylib is also available statically linked to another dylib
193+
// we try to use that instead.
168194
continue;
169195
}
196+
170197
let name = tcx.crate_name(cnum);
171-
let src = tcx.used_crate_source(cnum);
172-
if src.dylib.is_some() {
173-
info!("adding dylib: {}", name);
174-
add_library(tcx, cnum, RequireDynamic, &mut formats, &mut unavailable_as_static);
175-
let deps = tcx.dylib_dependency_formats(cnum);
176-
for &(depnum, style) in deps.iter() {
177-
info!("adding {:?}: {}", style, tcx.crate_name(depnum));
178-
add_library(tcx, depnum, style, &mut formats, &mut unavailable_as_static);
179-
}
198+
info!("adding dylib: {}", name);
199+
add_library(tcx, cnum, RequireDynamic, &mut formats, &mut unavailable_as_static);
200+
let deps = tcx.dylib_dependency_formats(cnum);
201+
for &(depnum, style) in deps.iter() {
202+
info!("adding {:?}: {}", style, tcx.crate_name(depnum));
203+
add_library(tcx, depnum, style, &mut formats, &mut unavailable_as_static);
180204
}
181205
}
182206

src/bootstrap/src/bin/rustc.rs

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,23 @@ fn main() {
9191
rustc_real
9292
};
9393

94+
// Get the name of the crate we're compiling, if any.
95+
let crate_name = arg("--crate-name");
96+
97+
// We want everything statically linked into `rustc_driver`, so remove `-C prefer-dynamic`
98+
if crate_name == Some("rustc_driver") && stage != "0" {
99+
// Remove `-C prefer-dynamic` to link `std` statically into `rustc_driver`
100+
if let Some(pos) = args.iter().enumerate().position(|(i, a)| {
101+
a == "-C" && args.get(i + 1).map(|a| a == "prefer-dynamic").unwrap_or(false)
102+
}) {
103+
args.remove(pos);
104+
args.remove(pos);
105+
}
106+
if let Some(pos) = args.iter().position(|a| a == "-Cprefer-dynamic") {
107+
args.remove(pos);
108+
}
109+
}
110+
94111
let mut cmd = if let Some(wrapper) = env::var_os("RUSTC_WRAPPER_REAL") {
95112
let mut cmd = Command::new(wrapper);
96113
cmd.arg(rustc_driver);
@@ -100,9 +117,6 @@ fn main() {
100117
};
101118
cmd.args(&args).env(dylib_path_var(), env::join_paths(&dylib_path).unwrap());
102119

103-
// Get the name of the crate we're compiling, if any.
104-
let crate_name = arg("--crate-name");
105-
106120
if let Some(crate_name) = crate_name {
107121
if let Some(target) = env::var_os("RUSTC_TIME") {
108122
if target == "all"

src/bootstrap/src/core/build_steps/compile.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1794,7 +1794,12 @@ impl Step for Assemble {
17941794
let src_libdir = builder.sysroot_libdir(build_compiler, host);
17951795
for f in builder.read_dir(&src_libdir) {
17961796
let filename = f.file_name().into_string().unwrap();
1797-
if (is_dylib(&filename) || is_debug_info(&filename)) && !proc_macros.contains(&filename)
1797+
let can_be_rustc_dep = filename.starts_with("rustc_driver-")
1798+
|| filename.starts_with("librustc_driver-")
1799+
|| build_compiler.stage == 0;
1800+
if can_be_rustc_dep
1801+
&& (is_dylib(&filename) || is_debug_info(&filename))
1802+
&& !proc_macros.contains(&filename)
17981803
{
17991804
builder.copy_link(&f.path(), &rustc_libdir.join(&filename));
18001805
}

src/bootstrap/src/core/builder.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2031,7 +2031,7 @@ impl<'a> Builder<'a> {
20312031
// When we build Rust dylibs they're all intended for intermediate
20322032
// usage, so make sure we pass the -Cprefer-dynamic flag instead of
20332033
// linking all deps statically into the dylib.
2034-
if matches!(mode, Mode::Std | Mode::Rustc) {
2034+
if matches!(mode, Mode::Std) {
20352035
rustflags.arg("-Cprefer-dynamic");
20362036
}
20372037

src/tools/clippy/src/main.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
// We need this feature as it changes `dylib` linking behavior and allows us to link to
2+
// `rustc_driver`.
3+
#![feature(rustc_private)]
14
#![cfg_attr(feature = "deny-warnings", deny(warnings))]
25
// warn on lints, that are included in `rust-lang/rust`s bootstrap
36
#![warn(rust_2018_idioms, unused_lifetimes)]

src/tools/clippy/tests/compile-test.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
// We need this feature as it changes `dylib` linking behavior and allows us to link to
2+
// `rustc_driver`.
3+
#![feature(rustc_private)]
14
#![feature(lazy_cell)]
25
#![feature(is_sorted)]
36
#![cfg_attr(feature = "deny-warnings", deny(warnings))]

src/tools/rustdoc/main.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
11
#![feature(unix_sigpipe)]
2+
// We need this feature as it changes `dylib` linking behavior and allows us to link to `rustc_driver`.
3+
#![feature(rustc_private)]
24

35
#[unix_sigpipe = "sig_dfl"]
46
fn main() {

src/tools/rustfmt/src/git-rustfmt/main.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
// We need this feature as it changes `dylib` linking behavior and allows us to link to
2+
// `rustc_driver`.
3+
#![feature(rustc_private)]
4+
15
#[macro_use]
26
extern crate tracing;
37

0 commit comments

Comments
 (0)