Skip to content

[experiment] Build the compiler with panic=abort #124362

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

Draft
wants to merge 6 commits into
base: master
Choose a base branch
from
Draft
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
2 changes: 2 additions & 0 deletions compiler/rustc/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
#![feature(unix_sigpipe)]
// We need this feature as it changes `dylib` linking behavior and allows us to link to `rustc_driver`.
#![feature(rustc_private)]

// A note about jemalloc: rustc uses jemalloc when built for CI and
// distribution. The obvious way to do this is with the `#[global_allocator]`
Expand Down
3 changes: 3 additions & 0 deletions compiler/rustc_metadata/messages.ftl
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ metadata_crate_dep_multiple =
metadata_crate_dep_not_static =
`{$crate_name}` was unavailable as a static crate, preventing fully static linking

metadata_crate_dep_rustc_driver =
`feature(rustc_private)` is needed to link to the compiler's `rustc_driver` library

metadata_crate_location_unknown_type =
extern location for {$crate_name} is of an unknown type: {$path}

Expand Down
55 changes: 42 additions & 13 deletions compiler/rustc_metadata/src/dependency_format.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,16 +54,18 @@
use crate::creader::CStore;
use crate::errors::{
BadPanicStrategy, CrateDepMultiple, IncompatiblePanicInDropStrategy, LibRequired,
NonStaticCrateDep, RequiredPanicStrategy, RlibRequired, RustcLibRequired, TwoPanicRuntimes,
NonStaticCrateDep, RequiredPanicStrategy, RlibRequired, RustcDriverHelp, RustcLibRequired,
TwoPanicRuntimes,
};

use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_hir::def_id::CrateNum;
use rustc_middle::middle::dependency_format::{Dependencies, DependencyList, Linkage};
use rustc_middle::ty::TyCtxt;
use rustc_session::config::CrateType;
use rustc_session::cstore::CrateDepKind;
use rustc_session::cstore::LinkagePreference::{self, RequireDynamic, RequireStatic};
use rustc_span::sym;

