add "force" option to --extern
This commit is contained in:
parent
4b94c23219
commit
812f2d75e1
7 changed files with 78 additions and 2 deletions
|
@ -69,6 +69,7 @@ where
|
||||||
is_private_dep: false,
|
is_private_dep: false,
|
||||||
add_prelude: true,
|
add_prelude: true,
|
||||||
nounused_dep: false,
|
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(
|
fn inject_dependency_if(
|
||||||
&self,
|
&self,
|
||||||
krate: CrateNum,
|
krate: CrateNum,
|
||||||
|
@ -913,7 +924,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
|
||||||
// Don't worry about pathless `--extern foo` sysroot references
|
// Don't worry about pathless `--extern foo` sysroot references
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if entry.nounused_dep {
|
if entry.nounused_dep || entry.force {
|
||||||
// We're not worried about this one
|
// We're not worried about this one
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -942,6 +953,7 @@ impl<'a, 'tcx> CrateLoader<'a, 'tcx> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn postprocess(&mut self, krate: &ast::Crate) {
|
pub fn postprocess(&mut self, krate: &ast::Crate) {
|
||||||
|
self.inject_forced_externs();
|
||||||
self.inject_profiler_runtime(krate);
|
self.inject_profiler_runtime(krate);
|
||||||
self.inject_allocator_crate(krate);
|
self.inject_allocator_crate(krate);
|
||||||
self.inject_panic_runtime(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
|
/// `--extern nounused:std=/path/to/lib/libstd.rlib`. This is used to
|
||||||
/// suppress `unused-crate-dependencies` warnings.
|
/// suppress `unused-crate-dependencies` warnings.
|
||||||
pub nounused_dep: bool,
|
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)]
|
#[derive(Clone, Debug)]
|
||||||
|
@ -556,7 +562,13 @@ impl Externs {
|
||||||
|
|
||||||
impl ExternEntry {
|
impl ExternEntry {
|
||||||
fn new(location: ExternLocation) -> 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>> {
|
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 is_private_dep = false;
|
||||||
let mut add_prelude = true;
|
let mut add_prelude = true;
|
||||||
let mut nounused_dep = false;
|
let mut nounused_dep = false;
|
||||||
|
let mut force = false;
|
||||||
if let Some(opts) = options {
|
if let Some(opts) = options {
|
||||||
if !is_unstable_enabled {
|
if !is_unstable_enabled {
|
||||||
early_error(
|
early_error(
|
||||||
|
@ -2283,6 +2296,7 @@ pub fn parse_externs(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
"nounused" => nounused_dep = true,
|
"nounused" => nounused_dep = true,
|
||||||
|
"force" => force = true,
|
||||||
_ => early_error(error_format, &format!("unknown --extern option `{opt}`")),
|
_ => early_error(error_format, &format!("unknown --extern option `{opt}`")),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2293,6 +2307,8 @@ pub fn parse_externs(
|
||||||
entry.is_private_dep |= is_private_dep;
|
entry.is_private_dep |= is_private_dep;
|
||||||
// likewise `nounused`
|
// likewise `nounused`
|
||||||
entry.nounused_dep |= nounused_dep;
|
entry.nounused_dep |= nounused_dep;
|
||||||
|
// and `force`
|
||||||
|
entry.force |= force;
|
||||||
// If any flag is missing `noprelude`, then add to the prelude.
|
// If any flag is missing `noprelude`, then add to the prelude.
|
||||||
entry.add_prelude |= add_prelude;
|
entry.add_prelude |= add_prelude;
|
||||||
}
|
}
|
||||||
|
|
17
tests/ui/extern-flag/auxiliary/panic_handler.rs
Normal file
17
tests/ui/extern-flag/auxiliary/panic_handler.rs
Normal file
|
@ -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() {}
|
9
tests/ui/extern-flag/force-extern.rs
Normal file
9
tests/ui/extern-flag/force-extern.rs
Normal file
|
@ -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() {}
|
10
tests/ui/extern-flag/no-force-extern.rs
Normal file
10
tests/ui/extern-flag/no-force-extern.rs
Normal file
|
@ -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() {}
|
11
tests/ui/extern-flag/redundant-force-extern.rs
Normal file
11
tests/ui/extern-flag/redundant-force-extern.rs
Normal file
|
@ -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() {}
|
Loading…
Add table
Add a link
Reference in a new issue