2014-05-24 18:16:10 -05:00
|
|
|
// Copyright 2012-2013 The Rust Project Developers. See the COPYRIGHT
|
|
|
|
// file at the top-level directory of this distribution and at
|
|
|
|
// http://rust-lang.org/COPYRIGHT.
|
|
|
|
//
|
|
|
|
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
|
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
|
|
|
|
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
|
|
|
|
// option. This file may not be copied, modified, or distributed
|
|
|
|
// except according to those terms.
|
|
|
|
|
2015-02-11 21:53:10 -06:00
|
|
|
//! Used by `rustc` when loading a plugin.
|
2014-05-26 16:48:54 -05:00
|
|
|
|
2015-11-22 14:14:09 -06:00
|
|
|
use rustc::session::Session;
|
2016-10-19 04:34:19 -05:00
|
|
|
use rustc_metadata::creader::CrateLoader;
|
2015-11-24 16:00:26 -06:00
|
|
|
use rustc_metadata::cstore::CStore;
|
2015-11-22 14:14:09 -06:00
|
|
|
use registry::Registry;
|
2014-05-24 18:16:10 -05:00
|
|
|
|
2015-02-06 15:56:38 -06:00
|
|
|
use std::borrow::ToOwned;
|
2015-02-26 23:00:43 -06:00
|
|
|
use std::env;
|
|
|
|
use std::mem;
|
|
|
|
use std::path::PathBuf;
|
2014-05-24 18:16:10 -05:00
|
|
|
use syntax::ast;
|
2017-03-16 23:04:41 -05:00
|
|
|
use syntax_pos::{Span, DUMMY_SP};
|
2014-05-24 18:16:10 -05:00
|
|
|
|
2014-05-26 16:48:54 -05:00
|
|
|
/// Pointer to a registrar function.
|
|
|
|
pub type PluginRegistrarFun =
|
|
|
|
fn(&mut Registry);
|
|
|
|
|
2015-01-02 20:26:00 -06:00
|
|
|
pub struct PluginRegistrar {
|
|
|
|
pub fun: PluginRegistrarFun,
|
2016-08-19 20:58:14 -05:00
|
|
|
pub args: Vec<ast::NestedMetaItem>,
|
2015-01-02 20:26:00 -06:00
|
|
|
}
|
|
|
|
|
2015-02-11 21:53:10 -06:00
|
|
|
struct PluginLoader<'a> {
|
2014-05-24 18:16:10 -05:00
|
|
|
sess: &'a Session,
|
2016-10-19 04:34:19 -05:00
|
|
|
reader: CrateLoader<'a>,
|
2015-02-11 21:53:10 -06:00
|
|
|
plugins: Vec<PluginRegistrar>,
|
2014-05-24 18:16:10 -05:00
|
|
|
}
|
|
|
|
|
2015-09-14 14:25:04 -05:00
|
|
|
fn call_malformed_plugin_attribute(a: &Session, b: Span) {
|
|
|
|
span_err!(a, b, E0498, "malformed plugin attribute");
|
|
|
|
}
|
|
|
|
|
2014-05-26 16:48:54 -05:00
|
|
|
/// Read plugin metadata and dynamically load registrar functions.
|
2016-02-26 15:25:25 -06:00
|
|
|
pub fn load_plugins(sess: &Session,
|
|
|
|
cstore: &CStore,
|
|
|
|
krate: &ast::Crate,
|
|
|
|
crate_name: &str,
|
2015-02-11 21:53:10 -06:00
|
|
|
addl_plugins: Option<Vec<String>>) -> Vec<PluginRegistrar> {
|
2016-10-27 01:36:56 -05:00
|
|
|
let mut loader = PluginLoader::new(sess, cstore, crate_name);
|
2015-01-03 00:21:28 -06:00
|
|
|
|
2016-04-06 17:43:03 -05:00
|
|
|
// do not report any error now. since crate attributes are
|
|
|
|
// not touched by expansion, every use of plugin without
|
|
|
|
// the feature enabled will result in an error later...
|
|
|
|
if sess.features.borrow().plugin {
|
|
|
|
for attr in &krate.attrs {
|
|
|
|
if !attr.check_name("plugin") {
|
2015-02-06 15:56:38 -06:00
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
2016-04-06 17:43:03 -05:00
|
|
|
let plugins = match attr.meta_item_list() {
|
|
|
|
Some(xs) => xs,
|
|
|
|
None => {
|
|
|
|
call_malformed_plugin_attribute(sess, attr.span);
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
for plugin in plugins {
|
2016-08-19 20:58:14 -05:00
|
|
|
// plugins must have a name and can't be key = value
|
|
|
|
match plugin.name() {
|
2016-11-14 22:34:52 -06:00
|
|
|
Some(name) if !plugin.is_value_str() => {
|
2016-08-19 20:58:14 -05:00
|
|
|
let args = plugin.meta_item_list().map(ToOwned::to_owned);
|
2016-11-14 22:34:52 -06:00
|
|
|
loader.load_plugin(plugin.span, &name.as_str(), args.unwrap_or_default());
|
2016-08-19 20:58:14 -05:00
|
|
|
},
|
|
|
|
_ => call_malformed_plugin_attribute(sess, attr.span),
|
2016-04-06 17:43:03 -05:00
|
|
|
}
|
|
|
|
}
|
2015-02-06 15:56:38 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-12-09 11:25:37 -06:00
|
|
|
if let Some(plugins) = addl_plugins {
|
2015-02-01 20:53:25 -06:00
|
|
|
for plugin in plugins {
|
2017-03-16 23:04:41 -05:00
|
|
|
loader.load_plugin(DUMMY_SP, &plugin, vec![]);
|
2014-07-19 23:54:37 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-02-11 21:53:10 -06:00
|
|
|
loader.plugins
|
2014-12-09 10:44:08 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
impl<'a> PluginLoader<'a> {
|
2016-10-27 01:36:56 -05:00
|
|
|
fn new(sess: &'a Session, cstore: &'a CStore, crate_name: &str) -> Self {
|
2015-02-11 21:53:10 -06:00
|
|
|
PluginLoader {
|
|
|
|
sess: sess,
|
2016-10-27 01:36:56 -05:00
|
|
|
reader: CrateLoader::new(sess, cstore, crate_name),
|
2015-02-11 21:53:10 -06:00
|
|
|
plugins: vec![],
|
2015-02-10 21:30:33 -06:00
|
|
|
}
|
2015-02-06 15:56:38 -06:00
|
|
|
}
|
|
|
|
|
2016-08-19 20:58:14 -05:00
|
|
|
fn load_plugin(&mut self, span: Span, name: &str, args: Vec<ast::NestedMetaItem>) {
|
2015-02-11 20:43:16 -06:00
|
|
|
let registrar = self.reader.find_plugin_registrar(span, name);
|
2015-01-01 18:37:47 -06:00
|
|
|
|
2017-04-13 14:55:48 -05:00
|
|
|
if let Some((lib, disambiguator, index)) = registrar {
|
|
|
|
let symbol = self.sess.generate_plugin_registrar_symbol(disambiguator, index);
|
2015-02-11 20:43:16 -06:00
|
|
|
let fun = self.dylink_registrar(span, lib, symbol);
|
2015-02-11 21:53:10 -06:00
|
|
|
self.plugins.push(PluginRegistrar {
|
2015-01-02 20:26:00 -06:00
|
|
|
fun: fun,
|
2015-02-06 15:56:38 -06:00
|
|
|
args: args,
|
2015-01-02 20:26:00 -06:00
|
|
|
});
|
2014-05-24 18:16:10 -05:00
|
|
|
}
|
|
|
|
}
|
2014-12-31 21:48:39 -06:00
|
|
|
|
2014-05-24 18:16:10 -05:00
|
|
|
// Dynamically link a registrar function into the compiler process.
|
2015-02-11 20:43:16 -06:00
|
|
|
fn dylink_registrar(&mut self,
|
|
|
|
span: Span,
|
2015-02-26 23:00:43 -06:00
|
|
|
path: PathBuf,
|
2015-01-02 20:26:00 -06:00
|
|
|
symbol: String) -> PluginRegistrarFun {
|
2016-03-07 17:42:29 -06:00
|
|
|
use rustc_back::dynamic_lib::DynamicLibrary;
|
std: Stabilize library APIs for 1.5
This commit stabilizes and deprecates library APIs whose FCP has closed in the
last cycle, specifically:
Stabilized APIs:
* `fs::canonicalize`
* `Path::{metadata, symlink_metadata, canonicalize, read_link, read_dir, exists,
is_file, is_dir}` - all moved to inherent methods from the `PathExt` trait.
* `Formatter::fill`
* `Formatter::width`
* `Formatter::precision`
* `Formatter::sign_plus`
* `Formatter::sign_minus`
* `Formatter::alternate`
* `Formatter::sign_aware_zero_pad`
* `string::ParseError`
* `Utf8Error::valid_up_to`
* `Iterator::{cmp, partial_cmp, eq, ne, lt, le, gt, ge}`
* `<[T]>::split_{first,last}{,_mut}`
* `Condvar::wait_timeout` - note that `wait_timeout_ms` is not yet deprecated
but will be once 1.5 is released.
* `str::{R,}MatchIndices`
* `str::{r,}match_indices`
* `char::from_u32_unchecked`
* `VecDeque::insert`
* `VecDeque::shrink_to_fit`
* `VecDeque::as_slices`
* `VecDeque::as_mut_slices`
* `VecDeque::swap_remove_front` - (renamed from `swap_front_remove`)
* `VecDeque::swap_remove_back` - (renamed from `swap_back_remove`)
* `Vec::resize`
* `str::slice_mut_unchecked`
* `FileTypeExt`
* `FileTypeExt::{is_block_device, is_char_device, is_fifo, is_socket}`
* `BinaryHeap::from` - `from_vec` deprecated in favor of this
* `BinaryHeap::into_vec` - plus a `Into` impl
* `BinaryHeap::into_sorted_vec`
Deprecated APIs
* `slice::ref_slice`
* `slice::mut_ref_slice`
* `iter::{range_inclusive, RangeInclusive}`
* `std::dynamic_lib`
Closes #27706
Closes #27725
cc #27726 (align not stabilized yet)
Closes #27734
Closes #27737
Closes #27742
Closes #27743
Closes #27772
Closes #27774
Closes #27777
Closes #27781
cc #27788 (a few remaining methods though)
Closes #27790
Closes #27793
Closes #27796
Closes #27810
cc #28147 (not all parts stabilized)
2015-10-22 18:28:45 -05:00
|
|
|
|
2014-05-24 18:16:10 -05:00
|
|
|
// Make sure the path contains a / or the linker will search for it.
|
2015-02-26 23:00:43 -06:00
|
|
|
let path = env::current_dir().unwrap().join(&path);
|
2014-05-24 18:16:10 -05:00
|
|
|
|
|
|
|
let lib = match DynamicLibrary::open(Some(&path)) {
|
|
|
|
Ok(lib) => lib,
|
|
|
|
// this is fatal: there are almost certainly macros we need
|
|
|
|
// inside this crate, so continue would spew "macro undefined"
|
|
|
|
// errors
|
2014-12-09 10:44:08 -06:00
|
|
|
Err(err) => {
|
2017-03-24 03:31:26 -05:00
|
|
|
self.sess.span_fatal(span, &err)
|
2014-12-09 10:44:08 -06:00
|
|
|
}
|
2014-05-24 18:16:10 -05:00
|
|
|
};
|
|
|
|
|
|
|
|
unsafe {
|
2014-06-12 16:08:44 -05:00
|
|
|
let registrar =
|
2017-03-24 03:31:26 -05:00
|
|
|
match lib.symbol(&symbol) {
|
2014-06-12 16:08:44 -05:00
|
|
|
Ok(registrar) => {
|
2014-06-25 14:47:34 -05:00
|
|
|
mem::transmute::<*mut u8,PluginRegistrarFun>(registrar)
|
2014-06-12 16:08:44 -05:00
|
|
|
}
|
2014-05-24 18:16:10 -05:00
|
|
|
// again fatal if we can't register macros
|
2014-12-09 10:44:08 -06:00
|
|
|
Err(err) => {
|
2017-03-24 03:31:26 -05:00
|
|
|
self.sess.span_fatal(span, &err)
|
2014-12-09 10:44:08 -06:00
|
|
|
}
|
2014-05-24 18:16:10 -05:00
|
|
|
};
|
|
|
|
|
|
|
|
// Intentionally leak the dynamic library. We can't ever unload it
|
|
|
|
// since the library can make things that will live arbitrarily long
|
2015-05-08 10:12:29 -05:00
|
|
|
// (e.g. an @-box cycle or a thread).
|
2014-05-24 18:16:10 -05:00
|
|
|
mem::forget(lib);
|
|
|
|
|
2015-01-02 20:26:00 -06:00
|
|
|
registrar
|
2014-05-24 18:16:10 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|