pub(crate) fn calculate(tcx: TyCtxt<'_>) -> Dependencies {
tcx.crate_types()
Expand Down Expand Up @@ -158,25 +160,49 @@ fn calculate_type(tcx: TyCtxt<'_>, ty: CrateType) -> DependencyList {
Linkage::Dynamic | Linkage::IncludedFromDylib => {}
}

let all_dylibs = || {
tcx.crates(()).iter().filter(|&&cnum| {
!tcx.dep_kind(cnum).macros_only() && tcx.used_crate_source(cnum).dylib.is_some()
})
};

let mut upstream_in_dylibs = FxHashSet::default();

if tcx.features().rustc_private {
// We need this to prevent users of `rustc_driver` from linking to dynamically to `std`
// which does not work as `std` is also statically linked into `rustc_driver`.

// Find all libraries statically linked to upstream dylibs.
for &cnum in all_dylibs() {
let deps = tcx.dylib_dependency_formats(cnum);
for &(depnum, style) in deps.iter() {
if let RequireStatic = style {
upstream_in_dylibs.insert(depnum);
}
}
}
}

let mut formats = FxHashMap::default();

// Sweep all crates for found dylibs. Add all dylibs, as well as their
// dependencies, ensuring there are no conflicts. The only valid case for a
// dependency to be relied upon twice is for both cases to rely on a dylib.
for &cnum in tcx.crates(()).iter() {
if tcx.dep_kind(cnum).macros_only() {
for &cnum in all_dylibs() {
if upstream_in_dylibs.contains(&cnum) {
info!("skipping dylib: {}", tcx.crate_name(cnum));
// If this dylib is also available statically linked to another dylib
// we try to use that instead.
continue;
}

let name = tcx.crate_name(cnum);
let src = tcx.used_crate_source(cnum);
if src.dylib.is_some() {
info!("adding dylib: {}", name);
add_library(tcx, cnum, RequireDynamic, &mut formats, &mut unavailable_as_static);
let deps = tcx.dylib_dependency_formats(cnum);
for &(depnum, style) in deps.iter() {
info!("adding {:?}: {}", style, tcx.crate_name(depnum));
add_library(tcx, depnum, style, &mut formats, &mut unavailable_as_static);
}
info!("adding dylib: {}", name);
add_library(tcx, cnum, RequireDynamic, &mut formats, &mut unavailable_as_static);
let deps = tcx.dylib_dependency_formats(cnum);
for &(depnum, style) in deps.iter() {
info!("adding {:?}: {}", style, tcx.crate_name(depnum));
add_library(tcx, depnum, style, &mut formats, &mut unavailable_as_static);
}
}

Expand Down Expand Up @@ -266,12 +292,15 @@ fn add_library(
// This error is probably a little obscure, but I imagine that it
// can be refined over time.
if link2 != link || link == RequireStatic {
let linking_to_rustc_driver = tcx.sess.psess.unstable_features.is_nightly_build()
&& tcx.crates(()).iter().any(|&cnum| tcx.crate_name(cnum) == sym::rustc_driver);
tcx.dcx().emit_err(CrateDepMultiple {
crate_name: tcx.crate_name(cnum),
non_static_deps: unavailable_as_static
.drain(..)
.map(|cnum| NonStaticCrateDep { crate_name: tcx.crate_name(cnum) })
.collect(),
rustc_driver_help: linking_to_rustc_driver.then_some(RustcDriverHelp),
});
}
}
Expand Down
6 changes: 6 additions & 0 deletions compiler/rustc_metadata/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,8 @@ pub struct CrateDepMultiple {
pub crate_name: Symbol,
#[subdiagnostic]
pub non_static_deps: Vec<NonStaticCrateDep>,
#[subdiagnostic]
pub rustc_driver_help: Option<RustcDriverHelp>,
}

#[derive(Subdiagnostic)]
Expand All @@ -48,6 +50,10 @@ pub struct NonStaticCrateDep {
pub crate_name: Symbol,
}

#[derive(Subdiagnostic)]
#[help(metadata_crate_dep_rustc_driver)]
pub struct RustcDriverHelp;

#[derive(Diagnostic)]
#[diag(metadata_two_panic_runtimes)]
pub struct TwoPanicRuntimes {
Expand Down
1 change: 1 addition & 0 deletions compiler/rustc_span/src/symbol.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1573,6 +1573,7 @@ symbols! {
rustc_dirty,
rustc_do_not_const_check,
rustc_doc_primitive,
rustc_driver,
rustc_dummy,
rustc_dump_env_program_clauses,
rustc_dump_program_clauses,
Expand Down
20 changes: 17 additions & 3 deletions src/bootstrap/src/bin/rustc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,23 @@ fn main() {
rustc_real
};

// Get the name of the crate we're compiling, if any.
let crate_name = arg("--crate-name");

// We want everything statically linked into `rustc_driver`, so remove `-C prefer-dynamic`
if crate_name == Some("rustc_driver") && stage != "0" {
// Remove `-C prefer-dynamic` to link `std` statically into `rustc_driver`
if let Some(pos) = args.iter().enumerate().position(|(i, a)| {
a == "-C" && args.get(i + 1).map(|a| a == "prefer-dynamic").unwrap_or(false)
}) {
args.remove(pos);
args.remove(pos);
}
if let Some(pos) = args.iter().position(|a| a == "-Cprefer-dynamic") {
args.remove(pos);
}
}

let mut cmd = if let Some(wrapper) = env::var_os("RUSTC_WRAPPER_REAL") {
let mut cmd = Command::new(wrapper);
cmd.arg(rustc_driver);
Expand All @@ -100,9 +117,6 @@ fn main() {
};
cmd.args(&args).env(dylib_path_var(), env::join_paths(&dylib_path).unwrap());

// Get the name of the crate we're compiling, if any.
let crate_name = arg("--crate-name");

if let Some(crate_name) = crate_name {
if let Some(target) = env::var_os("RUSTC_TIME") {
if target == "all"
Expand Down
12 changes: 11 additions & 1 deletion src/bootstrap/src/core/build_steps/compile.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1079,6 +1079,11 @@ pub fn rustc_cargo(
));
}

if compiler.stage != 0 {
cargo.rustflag("-Cpanic=abort");
cargo.rustflag("-Cforce-unwind-tables=yes");
}

rustc_cargo_env(builder, cargo, target, compiler.stage);
}

Expand Down Expand Up @@ -1780,7 +1785,12 @@ impl Step for Assemble {
let src_libdir = builder.sysroot_libdir(build_compiler, host);
for f in builder.read_dir(&src_libdir) {
let filename = f.file_name().into_string().unwrap();
if (is_dylib(&filename) || is_debug_info(&filename)) && !proc_macros.contains(&filename)
let can_be_rustc_dep = filename.starts_with("rustc_driver-")
|| filename.starts_with("librustc_driver-")
|| build_compiler.stage == 0;
if can_be_rustc_dep
&& (is_dylib(&filename) || is_debug_info(&filename))
&& !proc_macros.contains(&filename)
{
builder.copy_link(&f.path(), &rustc_libdir.join(&filename));
}
Expand Down
13 changes: 13 additions & 0 deletions src/bootstrap/src/core/build_steps/tool.rs
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,19 @@ pub fn prepare_tool_cargo(
}
}

if compiler.stage != 0 {
if path.ends_with("rls")
|| path.ends_with("clippy")
|| path.ends_with("miri")
|| path.ends_with("rustfmt")
|| path.ends_with("rustdoc")
|| path.ends_with("rustdoc-tool")
{
cargo.rustflag("-Cpanic=abort");
cargo.rustflag("-Cforce-unwind-tables=yes");
}
}

// clippy tests need to know about the stage sysroot. Set them consistently while building to
// avoid rebuilding when running tests.
cargo.env("SYSROOT", builder.sysroot(compiler));
Expand Down
2 changes: 1 addition & 1 deletion src/bootstrap/src/core/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2064,7 +2064,7 @@ impl<'a> Builder<'a> {
// When we build Rust dylibs they're all intended for intermediate
// usage, so make sure we pass the -Cprefer-dynamic flag instead of
// linking all deps statically into the dylib.
if matches!(mode, Mode::Std | Mode::Rustc) {
if matches!(mode, Mode::Std) {
rustflags.arg("-Cprefer-dynamic");
}

Expand Down
2 changes: 1 addition & 1 deletion src/ci/github-actions/jobs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ pr:
try:
- image: dist-x86_64-linux
env:
CODEGEN_BACKENDS: llvm,cranelift
CODEGEN_BACKENDS: llvm
<<: *job-linux-16c

# Main CI jobs that have to be green to merge a commit into master
Expand Down
3 changes: 3 additions & 0 deletions src/tools/clippy/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
// We need this feature as it changes `dylib` linking behavior and allows us to link to
// `rustc_driver`.
#![feature(rustc_private)]
#![cfg_attr(feature = "deny-warnings", deny(warnings))]
// warn on lints, that are included in `rust-lang/rust`s bootstrap
#![warn(rust_2018_idioms, unused_lifetimes)]
Expand Down
3 changes: 3 additions & 0 deletions src/tools/clippy/tests/compile-test.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
// We need this feature as it changes `dylib` linking behavior and allows us to link to
// `rustc_driver`.
#![feature(rustc_private)]
#![feature(lazy_cell)]
#![feature(is_sorted)]
#![cfg_attr(feature = "deny-warnings", deny(warnings))]
Expand Down
2 changes: 2 additions & 0 deletions src/tools/rustdoc/main.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
#![feature(unix_sigpipe)]
// We need this feature as it changes `dylib` linking behavior and allows us to link to `rustc_driver`.
#![feature(rustc_private)]

#[unix_sigpipe = "sig_dfl"]
fn main() {
Expand Down
4 changes: 4 additions & 0 deletions src/tools/rustfmt/src/git-rustfmt/main.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
// We need this feature as it changes `dylib` linking behavior and allows us to link to
// `rustc_driver`.
#![feature(rustc_private)]

#[macro_use]
extern crate tracing;

Expand Down