The goal of this refactoring is to make the rustc driver code easier to understand and use. Since this is as close to an API as we have, I think it is important that it is nice. On getting stuck in, I found that there wasn't as much to change as I'd hoped to make the stage... fns easier to use by tools.
This patch only moves code around - mostly just moving code to different files, but a few extracted method refactorings too. To summarise the changes: I added driver::config which handles everything about configuring the compiler. driver::session now just defines and builds session objects. I moved driver code from librustc/lib.rs to librustc/driver/mod.rs so all the code is one place. I extracted methods to make emulating the compiler without being the compiler a little easier. Within the driver directory, I moved code around to more logically fit in the modules.
// except according to those terms.
use back::target_strs;
-use driver::session::sess_os_to_meta_os;
+use driver::config::cfg_os_to_meta_os;
use metadata::loader::meta_section_name;
use syntax::abi;
return target_strs::t {
module_asm: "".to_owned(),
- meta_sect_name: meta_section_name(sess_os_to_meta_os(target_os)).to_owned(),
+ meta_sect_name: meta_section_name(cfg_os_to_meta_os(target_os)).to_owned(),
data_layout: match target_os {
abi::OsMacos => {
use back::rpath;
use back::svh::Svh;
use driver::driver::{CrateTranslation, OutputFilenames};
-use driver::session::{NoDebugInfo, Session};
-use driver::session;
+use driver::config::NoDebugInfo;
+use driver::session::Session;
+use driver::config;
use lib::llvm::llvm;
use lib::llvm::ModuleRef;
use lib;
use back::link::{OutputTypeExe, OutputTypeLlvmAssembly};
use back::link::{OutputTypeObject};
use driver::driver::{CrateTranslation, OutputFilenames};
- use driver::session::{NoDebugInfo, Session};
- use driver::session;
+ use driver::config::NoDebugInfo;
+ use driver::session::Session;
+ use driver::config;
use lib::llvm::llvm;
use lib::llvm::{ModuleRef, TargetMachineRef, PassManagerRef};
use lib;
}
let opt_level = match sess.opts.optimize {
- session::No => lib::llvm::CodeGenLevelNone,
- session::Less => lib::llvm::CodeGenLevelLess,
- session::Default => lib::llvm::CodeGenLevelDefault,
- session::Aggressive => lib::llvm::CodeGenLevelAggressive,
+ config::No => lib::llvm::CodeGenLevelNone,
+ config::Less => lib::llvm::CodeGenLevelLess,
+ config::Default => lib::llvm::CodeGenLevelDefault,
+ config::Aggressive => lib::llvm::CodeGenLevelAggressive,
};
let use_softfp = sess.opts.cg.soft_float;
// emitting an rlib. Whenever an rlib is created, the bytecode is
// inserted into the archive in order to allow LTO against it.
if sess.opts.cg.save_temps ||
- (sess.crate_types.borrow().contains(&session::CrateTypeRlib) &&
+ (sess.crate_types.borrow().contains(&config::CrateTypeRlib) &&
sess.opts.output_types.contains(&OutputTypeExe)) {
output.temp_path(OutputTypeBitcode).with_c_str(|buf| {
llvm::LLVMWriteBitcodeToFile(llmod, buf);
// Copy what clang does by turning on loop vectorization at O2 and
// slp vectorization at O3
let vectorize_loop = !sess.opts.cg.no_vectorize_loops &&
- (sess.opts.optimize == session::Default ||
- sess.opts.optimize == session::Aggressive);
+ (sess.opts.optimize == config::Default ||
+ sess.opts.optimize == config::Aggressive);
let vectorize_slp = !sess.opts.cg.no_vectorize_slp &&
- sess.opts.optimize == session::Aggressive;
+ sess.opts.optimize == config::Aggressive;
let mut llvm_c_strs = Vec::new();
let mut llvm_args = Vec::new();
}
}
-pub fn filename_for_input(sess: &Session, crate_type: session::CrateType,
+pub fn filename_for_input(sess: &Session, crate_type: config::CrateType,
id: &CrateId, out_filename: &Path) -> Path {
let libname = output_lib_filename(id);
match crate_type {
- session::CrateTypeRlib => {
+ config::CrateTypeRlib => {
out_filename.with_filename(format!("lib{}.rlib", libname))
}
- session::CrateTypeDylib => {
+ config::CrateTypeDylib => {
let (prefix, suffix) = match sess.targ_cfg.os {
abi::OsWin32 => (loader::WIN32_DLL_PREFIX, loader::WIN32_DLL_SUFFIX),
abi::OsMacos => (loader::MACOS_DLL_PREFIX, loader::MACOS_DLL_SUFFIX),
};
out_filename.with_filename(format!("{}{}{}", prefix, libname, suffix))
}
- session::CrateTypeStaticlib => {
+ config::CrateTypeStaticlib => {
out_filename.with_filename(format!("lib{}.a", libname))
}
- session::CrateTypeExecutable => out_filename.clone(),
+ config::CrateTypeExecutable => out_filename.clone(),
}
}
fn link_binary_output(sess: &Session,
trans: &CrateTranslation,
- crate_type: session::CrateType,
+ crate_type: config::CrateType,
outputs: &OutputFilenames,
id: &CrateId) -> Path {
let obj_filename = outputs.temp_path(OutputTypeObject);
}
match crate_type {
- session::CrateTypeRlib => {
+ config::CrateTypeRlib => {
link_rlib(sess, Some(trans), &obj_filename, &out_filename);
}
- session::CrateTypeStaticlib => {
+ config::CrateTypeStaticlib => {
link_staticlib(sess, &obj_filename, &out_filename);
}
- session::CrateTypeExecutable => {
+ config::CrateTypeExecutable => {
link_natively(sess, trans, false, &obj_filename, &out_filename);
}
- session::CrateTypeDylib => {
+ config::CrateTypeDylib => {
link_natively(sess, trans, true, &obj_filename, &out_filename);
}
}
let mut cc_args = sess.targ_cfg.target_strs.cc_args.clone();
cc_args.push_all_move(link_args(sess, dylib, tmpdir.path(), trans,
obj_filename, out_filename));
- if (sess.opts.debugging_opts & session::PRINT_LINK_ARGS) != 0 {
+ if (sess.opts.debugging_opts & config::PRINT_LINK_ARGS) != 0 {
println!("{} link args: '{}'", cc_prog, cc_args.connect("' '"));
}
// GNU-style linkers support optimization with -O. GNU ld doesn't need a
// numeric argument, but other linkers do.
- if sess.opts.optimize == session::Default ||
- sess.opts.optimize == session::Aggressive {
+ if sess.opts.optimize == config::Default ||
+ sess.opts.optimize == config::Aggressive {
args.push("-Wl,-O1".to_owned());
}
} else if sess.targ_cfg.os == abi::OsMacos {
// involves just passing the right -l flag.
let data = if dylib {
- trans.crate_formats.get(&session::CrateTypeDylib)
+ trans.crate_formats.get(&config::CrateTypeDylib)
} else {
- trans.crate_formats.get(&session::CrateTypeExecutable)
+ trans.crate_formats.get(&config::CrateTypeExecutable)
};
// Invoke get_used_crates to ensure that we get a topological sorting of
}
// Converts a library file-stem into a cc -l argument
- fn unlib(config: &session::Config, stem: &str) -> ~str {
+ fn unlib(config: &config::Config, stem: &str) -> ~str {
if stem.starts_with("lib") && config.os != abi::OsWin32 {
stem.slice(3, stem.len()).to_owned()
} else {
use back::archive::ArchiveRO;
use back::link;
use driver::session;
+use driver::config;
use lib::llvm::{ModuleRef, TargetMachineRef, llvm, True, False};
use metadata::cstore;
use util::common::time;
// Make sure we actually can run LTO
for crate_type in sess.crate_types.borrow().iter() {
match *crate_type {
- session::CrateTypeExecutable | session::CrateTypeStaticlib => {}
+ config::CrateTypeExecutable | config::CrateTypeStaticlib => {}
_ => {
sess.fatal("lto can only be run for executables and \
static library outputs");
// except according to those terms.
use back::target_strs;
-use driver::session::sess_os_to_meta_os;
+use driver::config::cfg_os_to_meta_os;
use metadata::loader::meta_section_name;
use syntax::abi;
return target_strs::t {
module_asm: "".to_owned(),
- meta_sect_name: meta_section_name(sess_os_to_meta_os(target_os)).to_owned(),
+ meta_sect_name: meta_section_name(cfg_os_to_meta_os(target_os)).to_owned(),
data_layout: match target_os {
abi::OsMacos => {
use back::target_strs;
-use driver::session::sess_os_to_meta_os;
+use driver::config::cfg_os_to_meta_os;
use metadata::loader::meta_section_name;
use syntax::abi;
return target_strs::t {
module_asm: "".to_owned(),
- meta_sect_name: meta_section_name(sess_os_to_meta_os(target_os)).to_owned(),
+ meta_sect_name: meta_section_name(cfg_os_to_meta_os(target_os)).to_owned(),
data_layout: match target_os {
abi::OsMacos => {
use back::target_strs;
-use driver::session::sess_os_to_meta_os;
+use driver::config::cfg_os_to_meta_os;
use metadata::loader::meta_section_name;
use syntax::abi;
return target_strs::t {
module_asm: "".to_owned(),
- meta_sect_name: meta_section_name(sess_os_to_meta_os(target_os)).to_owned(),
+ meta_sect_name: meta_section_name(cfg_os_to_meta_os(target_os)).to_owned(),
data_layout: match target_os {
abi::OsMacos => {
--- /dev/null
+// Copyright 2014 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.
+
+//! Contains infrastructure for configuring the compiler, including parsing
+//! command line options.
+
+use driver::early_error;
+use driver::driver;
+use driver::session::Session;
+
+use back;
+use back::link;
+use back::target_strs;
+use back::{arm, x86, x86_64, mips};
+use metadata;
+use middle::lint;
+
+use syntax::abi;
+use syntax::ast;
+use syntax::ast::{IntTy, UintTy};
+use syntax::attr;
+use syntax::attr::AttrMetaMethods;
+use syntax::parse;
+use syntax::parse::token::InternedString;
+
+use collections::HashSet;
+use getopts::{optopt, optmulti, optflag, optflagopt};
+use getopts;
+use lib::llvm::llvm;
+use std::cell::{RefCell};
+
+
+pub struct Config {
+ pub os: abi::Os,
+ pub arch: abi::Architecture,
+ pub target_strs: target_strs::t,
+ pub int_type: IntTy,
+ pub uint_type: UintTy,
+}
+
+#[deriving(Clone, Eq)]
+pub enum OptLevel {
+ No, // -O0
+ Less, // -O1
+ Default, // -O2
+ Aggressive // -O3
+}
+
+#[deriving(Clone, Eq)]
+pub enum DebugInfoLevel {
+ NoDebugInfo,
+ LimitedDebugInfo,
+ FullDebugInfo,
+}
+
+#[deriving(Clone)]
+pub struct Options {
+ // The crate config requested for the session, which may be combined
+ // with additional crate configurations during the compile process
+ pub crate_types: Vec<CrateType>,
+
+ pub gc: bool,
+ pub optimize: OptLevel,
+ pub debuginfo: DebugInfoLevel,
+ pub lint_opts: Vec<(lint::Lint, lint::level)> ,
+ pub output_types: Vec<back::link::OutputType> ,
+ // This was mutable for rustpkg, which updates search paths based on the
+ // parsed code. It remains mutable in case its replacements wants to use
+ // this.
+ pub addl_lib_search_paths: RefCell<HashSet<Path>>,
+ pub maybe_sysroot: Option<Path>,
+ pub target_triple: ~str,
+ // User-specified cfg meta items. The compiler itself will add additional
+ // items to the crate config, and during parsing the entire crate config
+ // will be added to the crate AST node. This should not be used for
+ // anything except building the full crate config prior to parsing.
+ pub cfg: ast::CrateConfig,
+ pub test: bool,
+ pub parse_only: bool,
+ pub no_trans: bool,
+ pub no_analysis: bool,
+ pub debugging_opts: u64,
+ /// Whether to write dependency files. It's (enabled, optional filename).
+ pub write_dependency_info: (bool, Option<Path>),
+ /// Crate id-related things to maybe print. It's (crate_id, crate_name, crate_file_name).
+ pub print_metas: (bool, bool, bool),
+ pub cg: CodegenOptions,
+}
+
+/// Some reasonable defaults
+pub fn basic_options() -> Options {
+ Options {
+ crate_types: Vec::new(),
+ gc: false,
+ optimize: No,
+ debuginfo: NoDebugInfo,
+ lint_opts: Vec::new(),
+ output_types: Vec::new(),
+ addl_lib_search_paths: RefCell::new(HashSet::new()),
+ maybe_sysroot: None,
+ target_triple: driver::host_triple().to_owned(),
+ cfg: Vec::new(),
+ test: false,
+ parse_only: false,
+ no_trans: false,
+ no_analysis: false,
+ debugging_opts: 0,
+ write_dependency_info: (false, None),
+ print_metas: (false, false, false),
+ cg: basic_codegen_options(),
+ }
+}
+
+// The type of entry function, so
+// users can have their own entry
+// functions that don't start a
+// scheduler
+#[deriving(Eq)]
+pub enum EntryFnType {
+ EntryMain,
+ EntryStart,
+ EntryNone,
+}
+
+#[deriving(Eq, Ord, Clone, TotalOrd, TotalEq, Hash)]
+pub enum CrateType {
+ CrateTypeExecutable,
+ CrateTypeDylib,
+ CrateTypeRlib,
+ CrateTypeStaticlib,
+}
+
+macro_rules! debugging_opts(
+ ([ $opt:ident ] $cnt:expr ) => (
+ pub static $opt: u64 = 1 << $cnt;
+ );
+ ([ $opt:ident, $($rest:ident),* ] $cnt:expr ) => (
+ pub static $opt: u64 = 1 << $cnt;
+ debugging_opts!([ $($rest),* ] $cnt + 1)
+ )
+)
+
+debugging_opts!(
+ [
+ VERBOSE,
+ TIME_PASSES,
+ COUNT_LLVM_INSNS,
+ TIME_LLVM_PASSES,
+ TRANS_STATS,
+ ASM_COMMENTS,
+ NO_VERIFY,
+ BORROWCK_STATS,
+ NO_LANDING_PADS,
+ DEBUG_LLVM,
+ SHOW_SPAN,
+ COUNT_TYPE_SIZES,
+ META_STATS,
+ NO_OPT,
+ GC,
+ PRINT_LINK_ARGS,
+ PRINT_LLVM_PASSES,
+ LTO,
+ AST_JSON,
+ AST_JSON_NOEXPAND,
+ LS
+ ]
+ 0
+)
+
+pub fn debugging_opts_map() -> Vec<(&'static str, &'static str, u64)> {
+ vec!(("verbose", "in general, enable more debug printouts", VERBOSE),
+ ("time-passes", "measure time of each rustc pass", TIME_PASSES),
+ ("count-llvm-insns", "count where LLVM \
+ instrs originate", COUNT_LLVM_INSNS),
+ ("time-llvm-passes", "measure time of each LLVM pass",
+ TIME_LLVM_PASSES),
+ ("trans-stats", "gather trans statistics", TRANS_STATS),
+ ("asm-comments", "generate comments into the assembly (may change behavior)",
+ ASM_COMMENTS),
+ ("no-verify", "skip LLVM verification", NO_VERIFY),
+ ("borrowck-stats", "gather borrowck statistics", BORROWCK_STATS),
+ ("no-landing-pads", "omit landing pads for unwinding",
+ NO_LANDING_PADS),
+ ("debug-llvm", "enable debug output from LLVM", DEBUG_LLVM),
+ ("show-span", "show spans for compiler debugging", SHOW_SPAN),
+ ("count-type-sizes", "count the sizes of aggregate types",
+ COUNT_TYPE_SIZES),
+ ("meta-stats", "gather metadata statistics", META_STATS),
+ ("no-opt", "do not optimize, even if -O is passed", NO_OPT),
+ ("print-link-args", "Print the arguments passed to the linker",
+ PRINT_LINK_ARGS),
+ ("gc", "Garbage collect shared data (experimental)", GC),
+ ("print-llvm-passes",
+ "Prints the llvm optimization passes being run",
+ PRINT_LLVM_PASSES),
+ ("lto", "Perform LLVM link-time optimizations", LTO),
+ ("ast-json", "Print the AST as JSON and halt", AST_JSON),
+ ("ast-json-noexpand", "Print the pre-expansion AST as JSON and halt", AST_JSON_NOEXPAND),
+ ("ls", "List the symbols defined by a library crate", LS))
+}
+
+/// Declare a macro that will define all CodegenOptions fields and parsers all
+/// at once. The goal of this macro is to define an interface that can be
+/// programmatically used by the option parser in order to initialize the struct
+/// without hardcoding field names all over the place.
+///
+/// The goal is to invoke this macro once with the correct fields, and then this
+/// macro generates all necessary code. The main gotcha of this macro is the
+/// cgsetters module which is a bunch of generated code to parse an option into
+/// its respective field in the struct. There are a few hand-written parsers for
+/// parsing specific types of values in this module.
+macro_rules! cgoptions(
+ ($($opt:ident : $t:ty = ($init:expr, $parse:ident, $desc:expr)),* ,) =>
+(
+ #[deriving(Clone)]
+ pub struct CodegenOptions { $(pub $opt: $t),* }
+
+ pub fn basic_codegen_options() -> CodegenOptions {
+ CodegenOptions { $($opt: $init),* }
+ }
+
+ pub type CodegenSetter = fn(&mut CodegenOptions, v: Option<&str>) -> bool;
+ pub static CG_OPTIONS: &'static [(&'static str, CodegenSetter,
+ &'static str)] =
+ &[ $( (stringify!($opt), cgsetters::$opt, $desc) ),* ];
+
+ mod cgsetters {
+ use super::CodegenOptions;
+
+ $(
+ pub fn $opt(cg: &mut CodegenOptions, v: Option<&str>) -> bool {
+ $parse(&mut cg.$opt, v)
+ }
+ )*
+
+ fn parse_bool(slot: &mut bool, v: Option<&str>) -> bool {
+ match v {
+ Some(..) => false,
+ None => { *slot = true; true }
+ }
+ }
+
+ fn parse_opt_string(slot: &mut Option<~str>, v: Option<&str>) -> bool {
+ match v {
+ Some(s) => { *slot = Some(s.to_owned()); true },
+ None => false,
+ }
+ }
+
+ fn parse_string(slot: &mut ~str, v: Option<&str>) -> bool {
+ match v {
+ Some(s) => { *slot = s.to_owned(); true },
+ None => false,
+ }
+ }
+
+ fn parse_list(slot: &mut Vec<~str>, v: Option<&str>)
+ -> bool {
+ match v {
+ Some(s) => {
+ for s in s.words() {
+ slot.push(s.to_owned());
+ }
+ true
+ },
+ None => false,
+ }
+ }
+
+ }
+) )
+
+cgoptions!(
+ ar: Option<~str> = (None, parse_opt_string,
+ "tool to assemble archives with"),
+ linker: Option<~str> = (None, parse_opt_string,
+ "system linker to link outputs with"),
+ link_args: Vec<~str> = (Vec::new(), parse_list,
+ "extra arguments to pass to the linker (space separated)"),
+ target_cpu: ~str = ("generic".to_owned(), parse_string,
+ "select target processor (llc -mcpu=help for details)"),
+ target_feature: ~str = ("".to_owned(), parse_string,
+ "target specific attributes (llc -mattr=help for details)"),
+ passes: Vec<~str> = (Vec::new(), parse_list,
+ "a list of extra LLVM passes to run (space separated)"),
+ llvm_args: Vec<~str> = (Vec::new(), parse_list,
+ "a list of arguments to pass to llvm (space separated)"),
+ save_temps: bool = (false, parse_bool,
+ "save all temporary output files during compilation"),
+ android_cross_path: Option<~str> = (None, parse_opt_string,
+ "the path to the Android NDK"),
+ no_rpath: bool = (false, parse_bool,
+ "disables setting the rpath in libs/exes"),
+ no_prepopulate_passes: bool = (false, parse_bool,
+ "don't pre-populate the pass manager with a list of passes"),
+ no_vectorize_loops: bool = (false, parse_bool,
+ "don't run the loop vectorization optimization passes"),
+ no_vectorize_slp: bool = (false, parse_bool,
+ "don't run LLVM's SLP vectorization pass"),
+ soft_float: bool = (false, parse_bool,
+ "generate software floating point library calls"),
+ prefer_dynamic: bool = (false, parse_bool,
+ "prefer dynamic linking to static linking"),
+ no_integrated_as: bool = (false, parse_bool,
+ "use an external assembler rather than LLVM's integrated one"),
+ relocation_model: ~str = ("pic".to_owned(), parse_string,
+ "choose the relocation model to use (llc -relocation-model for details)"),
+)
+
+pub fn build_codegen_options(matches: &getopts::Matches) -> CodegenOptions
+{
+ let mut cg = basic_codegen_options();
+ for option in matches.opt_strs("C").move_iter() {
+ let mut iter = option.splitn('=', 1);
+ let key = iter.next().unwrap();
+ let value = iter.next();
+ let option_to_lookup = key.replace("-", "_");
+ let mut found = false;
+ for &(candidate, setter, _) in CG_OPTIONS.iter() {
+ if option_to_lookup.as_slice() != candidate { continue }
+ if !setter(&mut cg, value) {
+ match value {
+ Some(..) => early_error(format!("codegen option `{}` takes \
+ no value", key)),
+ None => early_error(format!("codegen option `{0}` requires \
+ a value (-C {0}=<value>)",
+ key))
+ }
+ }
+ found = true;
+ break;
+ }
+ if !found {
+ early_error(format!("unknown codegen option: `{}`", key));
+ }
+ }
+ return cg;
+}
+
+pub fn default_lib_output() -> CrateType {
+ CrateTypeRlib
+}
+
+pub fn cfg_os_to_meta_os(os: abi::Os) -> metadata::loader::Os {
+ use metadata::loader;
+
+ match os {
+ abi::OsWin32 => loader::OsWin32,
+ abi::OsLinux => loader::OsLinux,
+ abi::OsAndroid => loader::OsAndroid,
+ abi::OsMacos => loader::OsMacos,
+ abi::OsFreebsd => loader::OsFreebsd
+ }
+}
+
+pub fn default_configuration(sess: &Session) -> ast::CrateConfig {
+ let tos = match sess.targ_cfg.os {
+ abi::OsWin32 => InternedString::new("win32"),
+ abi::OsMacos => InternedString::new("macos"),
+ abi::OsLinux => InternedString::new("linux"),
+ abi::OsAndroid => InternedString::new("android"),
+ abi::OsFreebsd => InternedString::new("freebsd"),
+ };
+
+ // ARM is bi-endian, however using NDK seems to default
+ // to little-endian unless a flag is provided.
+ let (end,arch,wordsz) = match sess.targ_cfg.arch {
+ abi::X86 => ("little", "x86", "32"),
+ abi::X86_64 => ("little", "x86_64", "64"),
+ abi::Arm => ("little", "arm", "32"),
+ abi::Mips => ("big", "mips", "32")
+ };
+
+ let fam = match sess.targ_cfg.os {
+ abi::OsWin32 => InternedString::new("windows"),
+ _ => InternedString::new("unix")
+ };
+
+ let mk = attr::mk_name_value_item_str;
+ return vec!(// Target bindings.
+ attr::mk_word_item(fam.clone()),
+ mk(InternedString::new("target_os"), tos),
+ mk(InternedString::new("target_family"), fam),
+ mk(InternedString::new("target_arch"), InternedString::new(arch)),
+ mk(InternedString::new("target_endian"), InternedString::new(end)),
+ mk(InternedString::new("target_word_size"),
+ InternedString::new(wordsz))
+ );
+}
+
+pub fn append_configuration(cfg: &mut ast::CrateConfig,
+ name: InternedString) {
+ if !cfg.iter().any(|mi| mi.name() == name) {
+ cfg.push(attr::mk_word_item(name))
+ }
+}
+
+pub fn build_configuration(sess: &Session) -> ast::CrateConfig {
+ // Combine the configuration requested by the session (command line) with
+ // some default and generated configuration items
+ let default_cfg = default_configuration(sess);
+ let mut user_cfg = sess.opts.cfg.clone();
+ // If the user wants a test runner, then add the test cfg
+ if sess.opts.test {
+ append_configuration(&mut user_cfg, InternedString::new("test"))
+ }
+ // If the user requested GC, then add the GC cfg
+ append_configuration(&mut user_cfg, if sess.opts.gc {
+ InternedString::new("gc")
+ } else {
+ InternedString::new("nogc")
+ });
+ user_cfg.move_iter().collect::<Vec<_>>().append(default_cfg.as_slice())
+}
+
+pub fn get_os(triple: &str) -> Option<abi::Os> {
+ for &(name, os) in os_names.iter() {
+ if triple.contains(name) { return Some(os) }
+ }
+ None
+}
+static os_names : &'static [(&'static str, abi::Os)] = &'static [
+ ("mingw32", abi::OsWin32),
+ ("win32", abi::OsWin32),
+ ("darwin", abi::OsMacos),
+ ("android", abi::OsAndroid),
+ ("linux", abi::OsLinux),
+ ("freebsd", abi::OsFreebsd)];
+
+pub fn get_arch(triple: &str) -> Option<abi::Architecture> {
+ for &(arch, abi) in architecture_abis.iter() {
+ if triple.contains(arch) { return Some(abi) }
+ }
+ None
+}
+static architecture_abis : &'static [(&'static str, abi::Architecture)] = &'static [
+ ("i386", abi::X86),
+ ("i486", abi::X86),
+ ("i586", abi::X86),
+ ("i686", abi::X86),
+ ("i786", abi::X86),
+
+ ("x86_64", abi::X86_64),
+
+ ("arm", abi::Arm),
+ ("xscale", abi::Arm),
+ ("thumb", abi::Arm),
+
+ ("mips", abi::Mips)];
+
+pub fn build_target_config(sopts: &Options) -> Config {
+ let os = match get_os(sopts.target_triple) {
+ Some(os) => os,
+ None => early_error("unknown operating system")
+ };
+ let arch = match get_arch(sopts.target_triple) {
+ Some(arch) => arch,
+ None => early_error("unknown architecture: " + sopts.target_triple)
+ };
+ let (int_type, uint_type) = match arch {
+ abi::X86 => (ast::TyI32, ast::TyU32),
+ abi::X86_64 => (ast::TyI64, ast::TyU64),
+ abi::Arm => (ast::TyI32, ast::TyU32),
+ abi::Mips => (ast::TyI32, ast::TyU32)
+ };
+ let target_triple = sopts.target_triple.clone();
+ let target_strs = match arch {
+ abi::X86 => x86::get_target_strs(target_triple, os),
+ abi::X86_64 => x86_64::get_target_strs(target_triple, os),
+ abi::Arm => arm::get_target_strs(target_triple, os),
+ abi::Mips => mips::get_target_strs(target_triple, os)
+ };
+ Config {
+ os: os,
+ arch: arch,
+ target_strs: target_strs,
+ int_type: int_type,
+ uint_type: uint_type,
+ }
+}
+
+// rustc command line options
+pub fn optgroups() -> Vec<getopts::OptGroup> {
+ vec!(
+ optflag("h", "help", "Display this message"),
+ optmulti("", "cfg", "Configure the compilation environment", "SPEC"),
+ optmulti("L", "", "Add a directory to the library search path", "PATH"),
+ optmulti("", "crate-type", "Comma separated list of types of crates
+ for the compiler to emit",
+ "[bin|lib|rlib|dylib|staticlib]"),
+ optmulti("", "emit", "Comma separated list of types of output for the compiler to emit",
+ "[asm|bc|ir|obj|link]"),
+ optflag("", "crate-id", "Output the crate id and exit"),
+ optflag("", "crate-name", "Output the crate name and exit"),
+ optflag("", "crate-file-name", "Output the file(s) that would be written if compilation \
+ continued and exit"),
+ optflag("g", "", "Equivalent to --debuginfo=2"),
+ optopt("", "debuginfo", "Emit DWARF debug info to the objects created:
+ 0 = no debug info,
+ 1 = line-tables only (for stacktraces and breakpoints),
+ 2 = full debug info with variable and type information (same as -g)", "LEVEL"),
+ optflag("", "no-trans", "Run all passes except translation; no output"),
+ optflag("", "no-analysis",
+ "Parse and expand the source, but run no analysis and produce no output"),
+ optflag("O", "", "Equivalent to --opt-level=2"),
+ optopt("o", "", "Write output to <filename>", "FILENAME"),
+ optopt("", "opt-level", "Optimize with possible levels 0-3", "LEVEL"),
+ optopt( "", "out-dir", "Write output to compiler-chosen filename in <dir>", "DIR"),
+ optflag("", "parse-only", "Parse only; do not compile, assemble, or link"),
+ optflagopt("", "pretty",
+ "Pretty-print the input instead of compiling;
+ valid types are: normal (un-annotated source),
+ expanded (crates expanded),
+ typed (crates expanded, with type annotations),
+ or identified (fully parenthesized,
+ AST nodes and blocks with IDs)", "TYPE"),
+ optflagopt("", "dep-info",
+ "Output dependency info to <filename> after compiling, \
+ in a format suitable for use by Makefiles", "FILENAME"),
+ optopt("", "sysroot", "Override the system root", "PATH"),
+ optflag("", "test", "Build a test harness"),
+ optopt("", "target", "Target triple cpu-manufacturer-kernel[-os]
+ to compile for (see chapter 3.4 of http://www.sourceware.org/autobook/
+ for details)", "TRIPLE"),
+ optmulti("W", "warn", "Set lint warnings", "OPT"),
+ optmulti("A", "allow", "Set lint allowed", "OPT"),
+ optmulti("D", "deny", "Set lint denied", "OPT"),
+ optmulti("F", "forbid", "Set lint forbidden", "OPT"),
+ optmulti("C", "codegen", "Set a codegen option", "OPT[=VALUE]"),
+ optmulti("Z", "", "Set internal debugging options", "FLAG"),
+ optflag( "v", "version", "Print version info and exit")
+ )
+}
+
+
+// Convert strings provided as --cfg [cfgspec] into a crate_cfg
+fn parse_cfgspecs(cfgspecs: Vec<~str> ) -> ast::CrateConfig {
+ cfgspecs.move_iter().map(|s| {
+ parse::parse_meta_from_source_str("cfgspec".to_strbuf(),
+ s.to_strbuf(),
+ Vec::new(),
+ &parse::new_parse_sess())
+ }).collect::<ast::CrateConfig>()
+}
+
+pub fn build_session_options(matches: &getopts::Matches) -> Options {
+ let mut crate_types: Vec<CrateType> = Vec::new();
+ let unparsed_crate_types = matches.opt_strs("crate-type");
+ for unparsed_crate_type in unparsed_crate_types.iter() {
+ for part in unparsed_crate_type.split(',') {
+ let new_part = match part {
+ "lib" => default_lib_output(),
+ "rlib" => CrateTypeRlib,
+ "staticlib" => CrateTypeStaticlib,
+ "dylib" => CrateTypeDylib,
+ "bin" => CrateTypeExecutable,
+ _ => early_error(format!("unknown crate type: `{}`", part))
+ };
+ crate_types.push(new_part)
+ }
+ }
+
+ let parse_only = matches.opt_present("parse-only");
+ let no_trans = matches.opt_present("no-trans");
+ let no_analysis = matches.opt_present("no-analysis");
+
+ let lint_levels = [lint::allow, lint::warn,
+ lint::deny, lint::forbid];
+ let mut lint_opts = Vec::new();
+ let lint_dict = lint::get_lint_dict();
+ for level in lint_levels.iter() {
+ let level_name = lint::level_to_str(*level);
+
+ let level_short = level_name.slice_chars(0, 1);
+ let level_short = level_short.to_ascii().to_upper().into_str();
+ let flags = matches.opt_strs(level_short).move_iter().collect::<Vec<_>>().append(
+ matches.opt_strs(level_name).as_slice());
+ for lint_name in flags.iter() {
+ let lint_name = lint_name.replace("-", "_");
+ match lint_dict.find_equiv(&lint_name) {
+ None => {
+ early_error(format!("unknown {} flag: {}",
+ level_name, lint_name));
+ }
+ Some(lint) => {
+ lint_opts.push((lint.lint, *level));
+ }
+ }
+ }
+ }
+
+ let mut debugging_opts = 0;
+ let debug_flags = matches.opt_strs("Z");
+ let debug_map = debugging_opts_map();
+ for debug_flag in debug_flags.iter() {
+ let mut this_bit = 0;
+ for tuple in debug_map.iter() {
+ let (name, bit) = match *tuple { (ref a, _, b) => (a, b) };
+ if *name == *debug_flag { this_bit = bit; break; }
+ }
+ if this_bit == 0 {
+ early_error(format!("unknown debug flag: {}", *debug_flag))
+ }
+ debugging_opts |= this_bit;
+ }
+
+ if debugging_opts & DEBUG_LLVM != 0 {
+ unsafe { llvm::LLVMSetDebug(1); }
+ }
+
+ let mut output_types = Vec::new();
+ if !parse_only && !no_trans {
+ let unparsed_output_types = matches.opt_strs("emit");
+ for unparsed_output_type in unparsed_output_types.iter() {
+ for part in unparsed_output_type.split(',') {
+ let output_type = match part.as_slice() {
+ "asm" => link::OutputTypeAssembly,
+ "ir" => link::OutputTypeLlvmAssembly,
+ "bc" => link::OutputTypeBitcode,
+ "obj" => link::OutputTypeObject,
+ "link" => link::OutputTypeExe,
+ _ => early_error(format!("unknown emission type: `{}`", part))
+ };
+ output_types.push(output_type)
+ }
+ }
+ };
+ output_types.as_mut_slice().sort();
+ output_types.dedup();
+ if output_types.len() == 0 {
+ output_types.push(link::OutputTypeExe);
+ }
+
+ let sysroot_opt = matches.opt_str("sysroot").map(|m| Path::new(m));
+ let target = matches.opt_str("target").unwrap_or(driver::host_triple().to_owned());
+ let opt_level = {
+ if (debugging_opts & NO_OPT) != 0 {
+ No
+ } else if matches.opt_present("O") {
+ if matches.opt_present("opt-level") {
+ early_error("-O and --opt-level both provided");
+ }
+ Default
+ } else if matches.opt_present("opt-level") {
+ match matches.opt_str("opt-level").as_ref().map(|s| s.as_slice()) {
+ None |
+ Some("0") => No,
+ Some("1") => Less,
+ Some("2") => Default,
+ Some("3") => Aggressive,
+ Some(arg) => {
+ early_error(format!("optimization level needs to be between 0-3 \
+ (instead was `{}`)", arg));
+ }
+ }
+ } else {
+ No
+ }
+ };
+ let gc = debugging_opts & GC != 0;
+ let debuginfo = if matches.opt_present("g") {
+ if matches.opt_present("debuginfo") {
+ early_error("-g and --debuginfo both provided");
+ }
+ FullDebugInfo
+ } else if matches.opt_present("debuginfo") {
+ match matches.opt_str("debuginfo").as_ref().map(|s| s.as_slice()) {
+ Some("0") => NoDebugInfo,
+ Some("1") => LimitedDebugInfo,
+ None |
+ Some("2") => FullDebugInfo,
+ Some(arg) => {
+ early_error(format!("optimization level needs to be between 0-3 \
+ (instead was `{}`)", arg));
+ }
+ }
+ } else {
+ NoDebugInfo
+ };
+
+ let addl_lib_search_paths = matches.opt_strs("L").iter().map(|s| {
+ Path::new(s.as_slice())
+ }).collect();
+
+ let cfg = parse_cfgspecs(matches.opt_strs("cfg").move_iter().collect());
+ let test = matches.opt_present("test");
+ let write_dependency_info = (matches.opt_present("dep-info"),
+ matches.opt_str("dep-info").map(|p| Path::new(p)));
+
+ let print_metas = (matches.opt_present("crate-id"),
+ matches.opt_present("crate-name"),
+ matches.opt_present("crate-file-name"));
+ let cg = build_codegen_options(matches);
+
+ Options {
+ crate_types: crate_types,
+ gc: gc,
+ optimize: opt_level,
+ debuginfo: debuginfo,
+ lint_opts: lint_opts,
+ output_types: output_types,
+ addl_lib_search_paths: RefCell::new(addl_lib_search_paths),
+ maybe_sysroot: sysroot_opt,
+ target_triple: target,
+ cfg: cfg,
+ test: test,
+ parse_only: parse_only,
+ no_trans: no_trans,
+ no_analysis: no_analysis,
+ debugging_opts: debugging_opts,
+ write_dependency_info: write_dependency_info,
+ print_metas: print_metas,
+ cg: cg,
+ }
+}
+
+
+#[cfg(test)]
+mod test {
+
+ use driver::config::{build_configuration, optgroups, build_session_options};
+ use driver::session::build_session;
+
+ use getopts::getopts;
+ use syntax::attr;
+ use syntax::attr::AttrMetaMethods;
+
+ // When the user supplies --test we should implicitly supply --cfg test
+ #[test]
+ fn test_switch_implies_cfg_test() {
+ let matches =
+ &match getopts(["--test".to_owned()], optgroups().as_slice()) {
+ Ok(m) => m,
+ Err(f) => fail!("test_switch_implies_cfg_test: {}", f.to_err_msg())
+ };
+ let sessopts = build_session_options(matches);
+ let sess = build_session(sessopts, None);
+ let cfg = build_configuration(&sess);
+ assert!((attr::contains_name(cfg.as_slice(), "test")));
+ }
+
+ // When the user supplies --test and --cfg test, don't implicitly add
+ // another --cfg test
+ #[test]
+ fn test_switch_implies_cfg_test_unless_cfg_test() {
+ let matches =
+ &match getopts(["--test".to_owned(), "--cfg=test".to_owned()],
+ optgroups().as_slice()) {
+ Ok(m) => m,
+ Err(f) => {
+ fail!("test_switch_implies_cfg_test_unless_cfg_test: {}",
+ f.to_err_msg());
+ }
+ };
+ let sessopts = build_session_options(matches);
+ let sess = build_session(sessopts, None);
+ let cfg = build_configuration(&sess);
+ let mut test_items = cfg.iter().filter(|m| m.name().equiv(&("test")));
+ assert!(test_items.next().is_some());
+ assert!(test_items.next().is_none());
+ }
+}
use back::link;
-use back::{arm, x86, x86_64, mips};
-use driver::session::{Aggressive, CrateTypeExecutable, CrateType,
- FullDebugInfo, LimitedDebugInfo, NoDebugInfo};
-use driver::session::{Session, No, Less, Default};
-use driver::session;
+use driver::session::Session;
+use driver::config;
use front;
-use lib::llvm::llvm;
use lib::llvm::{ContextRef, ModuleRef};
use metadata::common::LinkMeta;
-use metadata::{creader, filesearch};
-use metadata::cstore::CStore;
+use metadata::creader;
use metadata::creader::Loader;
-use metadata;
use middle::{trans, freevars, kind, ty, typeck, lint, reachable};
use middle::dependency_format;
use middle;
use util::common::time;
use util::ppaux;
-use util::nodemap::{NodeMap, NodeSet};
+use util::nodemap::{NodeSet};
use serialize::{json, Encodable};
-use std::cell::{Cell, RefCell};
use std::io;
use std::io::fs;
use std::io::MemReader;
-use std::os;
-use getopts::{optopt, optmulti, optflag, optflagopt};
-use getopts;
use syntax::ast;
-use syntax::abi;
use syntax::attr;
use syntax::attr::{AttrMetaMethods};
-use syntax::codemap;
use syntax::crateid::CrateId;
-use syntax::diagnostic;
-use syntax::diagnostic::Emitter;
use syntax::ext::base::CrateLoader;
use syntax::parse;
-use syntax::parse::token::InternedString;
use syntax::parse::token;
use syntax::print::{pp, pprust};
use syntax;
-pub enum PpMode {
- PpmNormal,
- PpmExpanded,
- PpmTyped,
- PpmIdentified,
- PpmExpandedIdentified
+pub fn host_triple() -> &'static str {
+ // Get the host triple out of the build environment. This ensures that our
+ // idea of the host triple is the same as for the set of libraries we've
+ // actually built. We can't just take LLVM's host triple because they
+ // normalize all ix86 architectures to i386.
+ //
+ // Instead of grabbing the host triple (for the current host), we grab (at
+ // compile time) the target triple that this rustc is built with and
+ // calling that (at runtime) the host triple.
+ (option_env!("CFG_COMPILER_HOST_TRIPLE")).
+ expect("CFG_COMPILER_HOST_TRIPLE")
+}
+
+pub fn compile_input(sess: Session,
+ cfg: ast::CrateConfig,
+ input: &Input,
+ outdir: &Option<Path>,
+ output: &Option<Path>) {
+ // We need nested scopes here, because the intermediate results can keep
+ // large chunks of memory alive and we want to free them as soon as
+ // possible to keep the peak memory usage low
+ let (outputs, trans, sess) = {
+ let (outputs, expanded_crate, ast_map) = {
+ let krate = phase_1_parse_input(&sess, cfg, input);
+ if stop_after_phase_1(&sess) { return; }
+ let outputs = build_output_filenames(input,
+ outdir,
+ output,
+ krate.attrs.as_slice(),
+ &sess);
+ let loader = &mut Loader::new(&sess);
+ let id = link::find_crate_id(krate.attrs.as_slice(),
+ outputs.out_filestem);
+ let (expanded_crate, ast_map) = phase_2_configure_and_expand(&sess, loader,
+ krate, &id);
+ (outputs, expanded_crate, ast_map)
+ };
+ write_out_deps(&sess, input, &outputs, &expanded_crate);
+
+ if stop_after_phase_2(&sess) { return; }
+
+ let analysis = phase_3_run_analysis_passes(sess, &expanded_crate, ast_map);
+ if stop_after_phase_3(&analysis.ty_cx.sess) { return; }
+ let (tcx, trans) = phase_4_translate_to_llvm(expanded_crate,
+ analysis, &outputs);
+
+ // Discard interned strings as they are no longer required.
+ token::get_ident_interner().clear();
+
+ (outputs, trans, tcx.sess)
+ };
+ phase_5_run_llvm_passes(&sess, &trans, &outputs);
+ if stop_after_phase_5(&sess) { return; }
+ phase_6_link_output(&sess, &trans, &outputs);
}
/**
}
}
-pub fn default_configuration(sess: &Session) ->
- ast::CrateConfig {
- let tos = match sess.targ_cfg.os {
- abi::OsWin32 => InternedString::new("win32"),
- abi::OsMacos => InternedString::new("macos"),
- abi::OsLinux => InternedString::new("linux"),
- abi::OsAndroid => InternedString::new("android"),
- abi::OsFreebsd => InternedString::new("freebsd"),
- };
-
- // ARM is bi-endian, however using NDK seems to default
- // to little-endian unless a flag is provided.
- let (end,arch,wordsz) = match sess.targ_cfg.arch {
- abi::X86 => ("little", "x86", "32"),
- abi::X86_64 => ("little", "x86_64", "64"),
- abi::Arm => ("little", "arm", "32"),
- abi::Mips => ("big", "mips", "32")
- };
-
- let fam = match sess.targ_cfg.os {
- abi::OsWin32 => InternedString::new("windows"),
- _ => InternedString::new("unix")
- };
-
- let mk = attr::mk_name_value_item_str;
- return vec!(// Target bindings.
- attr::mk_word_item(fam.clone()),
- mk(InternedString::new("target_os"), tos),
- mk(InternedString::new("target_family"), fam),
- mk(InternedString::new("target_arch"), InternedString::new(arch)),
- mk(InternedString::new("target_endian"), InternedString::new(end)),
- mk(InternedString::new("target_word_size"),
- InternedString::new(wordsz))
- );
-}
-
-pub fn append_configuration(cfg: &mut ast::CrateConfig,
- name: InternedString) {
- if !cfg.iter().any(|mi| mi.name() == name) {
- cfg.push(attr::mk_word_item(name))
- }
-}
-
-pub fn build_configuration(sess: &Session) -> ast::CrateConfig {
- // Combine the configuration requested by the session (command line) with
- // some default and generated configuration items
- let default_cfg = default_configuration(sess);
- let mut user_cfg = sess.opts.cfg.clone();
- // If the user wants a test runner, then add the test cfg
- if sess.opts.test {
- append_configuration(&mut user_cfg, InternedString::new("test"))
- }
- // If the user requested GC, then add the GC cfg
- append_configuration(&mut user_cfg, if sess.opts.gc {
- InternedString::new("gc")
- } else {
- InternedString::new("nogc")
- });
- user_cfg.move_iter().collect::<Vec<_>>().append(default_cfg.as_slice())
-}
-
-// Convert strings provided as --cfg [cfgspec] into a crate_cfg
-fn parse_cfgspecs(cfgspecs: Vec<~str> )
- -> ast::CrateConfig {
- cfgspecs.move_iter().map(|s| {
- parse::parse_meta_from_source_str("cfgspec".to_strbuf(),
- s.to_strbuf(),
- Vec::new(),
- &parse::new_parse_sess())
- }).collect::<ast::CrateConfig>()
-}
-
pub enum Input {
/// Load source from file
FileInput(Path),
}
});
- if sess.opts.debugging_opts & session::AST_JSON_NOEXPAND != 0 {
+ if sess.opts.debugging_opts & config::AST_JSON_NOEXPAND != 0 {
let mut stdout = io::BufferedWriter::new(io::stdout());
let mut json = json::PrettyEncoder::new(&mut stdout);
// unwrapping so IoError isn't ignored
-> (ast::Crate, syntax::ast_map::Map) {
let time_passes = sess.time_passes();
- *sess.crate_types.borrow_mut() = session::collect_crate_types(sess, krate.attrs.as_slice());
+ *sess.crate_types.borrow_mut() = collect_crate_types(sess, krate.attrs.as_slice());
time(time_passes, "gated feature checking", (), |_|
front::feature_gate::check_crate(sess, &krate));
let (krate, map) = time(time_passes, "assinging node ids and indexing ast", krate, |krate|
front::assign_node_ids_and_map::assign_node_ids_and_map(sess, krate));
- if sess.opts.debugging_opts & session::AST_JSON != 0 {
+ if sess.opts.debugging_opts & config::AST_JSON != 0 {
let mut stdout = io::BufferedWriter::new(io::stdout());
let mut json = json::PrettyEncoder::new(&mut stdout);
// unwrapping so IoError isn't ignored
if sess.show_span() {
return true;
}
- return sess.opts.debugging_opts & session::AST_JSON_NOEXPAND != 0;
+ return sess.opts.debugging_opts & config::AST_JSON_NOEXPAND != 0;
}
pub fn stop_after_phase_2(sess: &Session) -> bool {
debug!("invoked with --no-analysis, returning early from compile_input");
return true;
}
- return sess.opts.debugging_opts & session::AST_JSON != 0;
+ return sess.opts.debugging_opts & config::AST_JSON != 0;
}
pub fn stop_after_phase_5(sess: &Session) -> bool {
}
}
-pub fn compile_input(sess: Session, cfg: ast::CrateConfig, input: &Input,
- outdir: &Option<Path>, output: &Option<Path>) {
- // We need nested scopes here, because the intermediate results can keep
- // large chunks of memory alive and we want to free them as soon as
- // possible to keep the peak memory usage low
- let (outputs, trans, sess) = {
- let (outputs, expanded_crate, ast_map) = {
- let krate = phase_1_parse_input(&sess, cfg, input);
- if stop_after_phase_1(&sess) { return; }
- let outputs = build_output_filenames(input,
- outdir,
- output,
- krate.attrs.as_slice(),
- &sess);
- let loader = &mut Loader::new(&sess);
- let id = link::find_crate_id(krate.attrs.as_slice(),
- outputs.out_filestem);
- let (expanded_crate, ast_map) = phase_2_configure_and_expand(&sess, loader,
- krate, &id);
- (outputs, expanded_crate, ast_map)
- };
- write_out_deps(&sess, input, &outputs, &expanded_crate);
-
- if stop_after_phase_2(&sess) { return; }
-
- let analysis = phase_3_run_analysis_passes(sess, &expanded_crate, ast_map);
- if stop_after_phase_3(&analysis.ty_cx.sess) { return; }
- let (tcx, trans) = phase_4_translate_to_llvm(expanded_crate,
- analysis, &outputs);
-
- // Discard interned strings as they are no longer required.
- token::get_ident_interner().clear();
-
- (outputs, trans, tcx.sess)
- };
- phase_5_run_llvm_passes(&sess, &trans, &outputs);
- if stop_after_phase_5(&sess) { return; }
- phase_6_link_output(&sess, &trans, &outputs);
-}
-
struct IdentifiedAnnotation;
impl pprust::PpAnn for IdentifiedAnnotation {
pub fn pretty_print_input(sess: Session,
cfg: ast::CrateConfig,
input: &Input,
- ppm: PpMode,
+ ppm: ::driver::PpMode,
ofile: Option<Path>) {
let krate = phase_1_parse_input(&sess, cfg, input);
let id = link::find_crate_id(krate.attrs.as_slice(), input.filestem());
}
-pub fn get_os(triple: &str) -> Option<abi::Os> {
- for &(name, os) in os_names.iter() {
- if triple.contains(name) { return Some(os) }
+pub fn collect_crate_types(session: &Session,
+ attrs: &[ast::Attribute]) -> Vec<config::CrateType> {
+ // If we're generating a test executable, then ignore all other output
+ // styles at all other locations
+ if session.opts.test {
+ return vec!(config::CrateTypeExecutable)
}
- None
-}
-static os_names : &'static [(&'static str, abi::Os)] = &'static [
- ("mingw32", abi::OsWin32),
- ("win32", abi::OsWin32),
- ("darwin", abi::OsMacos),
- ("android", abi::OsAndroid),
- ("linux", abi::OsLinux),
- ("freebsd", abi::OsFreebsd)];
-
-pub fn get_arch(triple: &str) -> Option<abi::Architecture> {
- for &(arch, abi) in architecture_abis.iter() {
- if triple.contains(arch) { return Some(abi) }
- }
- None
-}
-static architecture_abis : &'static [(&'static str, abi::Architecture)] = &'static [
- ("i386", abi::X86),
- ("i486", abi::X86),
- ("i586", abi::X86),
- ("i686", abi::X86),
- ("i786", abi::X86),
-
- ("x86_64", abi::X86_64),
-
- ("arm", abi::Arm),
- ("xscale", abi::Arm),
- ("thumb", abi::Arm),
-
- ("mips", abi::Mips)];
-pub fn build_target_config(sopts: &session::Options) -> session::Config {
- let os = match get_os(sopts.target_triple) {
- Some(os) => os,
- None => early_error("unknown operating system")
- };
- let arch = match get_arch(sopts.target_triple) {
- Some(arch) => arch,
- None => early_error("unknown architecture: " + sopts.target_triple)
- };
- let (int_type, uint_type) = match arch {
- abi::X86 => (ast::TyI32, ast::TyU32),
- abi::X86_64 => (ast::TyI64, ast::TyU64),
- abi::Arm => (ast::TyI32, ast::TyU32),
- abi::Mips => (ast::TyI32, ast::TyU32)
- };
- let target_triple = sopts.target_triple.clone();
- let target_strs = match arch {
- abi::X86 => x86::get_target_strs(target_triple, os),
- abi::X86_64 => x86_64::get_target_strs(target_triple, os),
- abi::Arm => arm::get_target_strs(target_triple, os),
- abi::Mips => mips::get_target_strs(target_triple, os)
- };
- session::Config {
- os: os,
- arch: arch,
- target_strs: target_strs,
- int_type: int_type,
- uint_type: uint_type,
- }
-}
-
-pub fn host_triple() -> &'static str {
- // Get the host triple out of the build environment. This ensures that our
- // idea of the host triple is the same as for the set of libraries we've
- // actually built. We can't just take LLVM's host triple because they
- // normalize all ix86 architectures to i386.
- //
- // Instead of grabbing the host triple (for the current host), we grab (at
- // compile time) the target triple that this rustc is built with and
- // calling that (at runtime) the host triple.
- (option_env!("CFG_COMPILER_HOST_TRIPLE")).
- expect("CFG_COMPILER_HOST_TRIPLE")
-}
-
-pub fn build_session_options(matches: &getopts::Matches) -> session::Options {
- let mut crate_types: Vec<CrateType> = Vec::new();
- let unparsed_crate_types = matches.opt_strs("crate-type");
- for unparsed_crate_type in unparsed_crate_types.iter() {
- for part in unparsed_crate_type.split(',') {
- let new_part = match part {
- "lib" => session::default_lib_output(),
- "rlib" => session::CrateTypeRlib,
- "staticlib" => session::CrateTypeStaticlib,
- "dylib" => session::CrateTypeDylib,
- "bin" => session::CrateTypeExecutable,
- _ => early_error(format!("unknown crate type: `{}`", part))
- };
- crate_types.push(new_part)
- }
- }
-
- let parse_only = matches.opt_present("parse-only");
- let no_trans = matches.opt_present("no-trans");
- let no_analysis = matches.opt_present("no-analysis");
-
- let lint_levels = [lint::allow, lint::warn,
- lint::deny, lint::forbid];
- let mut lint_opts = Vec::new();
- let lint_dict = lint::get_lint_dict();
- for level in lint_levels.iter() {
- let level_name = lint::level_to_str(*level);
-
- let level_short = level_name.slice_chars(0, 1);
- let level_short = level_short.to_ascii().to_upper().into_str();
- let flags = matches.opt_strs(level_short).move_iter().collect::<Vec<_>>().append(
- matches.opt_strs(level_name).as_slice());
- for lint_name in flags.iter() {
- let lint_name = lint_name.replace("-", "_");
- match lint_dict.find_equiv(&lint_name) {
- None => {
- early_error(format!("unknown {} flag: {}",
- level_name, lint_name));
- }
- Some(lint) => {
- lint_opts.push((lint.lint, *level));
- }
- }
- }
- }
-
- let mut debugging_opts = 0;
- let debug_flags = matches.opt_strs("Z");
- let debug_map = session::debugging_opts_map();
- for debug_flag in debug_flags.iter() {
- let mut this_bit = 0;
- for tuple in debug_map.iter() {
- let (name, bit) = match *tuple { (ref a, _, b) => (a, b) };
- if *name == *debug_flag { this_bit = bit; break; }
- }
- if this_bit == 0 {
- early_error(format!("unknown debug flag: {}", *debug_flag))
- }
- debugging_opts |= this_bit;
- }
-
- if debugging_opts & session::DEBUG_LLVM != 0 {
- unsafe { llvm::LLVMSetDebug(1); }
- }
-
- let mut output_types = Vec::new();
- if !parse_only && !no_trans {
- let unparsed_output_types = matches.opt_strs("emit");
- for unparsed_output_type in unparsed_output_types.iter() {
- for part in unparsed_output_type.split(',') {
- let output_type = match part.as_slice() {
- "asm" => link::OutputTypeAssembly,
- "ir" => link::OutputTypeLlvmAssembly,
- "bc" => link::OutputTypeBitcode,
- "obj" => link::OutputTypeObject,
- "link" => link::OutputTypeExe,
- _ => early_error(format!("unknown emission type: `{}`", part))
- };
- output_types.push(output_type)
- }
- }
- };
- output_types.as_mut_slice().sort();
- output_types.dedup();
- if output_types.len() == 0 {
- output_types.push(link::OutputTypeExe);
- }
-
- let sysroot_opt = matches.opt_str("sysroot").map(|m| Path::new(m));
- let target = matches.opt_str("target").unwrap_or(host_triple().to_owned());
- let opt_level = {
- if (debugging_opts & session::NO_OPT) != 0 {
- No
- } else if matches.opt_present("O") {
- if matches.opt_present("opt-level") {
- early_error("-O and --opt-level both provided");
- }
- Default
- } else if matches.opt_present("opt-level") {
- match matches.opt_str("opt-level").as_ref().map(|s| s.as_slice()) {
- None |
- Some("0") => No,
- Some("1") => Less,
- Some("2") => Default,
- Some("3") => Aggressive,
- Some(arg) => {
- early_error(format!("optimization level needs to be between 0-3 \
- (instead was `{}`)", arg));
- }
- }
- } else {
- No
- }
- };
- let gc = debugging_opts & session::GC != 0;
- let debuginfo = if matches.opt_present("g") {
- if matches.opt_present("debuginfo") {
- early_error("-g and --debuginfo both provided");
- }
- FullDebugInfo
- } else if matches.opt_present("debuginfo") {
- match matches.opt_str("debuginfo").as_ref().map(|s| s.as_slice()) {
- Some("0") => NoDebugInfo,
- Some("1") => LimitedDebugInfo,
- None |
- Some("2") => FullDebugInfo,
- Some(arg) => {
- early_error(format!("optimization level needs to be between 0-3 \
- (instead was `{}`)", arg));
- }
- }
+ // Only check command line flags if present. If no types are specified by
+ // command line, then reuse the empty `base` Vec to hold the types that
+ // will be found in crate attributes.
+ let mut base = session.opts.crate_types.clone();
+ if base.len() > 0 {
+ return base
} else {
- NoDebugInfo
- };
-
- let addl_lib_search_paths = matches.opt_strs("L").iter().map(|s| {
- Path::new(s.as_slice())
- }).collect();
-
- let cfg = parse_cfgspecs(matches.opt_strs("cfg").move_iter().collect());
- let test = matches.opt_present("test");
- let write_dependency_info = (matches.opt_present("dep-info"),
- matches.opt_str("dep-info").map(|p| Path::new(p)));
-
- let print_metas = (matches.opt_present("crate-id"),
- matches.opt_present("crate-name"),
- matches.opt_present("crate-file-name"));
- let cg = build_codegen_options(matches);
-
- session::Options {
- crate_types: crate_types,
- gc: gc,
- optimize: opt_level,
- debuginfo: debuginfo,
- lint_opts: lint_opts,
- output_types: output_types,
- addl_lib_search_paths: RefCell::new(addl_lib_search_paths),
- maybe_sysroot: sysroot_opt,
- target_triple: target,
- cfg: cfg,
- test: test,
- parse_only: parse_only,
- no_trans: no_trans,
- no_analysis: no_analysis,
- debugging_opts: debugging_opts,
- write_dependency_info: write_dependency_info,
- print_metas: print_metas,
- cg: cg,
- }
-}
-
-pub fn build_codegen_options(matches: &getopts::Matches)
- -> session::CodegenOptions
-{
- let mut cg = session::basic_codegen_options();
- for option in matches.opt_strs("C").move_iter() {
- let mut iter = option.splitn('=', 1);
- let key = iter.next().unwrap();
- let value = iter.next();
- let option_to_lookup = key.replace("-", "_");
- let mut found = false;
- for &(candidate, setter, _) in session::CG_OPTIONS.iter() {
- if option_to_lookup.as_slice() != candidate { continue }
- if !setter(&mut cg, value) {
- match value {
- Some(..) => early_error(format!("codegen option `{}` takes \
- no value", key)),
- None => early_error(format!("codegen option `{0}` requires \
- a value (-C {0}=<value>)",
- key))
+ let iter = attrs.iter().filter_map(|a| {
+ if a.name().equiv(&("crate_type")) {
+ match a.value_str() {
+ Some(ref n) if n.equiv(&("rlib")) => Some(config::CrateTypeRlib),
+ Some(ref n) if n.equiv(&("dylib")) => Some(config::CrateTypeDylib),
+ Some(ref n) if n.equiv(&("lib")) => {
+ Some(config::default_lib_output())
+ }
+ Some(ref n) if n.equiv(&("staticlib")) => {
+ Some(config::CrateTypeStaticlib)
+ }
+ Some(ref n) if n.equiv(&("bin")) => Some(config::CrateTypeExecutable),
+ Some(_) => {
+ session.add_lint(lint::UnknownCrateType,
+ ast::CRATE_NODE_ID,
+ a.span,
+ "invalid `crate_type` value".to_owned());
+ None
+ }
+ _ => {
+ session.add_lint(lint::UnknownCrateType, ast::CRATE_NODE_ID,
+ a.span, "`crate_type` requires a value".to_owned());
+ None
+ }
}
+ } else {
+ None
}
- found = true;
- break;
- }
- if !found {
- early_error(format!("unknown codegen option: `{}`", key));
- }
- }
- return cg;
-}
-
-pub fn build_session(sopts: session::Options,
- local_crate_source_file: Option<Path>)
- -> Session {
- let codemap = codemap::CodeMap::new();
- let diagnostic_handler =
- diagnostic::default_handler();
- let span_diagnostic_handler =
- diagnostic::mk_span_handler(diagnostic_handler, codemap);
-
- build_session_(sopts, local_crate_source_file, span_diagnostic_handler)
-}
-
-pub fn build_session_(sopts: session::Options,
- local_crate_source_file: Option<Path>,
- span_diagnostic: diagnostic::SpanHandler)
- -> Session {
- let target_cfg = build_target_config(&sopts);
- let p_s = parse::new_parse_sess_special_handler(span_diagnostic);
- let default_sysroot = match sopts.maybe_sysroot {
- Some(_) => None,
- None => Some(filesearch::get_or_default_sysroot())
- };
-
- // Make the path absolute, if necessary
- let local_crate_source_file = local_crate_source_file.map(|path|
- if path.is_absolute() {
- path.clone()
- } else {
- os::getcwd().join(path.clone())
- }
- );
-
- Session {
- targ_cfg: target_cfg,
- opts: sopts,
- cstore: CStore::new(token::get_ident_interner()),
- parse_sess: p_s,
- // For a library crate, this is always none
- entry_fn: RefCell::new(None),
- entry_type: Cell::new(None),
- macro_registrar_fn: Cell::new(None),
- default_sysroot: default_sysroot,
- local_crate_source_file: local_crate_source_file,
- working_dir: os::getcwd(),
- lints: RefCell::new(NodeMap::new()),
- node_id: Cell::new(1),
- crate_types: RefCell::new(Vec::new()),
- features: front::feature_gate::Features::new(),
- recursion_limit: Cell::new(64),
- }
-}
-
-pub fn parse_pretty(sess: &Session, name: &str) -> PpMode {
- match name {
- "normal" => PpmNormal,
- "expanded" => PpmExpanded,
- "typed" => PpmTyped,
- "expanded,identified" => PpmExpandedIdentified,
- "identified" => PpmIdentified,
- _ => {
- sess.fatal("argument to `pretty` must be one of `normal`, \
- `expanded`, `typed`, `identified`, \
- or `expanded,identified`");
+ });
+ base.extend(iter);
+ if base.len() == 0 {
+ base.push(config::CrateTypeExecutable);
}
+ base.as_mut_slice().sort();
+ base.dedup();
+ return base;
}
}
-// rustc command line options
-pub fn optgroups() -> Vec<getopts::OptGroup> {
- vec!(
- optflag("h", "help", "Display this message"),
- optmulti("", "cfg", "Configure the compilation environment", "SPEC"),
- optmulti("L", "", "Add a directory to the library search path", "PATH"),
- optmulti("", "crate-type", "Comma separated list of types of crates for the compiler to emit",
- "[bin|lib|rlib|dylib|staticlib]"),
- optmulti("", "emit", "Comma separated list of types of output for the compiler to emit",
- "[asm|bc|ir|obj|link]"),
- optflag("", "crate-id", "Output the crate id and exit"),
- optflag("", "crate-name", "Output the crate name and exit"),
- optflag("", "crate-file-name", "Output the file(s) that would be written if compilation \
- continued and exit"),
- optflag("g", "", "Equivalent to --debuginfo=2"),
- optopt("", "debuginfo", "Emit DWARF debug info to the objects created:
- 0 = no debug info,
- 1 = line-tables only (for stacktraces and breakpoints),
- 2 = full debug info with variable and type information (same as -g)", "LEVEL"),
- optflag("", "no-trans", "Run all passes except translation; no output"),
- optflag("", "no-analysis",
- "Parse and expand the source, but run no analysis and produce no output"),
- optflag("O", "", "Equivalent to --opt-level=2"),
- optopt("o", "", "Write output to <filename>", "FILENAME"),
- optopt("", "opt-level", "Optimize with possible levels 0-3", "LEVEL"),
- optopt( "", "out-dir", "Write output to compiler-chosen filename in <dir>", "DIR"),
- optflag("", "parse-only", "Parse only; do not compile, assemble, or link"),
- optflagopt("", "pretty",
- "Pretty-print the input instead of compiling;
- valid types are: normal (un-annotated source),
- expanded (crates expanded),
- typed (crates expanded, with type annotations),
- or identified (fully parenthesized,
- AST nodes and blocks with IDs)", "TYPE"),
- optflagopt("", "dep-info",
- "Output dependency info to <filename> after compiling, \
- in a format suitable for use by Makefiles", "FILENAME"),
- optopt("", "sysroot", "Override the system root", "PATH"),
- optflag("", "test", "Build a test harness"),
- optopt("", "target", "Target triple cpu-manufacturer-kernel[-os]
- to compile for (see chapter 3.4 of http://www.sourceware.org/autobook/
- for details)", "TRIPLE"),
- optmulti("W", "warn", "Set lint warnings", "OPT"),
- optmulti("A", "allow", "Set lint allowed", "OPT"),
- optmulti("D", "deny", "Set lint denied", "OPT"),
- optmulti("F", "forbid", "Set lint forbidden", "OPT"),
- optmulti("C", "codegen", "Set a codegen option", "OPT[=VALUE]"),
- optmulti("Z", "", "Set internal debugging options", "FLAG"),
- optflag( "v", "version", "Print version info and exit"))
-}
-
pub struct OutputFilenames {
pub out_directory: Path,
pub out_filestem: ~str,
}
}
-pub fn early_error(msg: &str) -> ! {
- let mut emitter = diagnostic::EmitterWriter::stderr();
- emitter.emit(None, msg, diagnostic::Fatal);
- fail!(diagnostic::FatalError);
-}
-
-pub fn list_metadata(sess: &Session, path: &Path,
- out: &mut io::Writer) -> io::IoResult<()> {
- metadata::loader::list_file_metadata(
- session::sess_os_to_meta_os(sess.targ_cfg.os), path, out)
-}
-
-#[cfg(test)]
-mod test {
-
- use driver::driver::{build_configuration, build_session};
- use driver::driver::{build_session_options, optgroups};
-
- use getopts::getopts;
- use syntax::attr;
- use syntax::attr::AttrMetaMethods;
-
- // When the user supplies --test we should implicitly supply --cfg test
- #[test]
- fn test_switch_implies_cfg_test() {
- let matches =
- &match getopts(["--test".to_owned()], optgroups().as_slice()) {
- Ok(m) => m,
- Err(f) => fail!("test_switch_implies_cfg_test: {}", f.to_err_msg())
- };
- let sessopts = build_session_options(matches);
- let sess = build_session(sessopts, None);
- let cfg = build_configuration(&sess);
- assert!((attr::contains_name(cfg.as_slice(), "test")));
- }
-
- // When the user supplies --test and --cfg test, don't implicitly add
- // another --cfg test
- #[test]
- fn test_switch_implies_cfg_test_unless_cfg_test() {
- let matches =
- &match getopts(["--test".to_owned(), "--cfg=test".to_owned()],
- optgroups().as_slice()) {
- Ok(m) => m,
- Err(f) => {
- fail!("test_switch_implies_cfg_test_unless_cfg_test: {}",
- f.to_err_msg());
- }
- };
- let sessopts = build_session_options(matches);
- let sess = build_session(sessopts, None);
- let cfg = build_configuration(&sess);
- let mut test_items = cfg.iter().filter(|m| m.name().equiv(&("test")));
- assert!(test_items.next().is_some());
- assert!(test_items.next().is_none());
- }
-}
pub use syntax::diagnostic;
+use back::link;
+use driver::driver::{Input, FileInput, StrInput};
+use driver::session::{Session, build_session};
+use middle::lint;
+use metadata;
+
+use std::any::AnyRefExt;
+use std::cmp;
+use std::io;
+use std::os;
+use std::str;
+use std::task::TaskBuilder;
+
+use syntax::ast;
+use syntax::parse;
+use syntax::diagnostic::Emitter;
+
+use getopts;
+
+
pub mod driver;
pub mod session;
+pub mod config;
+
+
+pub fn main_args(args: &[~str]) -> int {
+ let owned_args = args.to_owned();
+ monitor(proc() run_compiler(owned_args));
+ 0
+}
+
+static BUG_REPORT_URL: &'static str =
+ "http://static.rust-lang.org/doc/master/complement-bugreport.html";
+
+fn run_compiler(args: &[~str]) {
+ let matches = match handle_options(Vec::from_slice(args)) {
+ Some(matches) => matches,
+ None => return
+ };
+
+ let (input, input_file_path) = match matches.free.len() {
+ 0u => early_error("no input filename given"),
+ 1u => {
+ let ifile = matches.free.get(0).as_slice();
+ if ifile == "-" {
+ let contents = io::stdin().read_to_end().unwrap();
+ let src = str::from_utf8(contents.as_slice()).unwrap().to_owned();
+ (StrInput(src), None)
+ } else {
+ (FileInput(Path::new(ifile)), Some(Path::new(ifile)))
+ }
+ }
+ _ => early_error("multiple input filenames provided")
+ };
+
+ let sopts = config::build_session_options(&matches);
+ let sess = build_session(sopts, input_file_path);
+ let cfg = config::build_configuration(&sess);
+ let odir = matches.opt_str("out-dir").map(|o| Path::new(o));
+ let ofile = matches.opt_str("o").map(|o| Path::new(o));
+
+ let pretty = matches.opt_default("pretty", "normal").map(|a| {
+ parse_pretty(&sess, a)
+ });
+ match pretty {
+ Some::<PpMode>(ppm) => {
+ driver::pretty_print_input(sess, cfg, &input, ppm, ofile);
+ return;
+ }
+ None::<PpMode> => {/* continue */ }
+ }
+
+ let r = matches.opt_strs("Z");
+ if r.contains(&("ls".to_owned())) {
+ match input {
+ FileInput(ref ifile) => {
+ let mut stdout = io::stdout();
+ list_metadata(&sess, &(*ifile), &mut stdout).unwrap();
+ }
+ StrInput(_) => {
+ early_error("can not list metadata for stdin");
+ }
+ }
+ return;
+ }
+
+ if print_crate_info(&sess, &input, &odir, &ofile) {
+ return;
+ }
+
+ driver::compile_input(sess, cfg, &input, &odir, &ofile);
+}
+
+pub fn version(argv0: &str) {
+ let vers = match option_env!("CFG_VERSION") {
+ Some(vers) => vers,
+ None => "unknown version"
+ };
+ println!("{} {}", argv0, vers);
+ println!("host: {}", driver::host_triple());
+}
+
+fn usage(argv0: &str) {
+ let message = format!("Usage: {} [OPTIONS] INPUT", argv0);
+ println!("{}\n\
+Additional help:
+ -C help Print codegen options
+ -W help Print 'lint' options and default settings
+ -Z help Print internal options for debugging rustc\n",
+ getopts::usage(message, config::optgroups().as_slice()));
+}
+
+fn describe_warnings() {
+ println!("
+Available lint options:
+ -W <foo> Warn about <foo>
+ -A <foo> Allow <foo>
+ -D <foo> Deny <foo>
+ -F <foo> Forbid <foo> (deny, and deny all overrides)
+");
+
+ let lint_dict = lint::get_lint_dict();
+ let mut lint_dict = lint_dict.move_iter()
+ .map(|(k, v)| (v, k))
+ .collect::<Vec<(lint::LintSpec, &'static str)> >();
+ lint_dict.as_mut_slice().sort();
+
+ let mut max_key = 0;
+ for &(_, name) in lint_dict.iter() {
+ max_key = cmp::max(name.len(), max_key);
+ }
+ fn padded(max: uint, s: &str) -> ~str {
+ " ".repeat(max - s.len()) + s
+ }
+ println!("\nAvailable lint checks:\n");
+ println!(" {} {:7.7s} {}",
+ padded(max_key, "name"), "default", "meaning");
+ println!(" {} {:7.7s} {}\n",
+ padded(max_key, "----"), "-------", "-------");
+ for (spec, name) in lint_dict.move_iter() {
+ let name = name.replace("_", "-");
+ println!(" {} {:7.7s} {}",
+ padded(max_key, name),
+ lint::level_to_str(spec.default),
+ spec.desc);
+ }
+ println!("");
+}
+
+fn describe_debug_flags() {
+ println!("\nAvailable debug options:\n");
+ let r = config::debugging_opts_map();
+ for tuple in r.iter() {
+ match *tuple {
+ (ref name, ref desc, _) => {
+ println!(" -Z {:>20s} -- {}", *name, *desc);
+ }
+ }
+ }
+}
+
+fn describe_codegen_flags() {
+ println!("\nAvailable codegen options:\n");
+ let mut cg = config::basic_codegen_options();
+ for &(name, parser, desc) in config::CG_OPTIONS.iter() {
+ // we invoke the parser function on `None` to see if this option needs
+ // an argument or not.
+ let (width, extra) = if parser(&mut cg, None) {
+ (25, "")
+ } else {
+ (21, "=val")
+ };
+ println!(" -C {:>width$s}{} -- {}", name.replace("_", "-"),
+ extra, desc, width=width);
+ }
+}
+
+/// Process command line options. Emits messages as appropirate.If compilation
+/// should continue, returns a getopts::Matches object parsed from args, otherwise
+/// returns None.
+pub fn handle_options(mut args: Vec<~str>) -> Option<getopts::Matches> {
+ let binary = args.shift().unwrap();
+
+ if args.is_empty() { usage(binary); return None; }
+
+ let matches =
+ match getopts::getopts(args.as_slice(), config::optgroups().as_slice()) {
+ Ok(m) => m,
+ Err(f) => {
+ early_error(f.to_err_msg());
+ }
+ };
+
+ if matches.opt_present("h") || matches.opt_present("help") {
+ usage(binary);
+ return None;
+ }
+
+ let lint_flags = matches.opt_strs("W").move_iter().collect::<Vec<_>>().append(
+ matches.opt_strs("warn").as_slice());
+ if lint_flags.iter().any(|x| x == &"help".to_owned()) {
+ describe_warnings();
+ return None;
+ }
+
+ let r = matches.opt_strs("Z");
+ if r.iter().any(|x| x == &"help".to_owned()) {
+ describe_debug_flags();
+ return None;
+ }
+
+ let cg_flags = matches.opt_strs("C");
+ if cg_flags.iter().any(|x| x == &"help".to_owned()) {
+ describe_codegen_flags();
+ return None;
+ }
+
+ if cg_flags.contains(&"passes=list".to_owned()) {
+ unsafe { ::lib::llvm::llvm::LLVMRustPrintPasses(); }
+ return None;
+ }
+
+ if matches.opt_present("v") || matches.opt_present("version") {
+ version(binary);
+ return None;
+ }
+
+ Some(matches)
+}
+
+fn print_crate_info(sess: &Session,
+ input: &Input,
+ odir: &Option<Path>,
+ ofile: &Option<Path>)
+ -> bool {
+ let (crate_id, crate_name, crate_file_name) = sess.opts.print_metas;
+ // these nasty nested conditions are to avoid doing extra work
+ if crate_id || crate_name || crate_file_name {
+ let attrs = parse_crate_attrs(sess, input);
+ let t_outputs = driver::build_output_filenames(input, odir, ofile,
+ attrs.as_slice(), sess);
+ let id = link::find_crate_id(attrs.as_slice(), t_outputs.out_filestem);
+
+ if crate_id {
+ println!("{}", id.to_str());
+ }
+ if crate_name {
+ println!("{}", id.name);
+ }
+ if crate_file_name {
+ let crate_types = driver::collect_crate_types(sess, attrs.as_slice());
+ for &style in crate_types.iter() {
+ let fname = link::filename_for_input(sess, style, &id,
+ &t_outputs.with_extension(""));
+ println!("{}", fname.filename_display());
+ }
+ }
+
+ true
+ } else {
+ false
+ }
+}
+
+pub enum PpMode {
+ PpmNormal,
+ PpmExpanded,
+ PpmTyped,
+ PpmIdentified,
+ PpmExpandedIdentified
+}
+
+pub fn parse_pretty(sess: &Session, name: &str) -> PpMode {
+ match name {
+ "normal" => PpmNormal,
+ "expanded" => PpmExpanded,
+ "typed" => PpmTyped,
+ "expanded,identified" => PpmExpandedIdentified,
+ "identified" => PpmIdentified,
+ _ => {
+ sess.fatal("argument to `pretty` must be one of `normal`, \
+ `expanded`, `typed`, `identified`, \
+ or `expanded,identified`");
+ }
+ }
+}
+
+fn parse_crate_attrs(sess: &Session, input: &Input) ->
+ Vec<ast::Attribute> {
+ let result = match *input {
+ FileInput(ref ifile) => {
+ parse::parse_crate_attrs_from_file(ifile,
+ Vec::new(),
+ &sess.parse_sess)
+ }
+ StrInput(ref src) => {
+ parse::parse_crate_attrs_from_source_str(
+ driver::anon_src().to_strbuf(),
+ src.to_strbuf(),
+ Vec::new(),
+ &sess.parse_sess)
+ }
+ };
+ result.move_iter().collect()
+}
+
+pub fn early_error(msg: &str) -> ! {
+ let mut emitter = diagnostic::EmitterWriter::stderr();
+ emitter.emit(None, msg, diagnostic::Fatal);
+ fail!(diagnostic::FatalError);
+}
+
+pub fn list_metadata(sess: &Session, path: &Path,
+ out: &mut io::Writer) -> io::IoResult<()> {
+ metadata::loader::list_file_metadata(
+ config::cfg_os_to_meta_os(sess.targ_cfg.os), path, out)
+}
+
+/// Run a procedure which will detect failures in the compiler and print nicer
+/// error messages rather than just failing the test.
+///
+/// The diagnostic emitter yielded to the procedure should be used for reporting
+/// errors of the compiler.
+fn monitor(f: proc():Send) {
+ // FIXME: This is a hack for newsched since it doesn't support split stacks.
+ // rustc needs a lot of stack! When optimizations are disabled, it needs
+ // even *more* stack than usual as well.
+ #[cfg(rtopt)]
+ static STACK_SIZE: uint = 6000000; // 6MB
+ #[cfg(not(rtopt))]
+ static STACK_SIZE: uint = 20000000; // 20MB
+
+ let mut task_builder = TaskBuilder::new().named("rustc");
+
+ // FIXME: Hacks on hacks. If the env is trying to override the stack size
+ // then *don't* set it explicitly.
+ if os::getenv("RUST_MIN_STACK").is_none() {
+ task_builder.opts.stack_size = Some(STACK_SIZE);
+ }
+
+ let (tx, rx) = channel();
+ let w = io::ChanWriter::new(tx);
+ let mut r = io::ChanReader::new(rx);
+
+ match task_builder.try(proc() {
+ io::stdio::set_stderr(box w);
+ f()
+ }) {
+ Ok(()) => { /* fallthrough */ }
+ Err(value) => {
+ // Task failed without emitting a fatal diagnostic
+ if !value.is::<diagnostic::FatalError>() {
+ let mut emitter = diagnostic::EmitterWriter::stderr();
+
+ // a .span_bug or .bug call has already printed what
+ // it wants to print.
+ if !value.is::<diagnostic::ExplicitBug>() {
+ emitter.emit(
+ None,
+ "unexpected failure",
+ diagnostic::Bug);
+ }
+
+ let xs = [
+ "the compiler hit an unexpected failure path. this is a bug.".to_owned(),
+ "we would appreciate a bug report: " + BUG_REPORT_URL,
+ "run with `RUST_BACKTRACE=1` for a backtrace".to_owned(),
+ ];
+ for note in xs.iter() {
+ emitter.emit(None, *note, diagnostic::Note)
+ }
+
+ match r.read_to_str() {
+ Ok(s) => println!("{}", s),
+ Err(e) => emitter.emit(None,
+ format!("failed to read internal stderr: {}", e),
+ diagnostic::Error),
+ }
+ }
+
+ // Fail so the process returns a failure code, but don't pollute the
+ // output with some unnecessary failure messages, we've already
+ // printed everything that we needed to.
+ io::stdio::set_stderr(box io::util::NullWriter);
+ fail!();
+ }
+ }
+}
// except according to those terms.
-use back::target_strs;
-use back;
-use driver::driver::host_triple;
+use driver::config;
+use driver::driver;
use front;
+use metadata::cstore::CStore;
use metadata::filesearch;
-use metadata;
use middle::lint;
use util::nodemap::NodeMap;
-use syntax::attr::AttrMetaMethods;
use syntax::ast::NodeId;
-use syntax::ast::{IntTy, UintTy};
use syntax::codemap::Span;
use syntax::diagnostic;
+use syntax::parse;
+use syntax::parse::token;
use syntax::parse::ParseSess;
-use syntax::{abi, ast, codemap};
+use syntax::{ast, codemap};
+use std::os;
use std::cell::{Cell, RefCell};
-use collections::HashSet;
-pub struct Config {
- pub os: abi::Os,
- pub arch: abi::Architecture,
- pub target_strs: target_strs::t,
- pub int_type: IntTy,
- pub uint_type: UintTy,
-}
-
-macro_rules! debugging_opts(
- ([ $opt:ident ] $cnt:expr ) => (
- pub static $opt: u64 = 1 << $cnt;
- );
- ([ $opt:ident, $($rest:ident),* ] $cnt:expr ) => (
- pub static $opt: u64 = 1 << $cnt;
- debugging_opts!([ $($rest),* ] $cnt + 1)
- )
-)
-
-debugging_opts!(
- [
- VERBOSE,
- TIME_PASSES,
- COUNT_LLVM_INSNS,
- TIME_LLVM_PASSES,
- TRANS_STATS,
- ASM_COMMENTS,
- NO_VERIFY,
- BORROWCK_STATS,
- NO_LANDING_PADS,
- DEBUG_LLVM,
- SHOW_SPAN,
- COUNT_TYPE_SIZES,
- META_STATS,
- NO_OPT,
- GC,
- PRINT_LINK_ARGS,
- PRINT_LLVM_PASSES,
- LTO,
- AST_JSON,
- AST_JSON_NOEXPAND,
- LS
- ]
- 0
-)
-
-pub fn debugging_opts_map() -> Vec<(&'static str, &'static str, u64)> {
- vec!(("verbose", "in general, enable more debug printouts", VERBOSE),
- ("time-passes", "measure time of each rustc pass", TIME_PASSES),
- ("count-llvm-insns", "count where LLVM \
- instrs originate", COUNT_LLVM_INSNS),
- ("time-llvm-passes", "measure time of each LLVM pass",
- TIME_LLVM_PASSES),
- ("trans-stats", "gather trans statistics", TRANS_STATS),
- ("asm-comments", "generate comments into the assembly (may change behavior)",
- ASM_COMMENTS),
- ("no-verify", "skip LLVM verification", NO_VERIFY),
- ("borrowck-stats", "gather borrowck statistics", BORROWCK_STATS),
- ("no-landing-pads", "omit landing pads for unwinding",
- NO_LANDING_PADS),
- ("debug-llvm", "enable debug output from LLVM", DEBUG_LLVM),
- ("show-span", "show spans for compiler debugging", SHOW_SPAN),
- ("count-type-sizes", "count the sizes of aggregate types",
- COUNT_TYPE_SIZES),
- ("meta-stats", "gather metadata statistics", META_STATS),
- ("no-opt", "do not optimize, even if -O is passed", NO_OPT),
- ("print-link-args", "Print the arguments passed to the linker",
- PRINT_LINK_ARGS),
- ("gc", "Garbage collect shared data (experimental)", GC),
- ("print-llvm-passes",
- "Prints the llvm optimization passes being run",
- PRINT_LLVM_PASSES),
- ("lto", "Perform LLVM link-time optimizations", LTO),
- ("ast-json", "Print the AST as JSON and halt", AST_JSON),
- ("ast-json-noexpand", "Print the pre-expansion AST as JSON and halt", AST_JSON_NOEXPAND),
- ("ls", "List the symbols defined by a library crate", LS))
-}
-
-#[deriving(Clone, Eq)]
-pub enum OptLevel {
- No, // -O0
- Less, // -O1
- Default, // -O2
- Aggressive // -O3
-}
-
-#[deriving(Clone, Eq)]
-pub enum DebugInfoLevel {
- NoDebugInfo,
- LimitedDebugInfo,
- FullDebugInfo,
-}
-
-#[deriving(Clone)]
-pub struct Options {
- // The crate config requested for the session, which may be combined
- // with additional crate configurations during the compile process
- pub crate_types: Vec<CrateType>,
-
- pub gc: bool,
- pub optimize: OptLevel,
- pub debuginfo: DebugInfoLevel,
- pub lint_opts: Vec<(lint::Lint, lint::level)> ,
- pub output_types: Vec<back::link::OutputType> ,
- // This was mutable for rustpkg, which updates search paths based on the
- // parsed code. It remains mutable in case its replacements wants to use
- // this.
- pub addl_lib_search_paths: RefCell<HashSet<Path>>,
- pub maybe_sysroot: Option<Path>,
- pub target_triple: ~str,
- // User-specified cfg meta items. The compiler itself will add additional
- // items to the crate config, and during parsing the entire crate config
- // will be added to the crate AST node. This should not be used for
- // anything except building the full crate config prior to parsing.
- pub cfg: ast::CrateConfig,
- pub test: bool,
- pub parse_only: bool,
- pub no_trans: bool,
- pub no_analysis: bool,
- pub debugging_opts: u64,
- /// Whether to write dependency files. It's (enabled, optional filename).
- pub write_dependency_info: (bool, Option<Path>),
- /// Crate id-related things to maybe print. It's (crate_id, crate_name, crate_file_name).
- pub print_metas: (bool, bool, bool),
- pub cg: CodegenOptions,
-}
-
-// The type of entry function, so
-// users can have their own entry
-// functions that don't start a
-// scheduler
-#[deriving(Eq)]
-pub enum EntryFnType {
- EntryMain,
- EntryStart,
- EntryNone,
-}
-
-#[deriving(Eq, Ord, Clone, TotalOrd, TotalEq, Hash)]
-pub enum CrateType {
- CrateTypeExecutable,
- CrateTypeDylib,
- CrateTypeRlib,
- CrateTypeStaticlib,
-}
pub struct Session {
- pub targ_cfg: Config,
- pub opts: Options,
- pub cstore: metadata::cstore::CStore,
+ pub targ_cfg: config::Config,
+ pub opts: config::Options,
+ pub cstore: CStore,
pub parse_sess: ParseSess,
// For a library crate, this is always none
pub entry_fn: RefCell<Option<(NodeId, codemap::Span)>>,
- pub entry_type: Cell<Option<EntryFnType>>,
+ pub entry_type: Cell<Option<config::EntryFnType>>,
pub macro_registrar_fn: Cell<Option<ast::NodeId>>,
pub default_sysroot: Option<Path>,
// The name of the root source file of the crate, in the local file system. The path is always
pub working_dir: Path,
pub lints: RefCell<NodeMap<Vec<(lint::Lint, codemap::Span, ~str)>>>,
pub node_id: Cell<ast::NodeId>,
- pub crate_types: RefCell<Vec<CrateType>>,
+ pub crate_types: RefCell<Vec<config::CrateType>>,
pub features: front::feature_gate::Features,
/// The maximum recursion limit for potentially infinitely recursive
pub fn impossible_case(&self, sp: Span, msg: &str) -> ! {
self.span_bug(sp, format!("impossible case reached: {}", msg));
}
- pub fn verbose(&self) -> bool { self.debugging_opt(VERBOSE) }
- pub fn time_passes(&self) -> bool { self.debugging_opt(TIME_PASSES) }
+ pub fn verbose(&self) -> bool { self.debugging_opt(config::VERBOSE) }
+ pub fn time_passes(&self) -> bool { self.debugging_opt(config::TIME_PASSES) }
pub fn count_llvm_insns(&self) -> bool {
- self.debugging_opt(COUNT_LLVM_INSNS)
+ self.debugging_opt(config::COUNT_LLVM_INSNS)
}
pub fn count_type_sizes(&self) -> bool {
- self.debugging_opt(COUNT_TYPE_SIZES)
+ self.debugging_opt(config::COUNT_TYPE_SIZES)
}
pub fn time_llvm_passes(&self) -> bool {
- self.debugging_opt(TIME_LLVM_PASSES)
+ self.debugging_opt(config::TIME_LLVM_PASSES)
}
- pub fn trans_stats(&self) -> bool { self.debugging_opt(TRANS_STATS) }
- pub fn meta_stats(&self) -> bool { self.debugging_opt(META_STATS) }
- pub fn asm_comments(&self) -> bool { self.debugging_opt(ASM_COMMENTS) }
- pub fn no_verify(&self) -> bool { self.debugging_opt(NO_VERIFY) }
- pub fn borrowck_stats(&self) -> bool { self.debugging_opt(BORROWCK_STATS) }
+ pub fn trans_stats(&self) -> bool { self.debugging_opt(config::TRANS_STATS) }
+ pub fn meta_stats(&self) -> bool { self.debugging_opt(config::META_STATS) }
+ pub fn asm_comments(&self) -> bool { self.debugging_opt(config::ASM_COMMENTS) }
+ pub fn no_verify(&self) -> bool { self.debugging_opt(config::NO_VERIFY) }
+ pub fn borrowck_stats(&self) -> bool { self.debugging_opt(config::BORROWCK_STATS) }
pub fn print_llvm_passes(&self) -> bool {
- self.debugging_opt(PRINT_LLVM_PASSES)
+ self.debugging_opt(config::PRINT_LLVM_PASSES)
}
pub fn lto(&self) -> bool {
- self.debugging_opt(LTO)
+ self.debugging_opt(config::LTO)
}
pub fn no_landing_pads(&self) -> bool {
- self.debugging_opt(NO_LANDING_PADS)
+ self.debugging_opt(config::NO_LANDING_PADS)
}
pub fn show_span(&self) -> bool {
- self.debugging_opt(SHOW_SPAN)
+ self.debugging_opt(config::SHOW_SPAN)
}
pub fn sysroot<'a>(&'a self) -> &'a Path {
match self.opts.maybe_sysroot {
pub fn host_filesearch<'a>(&'a self) -> filesearch::FileSearch<'a> {
filesearch::FileSearch::new(
self.sysroot(),
- host_triple(),
+ driver::host_triple(),
&self.opts.addl_lib_search_paths)
}
}
-/// Some reasonable defaults
-pub fn basic_options() -> Options {
- Options {
- crate_types: Vec::new(),
- gc: false,
- optimize: No,
- debuginfo: NoDebugInfo,
- lint_opts: Vec::new(),
- output_types: Vec::new(),
- addl_lib_search_paths: RefCell::new(HashSet::new()),
- maybe_sysroot: None,
- target_triple: host_triple().to_owned(),
- cfg: Vec::new(),
- test: false,
- parse_only: false,
- no_trans: false,
- no_analysis: false,
- debugging_opts: 0,
- write_dependency_info: (false, None),
- print_metas: (false, false, false),
- cg: basic_codegen_options(),
- }
-}
-
-/// Declare a macro that will define all CodegenOptions fields and parsers all
-/// at once. The goal of this macro is to define an interface that can be
-/// programmatically used by the option parser in order to initialize the struct
-/// without hardcoding field names all over the place.
-///
-/// The goal is to invoke this macro once with the correct fields, and then this
-/// macro generates all necessary code. The main gotcha of this macro is the
-/// cgsetters module which is a bunch of generated code to parse an option into
-/// its respective field in the struct. There are a few hand-written parsers for
-/// parsing specific types of values in this module.
-macro_rules! cgoptions(
- ($($opt:ident : $t:ty = ($init:expr, $parse:ident, $desc:expr)),* ,) =>
-(
- #[deriving(Clone)]
- pub struct CodegenOptions { $(pub $opt: $t),* }
-
- pub fn basic_codegen_options() -> CodegenOptions {
- CodegenOptions { $($opt: $init),* }
- }
-
- pub type CodegenSetter = fn(&mut CodegenOptions, v: Option<&str>) -> bool;
- pub static CG_OPTIONS: &'static [(&'static str, CodegenSetter,
- &'static str)] =
- &[ $( (stringify!($opt), cgsetters::$opt, $desc) ),* ];
-
- mod cgsetters {
- use super::CodegenOptions;
-
- $(
- pub fn $opt(cg: &mut CodegenOptions, v: Option<&str>) -> bool {
- $parse(&mut cg.$opt, v)
- }
- )*
+pub fn build_session(sopts: config::Options,
+ local_crate_source_file: Option<Path>)
+ -> Session {
+ let codemap = codemap::CodeMap::new();
+ let diagnostic_handler =
+ diagnostic::default_handler();
+ let span_diagnostic_handler =
+ diagnostic::mk_span_handler(diagnostic_handler, codemap);
- fn parse_bool(slot: &mut bool, v: Option<&str>) -> bool {
- match v {
- Some(..) => false,
- None => { *slot = true; true }
- }
- }
-
- fn parse_opt_string(slot: &mut Option<~str>, v: Option<&str>) -> bool {
- match v {
- Some(s) => { *slot = Some(s.to_owned()); true },
- None => false,
- }
- }
-
- fn parse_string(slot: &mut ~str, v: Option<&str>) -> bool {
- match v {
- Some(s) => { *slot = s.to_owned(); true },
- None => false,
- }
- }
+ build_session_(sopts, local_crate_source_file, span_diagnostic_handler)
+}
- fn parse_list(slot: &mut Vec<~str>, v: Option<&str>)
- -> bool {
- match v {
- Some(s) => {
- for s in s.words() {
- slot.push(s.to_owned());
- }
- true
- },
- None => false,
- }
+pub fn build_session_(sopts: config::Options,
+ local_crate_source_file: Option<Path>,
+ span_diagnostic: diagnostic::SpanHandler)
+ -> Session {
+ let target_cfg = config::build_target_config(&sopts);
+ let p_s = parse::new_parse_sess_special_handler(span_diagnostic);
+ let default_sysroot = match sopts.maybe_sysroot {
+ Some(_) => None,
+ None => Some(filesearch::get_or_default_sysroot())
+ };
+
+ // Make the path absolute, if necessary
+ let local_crate_source_file = local_crate_source_file.map(|path|
+ if path.is_absolute() {
+ path.clone()
+ } else {
+ os::getcwd().join(path.clone())
}
+ );
+ Session {
+ targ_cfg: target_cfg,
+ opts: sopts,
+ cstore: CStore::new(token::get_ident_interner()),
+ parse_sess: p_s,
+ // For a library crate, this is always none
+ entry_fn: RefCell::new(None),
+ entry_type: Cell::new(None),
+ macro_registrar_fn: Cell::new(None),
+ default_sysroot: default_sysroot,
+ local_crate_source_file: local_crate_source_file,
+ working_dir: os::getcwd(),
+ lints: RefCell::new(NodeMap::new()),
+ node_id: Cell::new(1),
+ crate_types: RefCell::new(Vec::new()),
+ features: front::feature_gate::Features::new(),
+ recursion_limit: Cell::new(64),
}
-) )
+}
-cgoptions!(
- ar: Option<~str> = (None, parse_opt_string,
- "tool to assemble archives with"),
- linker: Option<~str> = (None, parse_opt_string,
- "system linker to link outputs with"),
- link_args: Vec<~str> = (Vec::new(), parse_list,
- "extra arguments to pass to the linker (space separated)"),
- target_cpu: ~str = ("generic".to_owned(), parse_string,
- "select target processor (llc -mcpu=help for details)"),
- target_feature: ~str = ("".to_owned(), parse_string,
- "target specific attributes (llc -mattr=help for details)"),
- passes: Vec<~str> = (Vec::new(), parse_list,
- "a list of extra LLVM passes to run (space separated)"),
- llvm_args: Vec<~str> = (Vec::new(), parse_list,
- "a list of arguments to pass to llvm (space separated)"),
- save_temps: bool = (false, parse_bool,
- "save all temporary output files during compilation"),
- android_cross_path: Option<~str> = (None, parse_opt_string,
- "the path to the Android NDK"),
- no_rpath: bool = (false, parse_bool,
- "disables setting the rpath in libs/exes"),
- no_prepopulate_passes: bool = (false, parse_bool,
- "don't pre-populate the pass manager with a list of passes"),
- no_vectorize_loops: bool = (false, parse_bool,
- "don't run the loop vectorization optimization passes"),
- no_vectorize_slp: bool = (false, parse_bool,
- "don't run LLVM's SLP vectorization pass"),
- soft_float: bool = (false, parse_bool,
- "generate software floating point library calls"),
- prefer_dynamic: bool = (false, parse_bool,
- "prefer dynamic linking to static linking"),
- no_integrated_as: bool = (false, parse_bool,
- "use an external assembler rather than LLVM's integrated one"),
- relocation_model: ~str = ("pic".to_owned(), parse_string,
- "choose the relocation model to use (llc -relocation-model for details)"),
-)
// Seems out of place, but it uses session, so I'm putting it here
pub fn expect<T:Clone>(sess: &Session, opt: Option<T>, msg: || -> StrBuf)
diagnostic::expect(sess.diagnostic(), opt, msg)
}
-pub fn default_lib_output() -> CrateType {
- CrateTypeRlib
-}
-
-pub fn collect_crate_types(session: &Session,
- attrs: &[ast::Attribute]) -> Vec<CrateType> {
- // If we're generating a test executable, then ignore all other output
- // styles at all other locations
- if session.opts.test {
- return vec!(CrateTypeExecutable)
- }
-
- // Only check command line flags if present. If no types are specified by
- // command line, then reuse the empty `base` Vec to hold the types that
- // will be found in crate attributes.
- let mut base = session.opts.crate_types.clone();
- if base.len() > 0 {
- return base
- } else {
- let iter = attrs.iter().filter_map(|a| {
- if a.name().equiv(&("crate_type")) {
- match a.value_str() {
- Some(ref n) if n.equiv(&("rlib")) => Some(CrateTypeRlib),
- Some(ref n) if n.equiv(&("dylib")) => Some(CrateTypeDylib),
- Some(ref n) if n.equiv(&("lib")) => {
- Some(default_lib_output())
- }
- Some(ref n) if n.equiv(&("staticlib")) => {
- Some(CrateTypeStaticlib)
- }
- Some(ref n) if n.equiv(&("bin")) => Some(CrateTypeExecutable),
- Some(_) => {
- session.add_lint(lint::UnknownCrateType,
- ast::CRATE_NODE_ID,
- a.span,
- "invalid `crate_type` value".to_owned());
- None
- }
- _ => {
- session.add_lint(lint::UnknownCrateType, ast::CRATE_NODE_ID,
- a.span, "`crate_type` requires a value".to_owned());
- None
- }
- }
- } else {
- None
- }
- });
- base.extend(iter);
- if base.len() == 0 {
- base.push(CrateTypeExecutable);
- }
- base.as_mut_slice().sort();
- base.dedup();
- return base;
- }
-}
-
-pub fn sess_os_to_meta_os(os: abi::Os) -> metadata::loader::Os {
- use metadata::loader;
-
- match os {
- abi::OsWin32 => loader::OsWin32,
- abi::OsLinux => loader::OsLinux,
- abi::OsAndroid => loader::OsAndroid,
- abi::OsMacos => loader::OsMacos,
- abi::OsFreebsd => loader::OsFreebsd
- }
-}
// option. This file may not be copied, modified, or distributed
// except according to those terms.
-use driver::session;
+use driver::config;
use driver::session::Session;
use syntax::ast;
});
let any_exe = self.sess.crate_types.borrow().iter().any(|ty| {
- *ty == session::CrateTypeExecutable
+ *ty == config::CrateTypeExecutable
});
if use_start(&krate) && any_exe {
vis.push(ast::ViewItem {
#[phase(syntax, link)]
extern crate log;
-use back::link;
-use driver::session;
-use middle::lint;
-
-use d = driver::driver;
-
-use std::any::AnyRefExt;
-use std::cmp;
-use std::io;
-use std::os;
-use std::str;
-use std::task::TaskBuilder;
-use syntax::ast;
-use syntax::diagnostic::Emitter;
-use syntax::diagnostic;
-use syntax::parse;
-
pub mod middle {
pub mod trans;
pub mod ty;
pub mod llvmdeps;
}
-static BUG_REPORT_URL: &'static str =
- "http://static.rust-lang.org/doc/master/complement-bugreport.html";
-
-pub fn version(argv0: &str) {
- let vers = match option_env!("CFG_VERSION") {
- Some(vers) => vers,
- None => "unknown version"
- };
- println!("{} {}", argv0, vers);
- println!("host: {}", d::host_triple());
-}
-
-pub fn usage(argv0: &str) {
- let message = format!("Usage: {} [OPTIONS] INPUT", argv0);
- println!("{}\n\
-Additional help:
- -C help Print codegen options
- -W help Print 'lint' options and default settings
- -Z help Print internal options for debugging rustc\n",
- getopts::usage(message, d::optgroups().as_slice()));
-}
-
-pub fn describe_warnings() {
- println!("
-Available lint options:
- -W <foo> Warn about <foo>
- -A <foo> Allow <foo>
- -D <foo> Deny <foo>
- -F <foo> Forbid <foo> (deny, and deny all overrides)
-");
-
- let lint_dict = lint::get_lint_dict();
- let mut lint_dict = lint_dict.move_iter()
- .map(|(k, v)| (v, k))
- .collect::<Vec<(lint::LintSpec, &'static str)> >();
- lint_dict.as_mut_slice().sort();
-
- let mut max_key = 0;
- for &(_, name) in lint_dict.iter() {
- max_key = cmp::max(name.len(), max_key);
- }
- fn padded(max: uint, s: &str) -> ~str {
- " ".repeat(max - s.len()) + s
- }
- println!("\nAvailable lint checks:\n");
- println!(" {} {:7.7s} {}",
- padded(max_key, "name"), "default", "meaning");
- println!(" {} {:7.7s} {}\n",
- padded(max_key, "----"), "-------", "-------");
- for (spec, name) in lint_dict.move_iter() {
- let name = name.replace("_", "-");
- println!(" {} {:7.7s} {}",
- padded(max_key, name),
- lint::level_to_str(spec.default),
- spec.desc);
- }
- println!("");
-}
-
-pub fn describe_debug_flags() {
- println!("\nAvailable debug options:\n");
- let r = session::debugging_opts_map();
- for tuple in r.iter() {
- match *tuple {
- (ref name, ref desc, _) => {
- println!(" -Z {:>20s} -- {}", *name, *desc);
- }
- }
- }
-}
-
-pub fn describe_codegen_flags() {
- println!("\nAvailable codegen options:\n");
- let mut cg = session::basic_codegen_options();
- for &(name, parser, desc) in session::CG_OPTIONS.iter() {
- // we invoke the parser function on `None` to see if this option needs
- // an argument or not.
- let (width, extra) = if parser(&mut cg, None) {
- (25, "")
- } else {
- (21, "=val")
- };
- println!(" -C {:>width$s}{} -- {}", name.replace("_", "-"),
- extra, desc, width=width);
- }
-}
-
-pub fn run_compiler(args: &[~str]) {
- let mut args = Vec::from_slice(args);
- let binary = args.shift().unwrap();
-
- if args.is_empty() { usage(binary); return; }
-
- let matches =
- &match getopts::getopts(args.as_slice(), d::optgroups().as_slice()) {
- Ok(m) => m,
- Err(f) => {
- d::early_error(f.to_err_msg());
- }
- };
-
- if matches.opt_present("h") || matches.opt_present("help") {
- usage(binary);
- return;
- }
-
- let lint_flags = matches.opt_strs("W").move_iter().collect::<Vec<_>>().append(
- matches.opt_strs("warn").as_slice());
- if lint_flags.iter().any(|x| x == &"help".to_owned()) {
- describe_warnings();
- return;
- }
-
- let r = matches.opt_strs("Z");
- if r.iter().any(|x| x == &"help".to_owned()) {
- describe_debug_flags();
- return;
- }
-
- let cg_flags = matches.opt_strs("C");
- if cg_flags.iter().any(|x| x == &"help".to_owned()) {
- describe_codegen_flags();
- return;
- }
-
- if cg_flags.contains(&"passes=list".to_owned()) {
- unsafe { lib::llvm::llvm::LLVMRustPrintPasses(); }
- return;
- }
-
- if matches.opt_present("v") || matches.opt_present("version") {
- version(binary);
- return;
- }
- let (input, input_file_path) = match matches.free.len() {
- 0u => d::early_error("no input filename given"),
- 1u => {
- let ifile = matches.free.get(0).as_slice();
- if ifile == "-" {
- let contents = io::stdin().read_to_end().unwrap();
- let src = str::from_utf8(contents.as_slice()).unwrap().to_owned();
- (d::StrInput(src), None)
- } else {
- (d::FileInput(Path::new(ifile)), Some(Path::new(ifile)))
- }
- }
- _ => d::early_error("multiple input filenames provided")
- };
-
- let sopts = d::build_session_options(matches);
- let sess = d::build_session(sopts, input_file_path);
- let odir = matches.opt_str("out-dir").map(|o| Path::new(o));
- let ofile = matches.opt_str("o").map(|o| Path::new(o));
- let cfg = d::build_configuration(&sess);
- let pretty = matches.opt_default("pretty", "normal").map(|a| {
- d::parse_pretty(&sess, a)
- });
- match pretty {
- Some::<d::PpMode>(ppm) => {
- d::pretty_print_input(sess, cfg, &input, ppm, ofile);
- return;
- }
- None::<d::PpMode> => {/* continue */ }
- }
-
- if r.contains(&("ls".to_owned())) {
- match input {
- d::FileInput(ref ifile) => {
- let mut stdout = io::stdout();
- d::list_metadata(&sess, &(*ifile), &mut stdout).unwrap();
- }
- d::StrInput(_) => {
- d::early_error("can not list metadata for stdin");
- }
- }
- return;
- }
- let (crate_id, crate_name, crate_file_name) = sess.opts.print_metas;
- // these nasty nested conditions are to avoid doing extra work
- if crate_id || crate_name || crate_file_name {
- let attrs = parse_crate_attrs(&sess, &input);
- let t_outputs = d::build_output_filenames(&input, &odir, &ofile,
- attrs.as_slice(), &sess);
- let id = link::find_crate_id(attrs.as_slice(), t_outputs.out_filestem);
-
- if crate_id {
- println!("{}", id.to_str());
- }
- if crate_name {
- println!("{}", id.name);
- }
- if crate_file_name {
- let crate_types = session::collect_crate_types(&sess,
- attrs.as_slice());
- for &style in crate_types.iter() {
- let fname = link::filename_for_input(&sess, style, &id,
- &t_outputs.with_extension(""));
- println!("{}", fname.filename_display());
- }
- }
-
- return;
- }
-
- d::compile_input(sess, cfg, &input, &odir, &ofile);
-}
-
-fn parse_crate_attrs(sess: &session::Session, input: &d::Input) ->
- Vec<ast::Attribute> {
- let result = match *input {
- d::FileInput(ref ifile) => {
- parse::parse_crate_attrs_from_file(ifile,
- Vec::new(),
- &sess.parse_sess)
- }
- d::StrInput(ref src) => {
- parse::parse_crate_attrs_from_source_str(
- d::anon_src().to_strbuf(),
- src.to_strbuf(),
- Vec::new(),
- &sess.parse_sess)
- }
- };
- result.move_iter().collect()
-}
-
-/// Run a procedure which will detect failures in the compiler and print nicer
-/// error messages rather than just failing the test.
-///
-/// The diagnostic emitter yielded to the procedure should be used for reporting
-/// errors of the compiler.
-pub fn monitor(f: proc():Send) {
- // FIXME: This is a hack for newsched since it doesn't support split stacks.
- // rustc needs a lot of stack! When optimizations are disabled, it needs
- // even *more* stack than usual as well.
- #[cfg(rtopt)]
- static STACK_SIZE: uint = 6000000; // 6MB
- #[cfg(not(rtopt))]
- static STACK_SIZE: uint = 20000000; // 20MB
-
- let mut task_builder = TaskBuilder::new().named("rustc");
-
- // FIXME: Hacks on hacks. If the env is trying to override the stack size
- // then *don't* set it explicitly.
- if os::getenv("RUST_MIN_STACK").is_none() {
- task_builder.opts.stack_size = Some(STACK_SIZE);
- }
-
- let (tx, rx) = channel();
- let w = io::ChanWriter::new(tx);
- let mut r = io::ChanReader::new(rx);
-
- match task_builder.try(proc() {
- io::stdio::set_stderr(box w);
- f()
- }) {
- Ok(()) => { /* fallthrough */ }
- Err(value) => {
- // Task failed without emitting a fatal diagnostic
- if !value.is::<diagnostic::FatalError>() {
- let mut emitter = diagnostic::EmitterWriter::stderr();
-
- // a .span_bug or .bug call has already printed what
- // it wants to print.
- if !value.is::<diagnostic::ExplicitBug>() {
- emitter.emit(
- None,
- "unexpected failure",
- diagnostic::Bug);
- }
-
- let xs = [
- "the compiler hit an unexpected failure path. this is a bug.".to_owned(),
- "we would appreciate a bug report: " + BUG_REPORT_URL,
- "run with `RUST_BACKTRACE=1` for a backtrace".to_owned(),
- ];
- for note in xs.iter() {
- emitter.emit(None, *note, diagnostic::Note)
- }
-
- match r.read_to_str() {
- Ok(s) => println!("{}", s),
- Err(e) => emitter.emit(None,
- format!("failed to read internal stderr: {}", e),
- diagnostic::Error),
- }
- }
-
- // Fail so the process returns a failure code, but don't pollute the
- // output with some unnecessary failure messages, we've already
- // printed everything that we needed to.
- io::stdio::set_stderr(box io::util::NullWriter);
- fail!();
- }
- }
-}
pub fn main() {
- std::os::set_exit_status(main_args(std::os::args().as_slice()));
+ std::os::set_exit_status(driver::main_args(std::os::args().as_slice()));
}
-pub fn main_args(args: &[~str]) -> int {
- let owned_args = args.to_owned();
- monitor(proc() run_compiler(owned_args));
- 0
-}
use back::link;
use back::svh::Svh;
use driver::session::Session;
-use driver::{driver, session};
+use driver::{driver, config};
use metadata::cstore;
use metadata::cstore::CStore;
use metadata::decoder;
id_hash: id_hash,
hash: hash.map(|a| &*a),
filesearch: e.sess.target_filesearch(),
- os: session::sess_os_to_meta_os(e.sess.targ_cfg.os),
+ os: config::cfg_os_to_meta_os(e.sess.targ_cfg.os),
triple: e.sess.targ_cfg.target_strs.target_triple.as_slice(),
root: root,
rejected_via_hash: vec!(),
let is_cross = target_triple != driver::host_triple();
let mut should_link = info.should_link && !is_cross;
let id_hash = link::crate_id_hash(&info.crate_id);
- let os = driver::get_os(driver::host_triple()).unwrap();
+ let os = config::get_os(driver::host_triple()).unwrap();
let mut load_ctxt = loader::Context {
sess: self.env.sess,
span: krate.span,
hash: None,
filesearch: self.env.sess.host_filesearch(),
triple: driver::host_triple(),
- os: session::sess_os_to_meta_os(os),
+ os: config::cfg_os_to_meta_os(os),
root: &None,
rejected_via_hash: vec!(),
rejected_via_triple: vec!(),
// try loading from target crates (only valid if there are
// no syntax extensions)
load_ctxt.triple = target_triple;
- load_ctxt.os = session::sess_os_to_meta_os(self.env.sess.targ_cfg.os);
+ load_ctxt.os = config::cfg_os_to_meta_os(self.env.sess.targ_cfg.os);
load_ctxt.filesearch = self.env.sess.target_filesearch();
let lib = load_ctxt.load_library_crate();
if decoder::get_macro_registrar_fn(lib.metadata.as_slice()).is_some() {
#![allow(non_camel_case_types)]
use back::svh::Svh;
-use driver::session;
+use driver::config;
use metadata::common::*;
use metadata::cstore;
use metadata::decoder;
fn encode_dylib_dependency_formats(ebml_w: &mut Encoder, ecx: &EncodeContext) {
ebml_w.start_tag(tag_dylib_dependency_formats);
- match ecx.tcx.dependency_formats.borrow().find(&session::CrateTypeDylib) {
+ match ecx.tcx.dependency_formats.borrow().find(&config::CrateTypeDylib) {
Some(arr) => {
let s = arr.iter().enumerate().filter_map(|(i, slot)| {
slot.map(|kind| format!("{}:{}", i + 1, match kind {
use syntax::ast;
use driver::session;
+use driver::config;
use metadata::cstore;
use metadata::csearch;
use middle::ty;
/// A mapping of all required dependencies for a particular flavor of output.
///
/// This is local to the tcx, and is generally relevant to one session.
-pub type Dependencies = HashMap<session::CrateType, DependencyList>;
+pub type Dependencies = HashMap<config::CrateType, DependencyList>;
pub fn calculate(tcx: &ty::ctxt) {
let mut fmts = tcx.dependency_formats.borrow_mut();
}
fn calculate_type(sess: &session::Session,
- ty: session::CrateType) -> DependencyList {
+ ty: config::CrateType) -> DependencyList {
match ty {
// If the global prefer_dynamic switch is turned off, first attempt
// static linkage (this can fail).
- session::CrateTypeExecutable if !sess.opts.cg.prefer_dynamic => {
+ config::CrateTypeExecutable if !sess.opts.cg.prefer_dynamic => {
match attempt_static(sess) {
Some(v) => return v,
None => {}
// No linkage happens with rlibs, we just needed the metadata (which we
// got long ago), so don't bother with anything.
- session::CrateTypeRlib => return Vec::new(),
+ config::CrateTypeRlib => return Vec::new(),
// Staticlibs must have all static dependencies. If any fail to be
// found, we generate some nice pretty errors.
- session::CrateTypeStaticlib => {
+ config::CrateTypeStaticlib => {
match attempt_static(sess) {
Some(v) => return v,
None => {}
}
// Everything else falls through below
- session::CrateTypeExecutable | session::CrateTypeDylib => {},
+ config::CrateTypeExecutable | config::CrateTypeDylib => {},
}
let mut formats = HashMap::new();
// except according to those terms.
-use driver::session;
+use driver::config;
use driver::session::Session;
use syntax::ast::{Crate, Name, NodeId, Item, ItemFn};
use syntax::ast_map;
pub fn find_entry_point(session: &Session, krate: &Crate, ast_map: &ast_map::Map) {
let any_exe = session.crate_types.borrow().iter().any(|ty| {
- *ty == session::CrateTypeExecutable
+ *ty == config::CrateTypeExecutable
});
if !any_exe {
// No need to find a main function
// If the user wants no main function at all, then stop here.
if attr::contains_name(krate.attrs.as_slice(), "no_main") {
- session.entry_type.set(Some(session::EntryNone));
+ session.entry_type.set(Some(config::EntryNone));
return
}
fn configure_main(this: &mut EntryContext) {
if this.start_fn.is_some() {
*this.session.entry_fn.borrow_mut() = this.start_fn;
- this.session.entry_type.set(Some(session::EntryStart));
+ this.session.entry_type.set(Some(config::EntryStart));
} else if this.attr_main_fn.is_some() {
*this.session.entry_fn.borrow_mut() = this.attr_main_fn;
- this.session.entry_type.set(Some(session::EntryMain));
+ this.session.entry_type.set(Some(config::EntryMain));
} else if this.main_fn.is_some() {
*this.session.entry_fn.borrow_mut() = this.main_fn;
- this.session.entry_type.set(Some(session::EntryMain));
+ this.session.entry_type.set(Some(config::EntryMain));
} else {
// No main function
this.session.err("main function not found");
// makes all other generics or inline functions that it references
// reachable as well.
-use driver::session;
+use driver::config;
use middle::ty;
use middle::typeck;
use middle::privacy;
// Creates a new reachability computation context.
fn new(tcx: &'a ty::ctxt) -> ReachableContext<'a> {
let any_library = tcx.sess.crate_types.borrow().iter().any(|ty| {
- *ty != session::CrateTypeExecutable
+ *ty != config::CrateTypeExecutable
});
ReachableContext {
tcx: tcx,
#![allow(non_camel_case_types)]
use back::abi;
-use driver::session::FullDebugInfo;
+use driver::config::FullDebugInfo;
use lib::llvm::{llvm, ValueRef, BasicBlockRef};
use middle::const_eval;
use middle::lang_items::{UniqStrEqFnLangItem, StrEqFnLangItem};
use back::link::{mangle_exported_name};
use back::{link, abi};
-use driver::session;
-use driver::session::{Session, NoDebugInfo, FullDebugInfo};
+use driver::config;
+use driver::config::{NoDebugInfo, FullDebugInfo};
+use driver::session::Session;
use driver::driver::OutputFilenames;
use driver::driver::{CrateAnalysis, CrateTranslation};
use lib::llvm::{ModuleRef, ValueRef, BasicBlockRef};
main_llfn: ValueRef) {
let et = ccx.sess().entry_type.get().unwrap();
match et {
- session::EntryMain => {
+ config::EntryMain => {
create_entry_fn(ccx, main_llfn, true);
}
- session::EntryStart => create_entry_fn(ccx, main_llfn, false),
- session::EntryNone => {} // Do nothing.
+ config::EntryStart => create_entry_fn(ccx, main_llfn, false),
+ config::EntryNone => {} // Do nothing.
}
fn create_entry_fn(ccx: &CrateContext,
use flate;
let any_library = cx.sess().crate_types.borrow().iter().any(|ty| {
- *ty != session::CrateTypeExecutable
+ *ty != config::CrateTypeExecutable
});
if !any_library {
return Vec::new()
use back::abi;
use back::link::mangle_internal_name_by_path_and_seq;
-use driver::session::FullDebugInfo;
+use driver::config::FullDebugInfo;
use lib::llvm::ValueRef;
use middle::freevars;
use middle::lang_items::ClosureExchangeMallocFnLangItem;
// except according to those terms.
-use driver::session::NoDebugInfo;
+use driver::config::NoDebugInfo;
use driver::session::Session;
use lib::llvm::{ContextRef, ModuleRef, ValueRef};
use lib::llvm::{llvm, TargetData, TypeNames};
// except according to those terms.
use lib::llvm::*;
-use driver::session::FullDebugInfo;
+use driver::config::FullDebugInfo;
use middle::lang_items::{FailFnLangItem, FailBoundsCheckFnLangItem};
use middle::trans::base::*;
use middle::trans::build::*;
*/
-use driver::session;
-use driver::session::{FullDebugInfo, LimitedDebugInfo, NoDebugInfo};
+use driver::config;
+use driver::config::{FullDebugInfo, LimitedDebugInfo, NoDebugInfo};
use lib::llvm::llvm;
use lib::llvm::{ModuleRef, ContextRef, ValueRef};
use lib::llvm::debuginfo::*;
true,
scope_line as c_uint,
FlagPrototyped as c_uint,
- cx.sess().opts.optimize != session::No,
+ cx.sess().opts.optimize != config::No,
llfn,
template_parameters,
ptr::null())
compile_unit_name,
work_dir,
producer,
- cx.sess().opts.optimize != session::No,
+ cx.sess().opts.optimize != config::No,
flags,
0,
split_name);
file_metadata,
loc.line as c_uint,
type_metadata,
- cx.sess().opts.optimize != session::No,
+ cx.sess().opts.optimize != config::No,
0,
argument_index)
}
#![allow(non_camel_case_types)]
-use driver::session;
+use driver::config;
use middle::resolve;
use middle::ty;
let tcx = ccx.tcx;
match *tcx.sess.entry_fn.borrow() {
Some((id, sp)) => match tcx.sess.entry_type.get() {
- Some(session::EntryMain) => check_main_fn_ty(ccx, id, sp),
- Some(session::EntryStart) => check_start_fn_ty(ccx, id, sp),
- Some(session::EntryNone) => {}
+ Some(config::EntryMain) => check_main_fn_ty(ccx, id, sp),
+ Some(config::EntryStart) => check_start_fn_ty(ccx, id, sp),
+ Some(config::EntryNone) => {}
None => tcx.sess.bug("entry function without a type")
},
None => {}
fn get_ast_and_resolve(cpath: &Path, libs: HashSet<Path>, cfgs: Vec<~str>)
-> (DocContext, CrateAnalysis) {
use syntax::codemap::dummy_spanned;
- use rustc::driver::driver::{FileInput, build_configuration,
+ use rustc::driver::driver::{FileInput,
phase_1_parse_input,
phase_2_configure_and_expand,
phase_3_run_analysis_passes};
+ use rustc::driver::config::build_configuration;
let input = FileInput(cpath.clone());
- let sessopts = driver::session::Options {
+ let sessopts = driver::config::Options {
maybe_sysroot: Some(os::self_exe_path().unwrap().dir_path()),
addl_lib_search_paths: RefCell::new(libs),
- crate_types: vec!(driver::session::CrateTypeDylib),
+ crate_types: vec!(driver::config::CrateTypeDylib),
lint_opts: vec!((lint::Warnings, lint::allow)),
- ..rustc::driver::session::basic_options().clone()
+ ..rustc::driver::config::basic_options().clone()
};
let span_diagnostic_handler =
syntax::diagnostic::mk_span_handler(diagnostic_handler, codemap);
- let sess = driver::driver::build_session_(sessopts,
- Some(cpath.clone()),
- span_diagnostic_handler);
+ let sess = driver::session::build_session_(sessopts,
+ Some(cpath.clone()),
+ span_diagnostic_handler);
let mut cfg = build_configuration(&sess);
for cfg_ in cfgs.move_iter() {
usage(args[0]);
return 0;
} else if matches.opt_present("version") {
- rustc::version(args[0]);
+ rustc::driver::version(args[0]);
return 0;
}
use collections::{HashSet, HashMap};
use testing;
use rustc::back::link;
+use rustc::driver::config;
use rustc::driver::driver;
use rustc::driver::session;
use rustc::metadata::creader::Loader;
let input_path = Path::new(input);
let input = driver::FileInput(input_path.clone());
- let sessopts = session::Options {
+ let sessopts = config::Options {
maybe_sysroot: Some(os::self_exe_path().unwrap().dir_path()),
addl_lib_search_paths: RefCell::new(libs.clone()),
- crate_types: vec!(session::CrateTypeDylib),
- ..session::basic_options().clone()
+ crate_types: vec!(config::CrateTypeDylib),
+ ..config::basic_options().clone()
};
let span_diagnostic_handler =
diagnostic::mk_span_handler(diagnostic_handler, codemap);
- let sess = driver::build_session_(sessopts,
+ let sess = session::build_session_(sessopts,
Some(input_path.clone()),
span_diagnostic_handler);
- let mut cfg = driver::build_configuration(&sess);
+ let mut cfg = config::build_configuration(&sess);
cfg.extend(cfgs.move_iter().map(|cfg_| {
let cfg_ = token::intern_and_get_ident(cfg_);
@dummy_spanned(ast::MetaWord(cfg_))
let test = maketest(test, cratename, loose_feature_gating);
let input = driver::StrInput(test);
- let sessopts = session::Options {
+ let sessopts = config::Options {
maybe_sysroot: Some(os::self_exe_path().unwrap().dir_path()),
addl_lib_search_paths: RefCell::new(libs),
- crate_types: vec!(session::CrateTypeExecutable),
+ crate_types: vec!(config::CrateTypeExecutable),
output_types: vec!(link::OutputTypeExe),
no_trans: no_run,
- cg: session::CodegenOptions {
+ cg: config::CodegenOptions {
prefer_dynamic: true,
- .. session::basic_codegen_options()
+ .. config::basic_codegen_options()
},
- ..session::basic_options().clone()
+ ..config::basic_options().clone()
};
// Shuffle around a few input and output handles here. We're going to pass
let span_diagnostic_handler =
diagnostic::mk_span_handler(diagnostic_handler, codemap);
- let sess = driver::build_session_(sessopts,
+ let sess = session::build_session_(sessopts,
None,
span_diagnostic_handler);
let outdir = TempDir::new("rustdoctest").expect("rustdoc needs a tempdir");
let out = Some(outdir.path().clone());
- let cfg = driver::build_configuration(&sess);
+ let cfg = config::build_configuration(&sess);
driver::compile_input(sess, cfg, &input, &out, &None);
if no_run { return }