add "force" option to --extern

This commit is contained in:
Matt Hammerly 2023-03-13 20:55:43 -07:00
parent 4b94c23219
commit 812f2d75e1
7 changed files with 78 additions and 2 deletions
compiler
rustc_interface/src
rustc_metadata/src
rustc_session/src
tests/ui/extern-flag

@ -69,6 +69,7 @@ where
is_private_dep: false,
add_prelude: true,
nounused_dep: false,
force: false,
}
}

@ -865,6 +865,17 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
}
}
fn inject_forced_externs(&mut self) {
for (name, entry) in self.sess.opts.externs.iter() {
if entry.force {
let name_interned = Symbol::intern(name);
if !self.used_extern_options.contains(&name_interned) {
self.resolve_crate(name_interned, DUMMY_SP, CrateDepKind::Explicit);
}
}
}
}
fn inject_dependency_if(
&self,
krate: CrateNum,
@ -913,7 +924,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
// Don't worry about pathless `--extern foo` sysroot references
continue;
}
if entry.nounused_dep {
if entry.nounused_dep || entry.force {
// We're not worried about this one
continue;
}
@ -942,6 +953,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
}
pub fn postprocess(&mut self, krate: &ast::Crate) {
self.inject_forced_externs();
self.inject_profiler_runtime(krate);
self.inject_allocator_crate(krate);
self.inject_panic_runtime(krate);

@ -518,6 +518,12 @@ pub struct ExternEntry {
/// `--extern nounused:std=/path/to/lib/libstd.rlib`. This is used to
/// suppress `unused-crate-dependencies` warnings.
pub nounused_dep: bool,
/// If the extern entry is not referenced in the crate, force it to be resolved anyway.
///
/// Allows a dependency satisfying, for instance, a missing panic handler to be injected
/// without modifying source:
/// `--extern force:extras=/path/to/lib/libstd.rlib`
pub force: bool,
}
#[derive(Clone, Debug)]
@ -556,7 +562,13 @@ impl Externs {
impl ExternEntry {
fn new(location: ExternLocation) -> ExternEntry {
ExternEntry { location, is_private_dep: false, add_prelude: false, nounused_dep: false }
ExternEntry {
location,
is_private_dep: false,
add_prelude: false,
nounused_dep: false,
force: false,
}
}
pub fn files(&self) -> Option<impl Iterator<Item = &CanonicalizedPath>> {
@ -2261,6 +2273,7 @@ pub fn parse_externs(
let mut is_private_dep = false;
let mut add_prelude = true;
let mut nounused_dep = false;
let mut force = false;
if let Some(opts) = options {
if !is_unstable_enabled {
early_error(
@ -2283,6 +2296,7 @@ pub fn parse_externs(
}
}
"nounused" => nounused_dep = true,
"force" => force = true,
_ => early_error(error_format, &format!("unknown --extern option `{opt}`")),
}
}
@ -2293,6 +2307,8 @@ pub fn parse_externs(
entry.is_private_dep |= is_private_dep;
// likewise `nounused`
entry.nounused_dep |= nounused_dep;
// and `force`
entry.force |= force;
// If any flag is missing `noprelude`, then add to the prelude.
entry.add_prelude |= add_prelude;
}

@ -0,0 +1,17 @@
#![feature(lang_items)]
#![no_std]
// Since `rustc` generally passes `-nodefaultlibs` to the linker,
// Rust programs link necessary system libraries via `#[link()]`
// attributes in the `libc` crate. `libc` is a dependency of `std`,
// but as we are `#![no_std]`, we need to include it manually.
#![feature(rustc_private)]
extern crate libc;
#[panic_handler]
pub fn begin_panic_handler(_info: &core::panic::PanicInfo<'_>) -> ! {
loop {}
}
#[lang = "eh_personality"]
extern "C" fn eh_personality() {}

@ -0,0 +1,9 @@
// check-pass
// ignore-cross-compile (needs dylibs and compiletest doesn't have a more specific header)
// aux-crate:force:panic_handler=panic_handler.rs
// compile-flags: -Zunstable-options --crate-type dylib
// edition:2018
#![no_std]
fn foo() {}

@ -0,0 +1,10 @@
// aux-crate:panic_handler=panic_handler.rs
// ignore-cross-compile (needs dylibs and compiletest doesn't have a more specific header)
// compile_flags: -Zunstable-options --crate-type dylib
// error-pattern: `#[panic_handler]` function required, but not found
// dont-check-compiler-stderr
// edition: 2018
#![no_std]
fn foo() {}

@ -0,0 +1,11 @@
// check-pass
// ignore-cross-compile (needs dylibs and compiletest doesn't have a more specific header)
// aux-crate:force:panic_handler=panic_handler.rs
// compile-flags: -Zunstable-options --crate-type dylib
// edition:2018
#![no_std]
extern crate panic_handler;
fn foo() {}