in checker/src/main.rs [35:144]
fn main() {
// Initialize loggers.
if env::var("RUSTC_LOG").is_ok() {
rustc_driver::init_rustc_env_logger();
}
if env::var("MIRAI_LOG").is_ok() {
let e = env_logger::Env::new()
.filter("MIRAI_LOG")
.write_style("MIRAI_LOG_STYLE");
env_logger::init_from_env(e);
}
// Get any options specified via the MIRAI_FLAGS environment variable
let mut options = Options::default();
let rustc_args = options.parse_from_str(&env::var("MIRAI_FLAGS").unwrap_or_default(), false);
info!("MIRAI options from environment: {:?}", options);
// Let arguments supplied on the command line override the environment variable.
let mut args = env::args_os()
.enumerate()
.map(|(i, arg)| {
arg.into_string().unwrap_or_else(|arg| {
early_error(
ErrorOutputType::default(),
&format!("Argument {} is not valid Unicode: {:?}", i, arg),
)
})
})
.collect::<Vec<_>>();
assume!(!args.is_empty());
// Setting RUSTC_WRAPPER causes Cargo to pass 'rustc' as the first argument.
// We're invoking the compiler programmatically, so we remove it if present.
if args.len() > 1 && Path::new(&args[1]).file_stem() == Some("rustc".as_ref()) {
args.remove(1);
}
let mut rustc_command_line_arguments = options.parse(&args[1..], false);
info!("MIRAI options modified by command line: {:?}", options);
rustc_driver::install_ice_hook();
let result = rustc_driver::catch_fatal_errors(|| {
// Add back the binary name
rustc_command_line_arguments.insert(0, args[0].clone());
let print: String = "--print=".into();
if rustc_command_line_arguments
.iter()
.any(|arg| arg.starts_with(&print))
{
// If a --print option is given on the command line we wont get called to analyze
// anything. We also don't want to the caller to know that MIRAI adds configuration
// parameters to the command line, lest the caller be cargo and it panics because
// the output from --print=cfg is not what it expects.
} else {
// Add rustc arguments supplied via the MIRAI_FLAGS environment variable
rustc_command_line_arguments.extend(rustc_args);
let sysroot: String = "--sysroot".into();
if !rustc_command_line_arguments
.iter()
.any(|arg| arg.starts_with(&sysroot))
{
// Tell compiler where to find the std library and so on.
// The compiler relies on the standard rustc driver to tell it, so we have to do likewise.
rustc_command_line_arguments.push(sysroot);
rustc_command_line_arguments.push(utils::find_sysroot());
}
let always_encode_mir: String = "always-encode-mir".into();
if !rustc_command_line_arguments
.iter()
.any(|arg| arg.ends_with(&always_encode_mir))
{
// Tell compiler to emit MIR into crate for every function with a body.
rustc_command_line_arguments.push("-Z".into());
rustc_command_line_arguments.push(always_encode_mir);
}
if options.test_only {
let prefix: String = "mirai_annotations=".into();
let postfix: String = ".rmeta".into();
if let Some((_, s)) = rustc_command_line_arguments
.iter_mut()
.find_position(|arg| arg.starts_with(&prefix))
{
if s.ends_with(&postfix) {
*s = s.replace(&postfix, ".rlib");
}
}
}
}
let mut callbacks = callbacks::MiraiCallbacks::new(options);
debug!(
"rustc_command_line_arguments {:?}",
rustc_command_line_arguments
);
let compiler =
rustc_driver::RunCompiler::new(&rustc_command_line_arguments, &mut callbacks);
compiler.run()
})
.and_then(|result| result);
let exit_code = match result {
Ok(_) => rustc_driver::EXIT_SUCCESS,
Err(_) => rustc_driver::EXIT_FAILURE,
};
std::process::exit(exit_code);
}