1
Fork 0

rustc: add unstable support for --extern crate_name without a path.

This commit is contained in:
Eduard-Mihai Burtescu 2018-08-24 18:51:10 +03:00
parent afc2149c05
commit 26b1ed1b92
4 changed files with 37 additions and 27 deletions

View file

@ -275,18 +275,18 @@ impl OutputTypes {
// DO NOT switch BTreeMap or BTreeSet out for an unsorted container type! That // DO NOT switch BTreeMap or BTreeSet out for an unsorted container type! That
// would break dependency tracking for commandline arguments. // would break dependency tracking for commandline arguments.
#[derive(Clone, Hash)] #[derive(Clone, Hash)]
pub struct Externs(BTreeMap<String, BTreeSet<String>>); pub struct Externs(BTreeMap<String, BTreeSet<Option<String>>>);
impl Externs { impl Externs {
pub fn new(data: BTreeMap<String, BTreeSet<String>>) -> Externs { pub fn new(data: BTreeMap<String, BTreeSet<Option<String>>>) -> Externs {
Externs(data) Externs(data)
} }
pub fn get(&self, key: &str) -> Option<&BTreeSet<String>> { pub fn get(&self, key: &str) -> Option<&BTreeSet<Option<String>>> {
self.0.get(key) self.0.get(key)
} }
pub fn iter<'a>(&'a self) -> BTreeMapIter<'a, String, BTreeSet<String>> { pub fn iter<'a>(&'a self) -> BTreeMapIter<'a, String, BTreeSet<Option<String>>> {
self.0.iter() self.0.iter()
} }
} }
@ -2169,6 +2169,8 @@ pub fn build_session_options_and_crate_config(
let cfg = parse_cfgspecs(matches.opt_strs("cfg")); let cfg = parse_cfgspecs(matches.opt_strs("cfg"));
let test = matches.opt_present("test"); let test = matches.opt_present("test");
let is_unstable_enabled = nightly_options::is_unstable_enabled(matches);
prints.extend(matches.opt_strs("print").into_iter().map(|s| match &*s { prints.extend(matches.opt_strs("print").into_iter().map(|s| match &*s {
"crate-name" => PrintRequest::CrateName, "crate-name" => PrintRequest::CrateName,
"file-names" => PrintRequest::FileNames, "file-names" => PrintRequest::FileNames,
@ -2182,15 +2184,13 @@ pub fn build_session_options_and_crate_config(
"tls-models" => PrintRequest::TlsModels, "tls-models" => PrintRequest::TlsModels,
"native-static-libs" => PrintRequest::NativeStaticLibs, "native-static-libs" => PrintRequest::NativeStaticLibs,
"target-spec-json" => { "target-spec-json" => {
if nightly_options::is_unstable_enabled(matches) { if is_unstable_enabled {
PrintRequest::TargetSpec PrintRequest::TargetSpec
} else { } else {
early_error( early_error(
error_format, error_format,
&format!( "the `-Z unstable-options` flag must also be passed to \
"the `-Z unstable-options` flag must also be passed to \ enable the target-spec-json print option",
enable the target-spec-json print option"
),
); );
} }
} }
@ -2220,18 +2220,19 @@ pub fn build_session_options_and_crate_config(
Some(s) => s, Some(s) => s,
None => early_error(error_format, "--extern value must not be empty"), None => early_error(error_format, "--extern value must not be empty"),
}; };
let location = match parts.next() { let location = parts.next().map(|s| s.to_string());
Some(s) => s, if location.is_none() && !is_unstable_enabled {
None => early_error( early_error(
error_format, error_format,
"--extern value must be of the format `foo=bar`", "the `-Z unstable-options` flag must also be passed to \
), enable `--extern crate_name` without `=path`",
);
}; };
externs externs
.entry(name.to_string()) .entry(name.to_string())
.or_default() .or_default()
.insert(location.to_string()); .insert(location);
} }
let crate_name = matches.opt_str("crate-name"); let crate_name = matches.opt_str("crate-name");
@ -2687,33 +2688,33 @@ mod tests {
v1.externs = Externs::new(mk_map(vec![ v1.externs = Externs::new(mk_map(vec![
( (
String::from("a"), String::from("a"),
mk_set(vec![String::from("b"), String::from("c")]), mk_set(vec![Some(String::from("b")), Some(String::from("c"))]),
), ),
( (
String::from("d"), String::from("d"),
mk_set(vec![String::from("e"), String::from("f")]), mk_set(vec![Some(String::from("e")), Some(String::from("f"))]),
), ),
])); ]));
v2.externs = Externs::new(mk_map(vec![ v2.externs = Externs::new(mk_map(vec![
( (
String::from("d"), String::from("d"),
mk_set(vec![String::from("e"), String::from("f")]), mk_set(vec![Some(String::from("e")), Some(String::from("f"))]),
), ),
( (
String::from("a"), String::from("a"),
mk_set(vec![String::from("b"), String::from("c")]), mk_set(vec![Some(String::from("b")), Some(String::from("c"))]),
), ),
])); ]));
v3.externs = Externs::new(mk_map(vec![ v3.externs = Externs::new(mk_map(vec![
( (
String::from("a"), String::from("a"),
mk_set(vec![String::from("b"), String::from("c")]), mk_set(vec![Some(String::from("b")), Some(String::from("c"))]),
), ),
( (
String::from("d"), String::from("d"),
mk_set(vec![String::from("f"), String::from("e")]), mk_set(vec![Some(String::from("f")), Some(String::from("e"))]),
), ),
])); ]));

View file

@ -132,7 +132,8 @@ impl<'a> CrateLoader<'a> {
// from the strings on the command line. // from the strings on the command line.
let source = &self.cstore.get_crate_data(cnum).source; let source = &self.cstore.get_crate_data(cnum).source;
if let Some(locs) = self.sess.opts.externs.get(&*name.as_str()) { if let Some(locs) = self.sess.opts.externs.get(&*name.as_str()) {
let found = locs.iter().any(|l| { // Only use `--extern crate_name=path` here, not `--extern crate_name`.
let found = locs.iter().filter_map(|l| l.as_ref()).any(|l| {
let l = fs::canonicalize(l).ok(); let l = fs::canonicalize(l).ok();
source.dylib.as_ref().map(|p| &p.0) == l.as_ref() || source.dylib.as_ref().map(|p| &p.0) == l.as_ref() ||
source.rlib.as_ref().map(|p| &p.0) == l.as_ref() source.rlib.as_ref().map(|p| &p.0) == l.as_ref()

View file

@ -438,7 +438,12 @@ impl<'a> Context<'a> {
if self.hash.is_none() { if self.hash.is_none() {
self.should_match_name = false; self.should_match_name = false;
if let Some(s) = self.sess.opts.externs.get(&self.crate_name.as_str()) { if let Some(s) = self.sess.opts.externs.get(&self.crate_name.as_str()) {
return self.find_commandline_library(s.iter()); // Only use `--extern crate_name=path` here, not `--extern crate_name`.
if s.iter().any(|l| l.is_some()) {
return self.find_commandline_library(
s.iter().filter_map(|l| l.as_ref()),
);
}
} }
self.should_match_name = true; self.should_match_name = true;
} }

View file

@ -609,16 +609,19 @@ where R: 'static + Send, F: 'static + Send + FnOnce(Output) -> R {
/// Extracts `--extern CRATE=PATH` arguments from `matches` and /// Extracts `--extern CRATE=PATH` arguments from `matches` and
/// returns a map mapping crate names to their paths or else an /// returns a map mapping crate names to their paths or else an
/// error message. /// error message.
// FIXME(eddyb) This shouldn't be duplicated with `rustc::session`.
fn parse_externs(matches: &getopts::Matches) -> Result<Externs, String> { fn parse_externs(matches: &getopts::Matches) -> Result<Externs, String> {
let mut externs: BTreeMap<_, BTreeSet<_>> = BTreeMap::new(); let mut externs: BTreeMap<_, BTreeSet<_>> = BTreeMap::new();
for arg in &matches.opt_strs("extern") { for arg in &matches.opt_strs("extern") {
let mut parts = arg.splitn(2, '='); let mut parts = arg.splitn(2, '=');
let name = parts.next().ok_or("--extern value must not be empty".to_string())?; let name = parts.next().ok_or("--extern value must not be empty".to_string())?;
let location = parts.next() let location = parts.next().map(|s| s.to_string());
.ok_or("--extern value must be of the format `foo=bar`" if location.is_none() && !nightly_options::is_unstable_enabled(matches) {
.to_string())?; return Err("the `-Z unstable-options` flag must also be passed to \
enable `--extern crate_name` without `=path`".to_string());
}
let name = name.to_string(); let name = name.to_string();
externs.entry(name).or_default().insert(location.to_string()); externs.entry(name).or_default().insert(location);
} }
Ok(Externs::new(externs)) Ok(Externs::new(externs))
} }