2 use metadata::{creader, cstore, filesearch};
3 use session::{Session, Session_, OptLevel, No, Less, Default, Aggressive};
5 use syntax::{ast, codemap};
7 use middle::{trans, freevars, kind, ty, typeck, lint};
8 use syntax::print::{pp, pprust};
11 use result::{Ok, Err};
13 use std::getopts::{opt_present};
14 use std::getopts::groups;
15 use std::getopts::groups::{optopt, optmulti, optflag, optflagopt, getopts};
17 use back::{x86, x86_64};
18 use std::map::HashMap;
21 enum pp_mode {ppm_normal, ppm_expanded, ppm_typed, ppm_identified,
22 ppm_expanded_identified }
25 * The name used for source code that doesn't originate in a file
26 * (e.g. source from stdin or a string)
28 fn anon_src() -> ~str { ~"<anon>" }
30 fn source_name(input: input) -> ~str {
32 file_input(ifile) => ifile.to_str(),
33 str_input(_) => anon_src()
37 fn default_configuration(sess: Session, argv0: ~str, input: input) ->
39 let libc = match sess.targ_cfg.os {
40 session::os_win32 => ~"msvcrt.dll",
41 session::os_macos => ~"libc.dylib",
42 session::os_linux => ~"libc.so.6",
43 session::os_freebsd => ~"libc.so.7"
47 let mk = attr::mk_name_value_item_str;
49 let (arch,wordsz) = match sess.targ_cfg.arch {
50 session::arch_x86 => (~"x86",~"32"),
51 session::arch_x86_64 => (~"x86_64",~"64"),
52 session::arch_arm => (~"arm",~"32")
55 return ~[ // Target bindings.
56 attr::mk_word_item(os::family()),
57 mk(~"target_os", os::sysname()),
58 mk(~"target_family", os::family()),
59 mk(~"target_arch", arch),
60 mk(~"target_word_size", wordsz),
61 mk(~"target_libc", libc),
63 mk(~"build_compiler", argv0),
64 mk(~"build_input", source_name(input))];
67 fn append_configuration(cfg: ast::crate_cfg, name: ~str) -> ast::crate_cfg {
68 if attr::contains_name(cfg, name) {
71 return vec::append_one(cfg, attr::mk_word_item(name));
75 fn build_configuration(sess: Session, argv0: ~str, input: input) ->
77 // Combine the configuration requested by the session (command line) with
78 // some default and generated configuration items
79 let default_cfg = default_configuration(sess, argv0, input);
80 let user_cfg = sess.opts.cfg;
81 // If the user wants a test runner, then add the test cfg
82 let user_cfg = append_configuration(
84 if sess.opts.test { ~"test" } else { ~"notest" });
85 // If the user requested GC, then add the GC cfg
86 let user_cfg = append_configuration(
88 if sess.opts.gc { ~"gc" } else { ~"nogc" });
89 return vec::append(user_cfg, default_cfg);
92 // Convert strings provided as --cfg [cfgspec] into a crate_cfg
93 fn parse_cfgspecs(cfgspecs: ~[~str]) -> ast::crate_cfg {
94 // FIXME (#2399): It would be nice to use the parser to parse all
95 // varieties of meta_item here. At the moment we just support the
98 for cfgspecs.each |s| {
99 words.push(attr::mk_word_item(*s));
105 /// Load source from file
107 /// The string is the source
111 fn parse_input(sess: Session, cfg: ast::crate_cfg, input: input)
114 file_input(file) => {
115 parse::parse_crate_from_file(&file, cfg, sess.parse_sess)
118 // FIXME (#2319): Don't really want to box the source string
119 parse::parse_crate_from_source_str(
120 anon_src(), @src, cfg, sess.parse_sess)
125 fn time<T>(do_it: bool, what: ~str, thunk: fn() -> T) -> T {
126 if !do_it { return thunk(); }
127 let start = std::time::precise_time_s();
129 let end = std::time::precise_time_s();
130 io::stdout().write_str(fmt!("time: %3.3f s\t%s\n",
143 impl compile_upto : cmp::Eq {
144 pure fn eq(other: &compile_upto) -> bool {
145 (self as uint) == ((*other) as uint)
147 pure fn ne(other: &compile_upto) -> bool { !self.eq(other) }
150 fn compile_upto(sess: Session, cfg: ast::crate_cfg,
151 input: input, upto: compile_upto,
152 outputs: Option<output_filenames>)
153 -> {crate: @ast::crate, tcx: Option<ty::ctxt>} {
154 let time_passes = sess.time_passes();
155 let mut crate = time(time_passes, ~"parsing",
156 ||parse_input(sess, cfg, input) );
157 if upto == cu_parse { return {crate: crate, tcx: None}; }
159 sess.building_library = session::building_library(
160 sess.opts.crate_type, crate, sess.opts.test);
162 crate = time(time_passes, ~"configuration", ||
163 front::config::strip_unconfigured_items(crate));
165 crate = time(time_passes, ~"maybe building test harness", ||
166 front::test::modify_for_testing(sess, crate));
168 crate = time(time_passes, ~"expansion", ||
169 syntax::ext::expand::expand_crate(sess.parse_sess, cfg,
172 if upto == cu_expand { return {crate: crate, tcx: None}; }
174 crate = time(time_passes, ~"intrinsic injection", ||
175 front::intrinsic_inject::inject_intrinsic(sess, crate));
177 crate = time(time_passes, ~"core injection", ||
178 front::core_inject::maybe_inject_libcore_ref(sess, crate));
180 time(time_passes, ~"building lint settings table", ||
181 lint::build_settings_crate(sess, crate));
183 let ast_map = time(time_passes, ~"ast indexing", ||
184 syntax::ast_map::map_crate(sess.diagnostic(), *crate));
186 time(time_passes, ~"external crate/lib resolution", ||
187 creader::read_crates(sess.diagnostic(), *crate, sess.cstore,
189 session::sess_os_to_meta_os(sess.targ_cfg.os),
191 sess.parse_sess.interner));
193 let lang_items = time(time_passes, ~"language item collection", ||
194 middle::lang_items::collect_language_items(crate, sess));
196 let { def_map: def_map,
198 trait_map: trait_map } =
199 time(time_passes, ~"resolution", ||
200 middle::resolve::resolve_crate(sess, lang_items, crate));
202 let freevars = time(time_passes, ~"freevar finding", ||
203 freevars::annotate_freevars(def_map, crate));
205 let region_map = time(time_passes, ~"region resolution", ||
206 middle::region::resolve_crate(sess, def_map, crate));
208 let rp_set = time(time_passes, ~"region parameterization inference", ||
209 middle::region::determine_rp_in_crate(sess, ast_map, def_map, crate));
212 let outputs = outputs.get();
214 let (llmod, link_meta) = {
216 let ty_cx = ty::mk_ctxt(sess, def_map, ast_map, freevars,
217 region_map, rp_set, move lang_items, crate);
219 let (method_map, vtable_map) =
220 time(time_passes, ~"typechecking", ||
221 typeck::check_crate(ty_cx,
225 // These next two const passes can probably be merged
226 time(time_passes, ~"const marking", ||
227 middle::const_eval::process_crate(crate, def_map, ty_cx));
229 time(time_passes, ~"const checking", ||
230 middle::check_const::check_crate(sess, crate, ast_map, def_map,
233 if upto == cu_typeck { return {crate: crate, tcx: Some(ty_cx)}; }
235 time(time_passes, ~"privacy checking", ||
236 middle::privacy::check_crate(ty_cx, &method_map, crate));
238 time(time_passes, ~"loop checking", ||
239 middle::check_loop::check_crate(ty_cx, crate));
241 time(time_passes, ~"alt checking", ||
242 middle::check_alt::check_crate(ty_cx, crate));
245 time(time_passes, ~"liveness checking", ||
246 middle::liveness::check_crate(ty_cx, method_map, crate));
248 let (root_map, mutbl_map) =
249 time(time_passes, ~"borrow checking", ||
250 middle::borrowck::check_crate(ty_cx, method_map,
251 last_use_map, crate));
253 time(time_passes, ~"kind checking", ||
254 kind::check_crate(ty_cx, method_map, last_use_map, crate));
256 time(time_passes, ~"lint checking", ||
257 lint::check_crate(ty_cx, crate));
259 if upto == cu_no_trans { return {crate: crate, tcx: Some(ty_cx)}; }
261 let maps = {mutbl_map: mutbl_map,
263 last_use_map: last_use_map,
264 method_map: method_map,
265 vtable_map: vtable_map};
267 time(time_passes, ~"translation", ||
268 trans::base::trans_crate(sess, crate, ty_cx,
269 &outputs.obj_filename,
275 time(time_passes, ~"LLVM passes", ||
276 link::write::run_passes(sess, llmod,
277 &outputs.obj_filename));
279 let stop_after_codegen =
280 sess.opts.output_type != link::output_type_exe ||
281 (sess.opts.static && sess.building_library) ||
284 if stop_after_codegen { return {crate: crate, tcx: None}; }
286 time(time_passes, ~"linking", ||
287 link::link_binary(sess,
288 &outputs.obj_filename,
289 &outputs.out_filename, link_meta));
291 return {crate: crate, tcx: None};
294 fn compile_input(sess: Session, cfg: ast::crate_cfg, input: input,
295 outdir: &Option<Path>, output: &Option<Path>) {
297 let upto = if sess.opts.parse_only { cu_parse }
298 else if sess.opts.no_trans { cu_no_trans }
299 else { cu_everything };
300 let outputs = build_output_filenames(input, outdir, output, sess);
301 compile_upto(sess, cfg, input, upto, Some(outputs));
304 fn pretty_print_input(sess: Session, cfg: ast::crate_cfg, input: input,
306 fn ann_paren_for_expr(node: pprust::ann_node) {
308 pprust::node_expr(s, _) => pprust::popen(s),
312 fn ann_typed_post(tcx: ty::ctxt, node: pprust::ann_node) {
314 pprust::node_expr(s, expr) => {
316 pp::word(s.s, ~"as");
318 pp::word(s.s, ppaux::ty_to_str(tcx, ty::expr_ty(tcx, expr)));
324 fn ann_identified_post(node: pprust::ann_node) {
326 pprust::node_item(s, item) => {
328 pprust::synth_comment(s, int::to_str(item.id, 10u));
330 pprust::node_block(s, blk) => {
332 pprust::synth_comment(s,
333 ~"block " + int::to_str(blk.node.id, 10u));
335 pprust::node_expr(s, expr) => {
337 pprust::synth_comment(s, int::to_str(expr.id, 10u));
340 pprust::node_pat(s, pat) => {
342 pprust::synth_comment(s, ~"pat " + int::to_str(pat.id, 10u));
347 // Because the pretty printer needs to make a pass over the source
348 // to collect comments and literals, and we need to support reading
349 // from stdin, we're going to just suck the source into a string
350 // so both the parser and pretty-printer can use it.
351 let upto = match ppm {
352 ppm_expanded | ppm_expanded_identified => cu_expand,
353 ppm_typed => cu_typeck,
356 let {crate, tcx} = compile_upto(sess, cfg, input, upto, None);
358 let ann = match ppm {
360 {pre: ann_paren_for_expr,
361 post: |a| ann_typed_post(tcx.get(), a) }
363 ppm_identified | ppm_expanded_identified => {
364 {pre: ann_paren_for_expr, post: ann_identified_post}
366 ppm_expanded | ppm_normal => pprust::no_ann()
368 let is_expanded = upto != cu_parse;
369 let src = sess.codemap.get_filemap(source_name(input)).src;
370 do io::with_str_reader(*src) |rdr| {
371 pprust::print_crate(sess.codemap, sess.parse_sess.interner,
372 sess.span_diagnostic, crate,
374 rdr, io::stdout(), ann, is_expanded);
378 fn get_os(triple: ~str) -> Option<session::os> {
379 if str::contains(triple, ~"win32") ||
380 str::contains(triple, ~"mingw32") {
381 Some(session::os_win32)
382 } else if str::contains(triple, ~"darwin") {
383 Some(session::os_macos)
384 } else if str::contains(triple, ~"linux") {
385 Some(session::os_linux)
386 } else if str::contains(triple, ~"freebsd") {
387 Some(session::os_freebsd)
391 fn get_arch(triple: ~str) -> Option<session::arch> {
392 if str::contains(triple, ~"i386") ||
393 str::contains(triple, ~"i486") ||
394 str::contains(triple, ~"i586") ||
395 str::contains(triple, ~"i686") ||
396 str::contains(triple, ~"i786") {
397 Some(session::arch_x86)
398 } else if str::contains(triple, ~"x86_64") {
399 Some(session::arch_x86_64)
400 } else if str::contains(triple, ~"arm") ||
401 str::contains(triple, ~"xscale") {
402 Some(session::arch_arm)
406 fn build_target_config(sopts: @session::options,
407 demitter: diagnostic::emitter) -> @session::config {
408 let os = match get_os(sopts.target_triple) {
410 None => early_error(demitter, ~"unknown operating system")
412 let arch = match get_arch(sopts.target_triple) {
414 None => early_error(demitter,
415 ~"unknown architecture: " + sopts.target_triple)
417 let (int_type, uint_type, float_type) = match arch {
418 session::arch_x86 => (ast::ty_i32, ast::ty_u32, ast::ty_f64),
419 session::arch_x86_64 => (ast::ty_i64, ast::ty_u64, ast::ty_f64),
420 session::arch_arm => (ast::ty_i32, ast::ty_u32, ast::ty_f64)
422 let target_strs = match arch {
423 session::arch_x86 => x86::get_target_strs(os),
424 session::arch_x86_64 => x86_64::get_target_strs(os),
425 session::arch_arm => x86::get_target_strs(os)
427 let target_cfg: @session::config =
428 @{os: os, arch: arch, target_strs: target_strs, int_type: int_type,
429 uint_type: uint_type, float_type: float_type};
433 fn host_triple() -> ~str {
434 // Get the host triple out of the build environment. This ensures that our
435 // idea of the host triple is the same as for the set of libraries we've
436 // actually built. We can't just take LLVM's host triple because they
437 // normalize all ix86 architectures to i386.
439 // FIXME (#2400): Instead of grabbing the host triple we really should
440 // be grabbing (at compile time) the target triple that this rustc is
441 // built with and calling that (at runtime) the host triple.
442 let ht = env!("CFG_HOST_TRIPLE");
443 return if ht != ~"" {
446 fail ~"rustc built without CFG_HOST_TRIPLE"
450 fn build_session_options(binary: ~str,
451 matches: getopts::Matches,
452 demitter: diagnostic::emitter) -> @session::options {
453 let crate_type = if opt_present(matches, ~"lib") {
455 } else if opt_present(matches, ~"bin") {
458 session::unknown_crate
460 let static = opt_present(matches, ~"static");
461 let gc = opt_present(matches, ~"gc");
463 let parse_only = opt_present(matches, ~"parse-only");
464 let no_trans = opt_present(matches, ~"no-trans");
466 let lint_levels = [lint::allow, lint::warn,
467 lint::deny, lint::forbid];
468 let mut lint_opts = ~[];
469 let lint_dict = lint::get_lint_dict();
470 for lint_levels.each |level| {
471 let level_name = lint::level_to_str(*level);
472 let level_short = level_name.substr(0,1).to_upper();
473 let flags = vec::append(getopts::opt_strs(matches, level_short),
474 getopts::opt_strs(matches, level_name));
475 for flags.each |lint_name| {
476 let lint_name = str::replace(*lint_name, ~"-", ~"_");
477 match lint_dict.find(lint_name) {
479 early_error(demitter, fmt!("unknown %s flag: %s",
480 level_name, lint_name));
483 lint_opts.push((lint.lint, *level));
489 let mut debugging_opts = 0u;
490 let debug_flags = getopts::opt_strs(matches, ~"Z");
491 let debug_map = session::debugging_opts_map();
492 for debug_flags.each |debug_flag| {
493 let mut this_bit = 0u;
494 for debug_map.each |pair| {
495 let (name, _, bit) = *pair;
496 if name == *debug_flag { this_bit = bit; break; }
499 early_error(demitter, fmt!("unknown debug flag: %s", *debug_flag))
501 debugging_opts |= this_bit;
503 if debugging_opts & session::debug_llvm != 0 {
504 llvm::LLVMSetDebug(1);
507 let jit = opt_present(matches, ~"jit");
509 if parse_only || no_trans {
510 link::output_type_none
511 } else if opt_present(matches, ~"S") &&
512 opt_present(matches, ~"emit-llvm") {
513 link::output_type_llvm_assembly
514 } else if opt_present(matches, ~"S") {
515 link::output_type_assembly
516 } else if opt_present(matches, ~"c") {
517 link::output_type_object
518 } else if opt_present(matches, ~"emit-llvm") {
519 link::output_type_bitcode
520 } else { link::output_type_exe };
521 let extra_debuginfo = opt_present(matches, ~"xg");
522 let debuginfo = opt_present(matches, ~"g") || extra_debuginfo;
523 let sysroot_opt = getopts::opt_maybe_str(matches, ~"sysroot");
524 let sysroot_opt = sysroot_opt.map(|m| Path(*m));
525 let target_opt = getopts::opt_maybe_str(matches, ~"target");
526 let save_temps = getopts::opt_present(matches, ~"save-temps");
528 // unless we're emitting huamn-readable assembly, omit comments.
529 link::output_type_llvm_assembly | link::output_type_assembly => (),
530 _ => debugging_opts |= session::no_asm_comments
533 if (debugging_opts & session::no_opt) != 0 {
535 } else if opt_present(matches, ~"O") {
536 if opt_present(matches, ~"opt-level") {
537 early_error(demitter, ~"-O and --opt-level both provided");
540 } else if opt_present(matches, ~"opt-level") {
541 match getopts::opt_str(matches, ~"opt-level") {
547 early_error(demitter, ~"optimization level needs " +
548 ~"to be between 0-3")
555 None => host_triple(),
559 let addl_lib_search_paths =
560 getopts::opt_strs(matches, ~"L")
562 let cfg = parse_cfgspecs(getopts::opt_strs(matches, ~"cfg"));
563 let test = opt_present(matches, ~"test");
564 let sopts: @session::options =
565 @{crate_type: crate_type,
569 debuginfo: debuginfo,
570 extra_debuginfo: extra_debuginfo,
571 lint_opts: lint_opts,
572 save_temps: save_temps,
574 output_type: output_type,
575 addl_lib_search_paths: addl_lib_search_paths,
576 maybe_sysroot: sysroot_opt,
577 target_triple: target,
581 parse_only: parse_only,
583 debugging_opts: debugging_opts};
587 fn build_session(sopts: @session::options,
588 demitter: diagnostic::emitter) -> Session {
589 let codemap = @codemap::CodeMap::new();
590 let diagnostic_handler =
591 diagnostic::mk_handler(Some(demitter));
592 let span_diagnostic_handler =
593 diagnostic::mk_span_handler(diagnostic_handler, codemap);
594 build_session_(sopts, codemap, demitter, span_diagnostic_handler)
597 fn build_session_(sopts: @session::options,
598 cm: @codemap::CodeMap,
599 demitter: diagnostic::emitter,
600 span_diagnostic_handler: diagnostic::span_handler)
602 let target_cfg = build_target_config(sopts, demitter);
603 let p_s = parse::new_parse_sess_special_handler(span_diagnostic_handler,
605 let cstore = cstore::mk_cstore(p_s.interner);
606 let filesearch = filesearch::mk_filesearch(
609 sopts.addl_lib_search_paths);
610 let lint_settings = lint::mk_lint_settings();
611 Session_(@{targ_cfg: target_cfg,
616 // For a library crate, this is always none
618 span_diagnostic: span_diagnostic_handler,
619 filesearch: filesearch,
620 mut building_library: false,
621 working_dir: os::getcwd(),
622 lint_settings: lint_settings})
625 fn parse_pretty(sess: Session, &&name: ~str) -> pp_mode {
627 ~"normal" => ppm_normal,
628 ~"expanded" => ppm_expanded,
629 ~"typed" => ppm_typed,
630 ~"expanded,identified" => ppm_expanded_identified,
631 ~"identified" => ppm_identified,
633 sess.fatal(~"argument to `pretty` must be one of `normal`, \
634 `expanded`, `typed`, `identified`, \
635 or `expanded,identified`");
640 // rustc command line options
641 fn optgroups() -> ~[getopts::groups::OptGroup] {
643 optflag(~"", ~"bin", ~"Compile an executable crate (default)"),
644 optflag(~"c", ~"", ~"Compile and assemble, but do not link"),
645 optmulti(~"", ~"cfg", ~"Configure the compilation
646 environment", ~"SPEC"),
647 optflag(~"", ~"emit-llvm",
648 ~"Produce an LLVM bitcode file"),
649 optflag(~"g", ~"", ~"Produce debug info (experimental)"),
650 optflag(~"", ~"gc", ~"Garbage collect shared data (experimental)"),
651 optflag(~"h", ~"help",~"Display this message"),
652 optmulti(~"L", ~"", ~"Add a directory to the library search path",
654 optflag(~"", ~"lib", ~"Compile a library crate"),
655 optflag(~"", ~"ls", ~"List the symbols defined by a library crate"),
656 optflag(~"", ~"jit", ~"Execute using JIT (experimental)"),
657 optflag(~"", ~"no-trans",
658 ~"Run all passes except translation; no output"),
659 optflag(~"O", ~"", ~"Equivalent to --opt-level=2"),
660 optopt(~"o", ~"", ~"Write output to <filename>", ~"FILENAME"),
661 optopt(~"", ~"opt-level",
662 ~"Optimize with possible levels 0-3", ~"LEVEL"),
663 optopt( ~"", ~"out-dir",
664 ~"Write output to compiler-chosen filename
666 optflag(~"", ~"parse-only",
667 ~"Parse only; do not compile, assemble, or link"),
668 optflagopt(~"", ~"pretty",
669 ~"Pretty-print the input instead of compiling;
670 valid types are: normal (un-annotated source),
671 expanded (crates expanded),
672 typed (crates expanded, with type annotations),
673 or identified (fully parenthesized,
674 AST nodes and blocks with IDs)", ~"TYPE"),
675 optflag(~"S", ~"", ~"Compile only; do not assemble or link"),
676 optflag(~"", ~"xg", ~"Extra debugging info (experimental)"),
677 optflag(~"", ~"save-temps",
678 ~"Write intermediate files (.bc, .opt.bc, .o)
679 in addition to normal output"),
680 optflag(~"", ~"static",
681 ~"Use or produce static libraries or binaries
683 optopt(~"", ~"sysroot",
684 ~"Override the system root", ~"PATH"),
685 optflag(~"", ~"test", ~"Build a test harness"),
686 optopt(~"", ~"target",
687 ~"Target triple cpu-manufacturer-kernel[-os]
689 http://sources.redhat.com/autobook/autobook/autobook_17.html
690 for detail)", ~"TRIPLE"),
691 optmulti(~"W", ~"warn",
692 ~"Set lint warnings", ~"OPT"),
693 optmulti(~"A", ~"allow",
694 ~"Set lint allowed", ~"OPT"),
695 optmulti(~"D", ~"deny",
696 ~"Set lint denied", ~"OPT"),
697 optmulti(~"F", ~"forbid",
698 ~"Set lint forbidden", ~"OPT"),
699 optmulti(~"Z", ~"", ~"Set internal debugging options", "FLAG"),
700 optflag( ~"v", ~"version",
701 ~"Print version info and exit"),
705 type output_filenames = @{out_filename:Path, obj_filename:Path};
707 fn build_output_filenames(input: input,
709 ofile: &Option<Path>,
711 -> output_filenames {
714 let sopts = sess.opts;
715 let stop_after_codegen =
716 sopts.output_type != link::output_type_exe ||
717 sopts.static && sess.building_library;
721 match sopts.output_type {
722 link::output_type_none => ~"none",
723 link::output_type_bitcode => ~"bc",
724 link::output_type_assembly => ~"s",
725 link::output_type_llvm_assembly => ~"ll",
726 // Object and exe output both use the '.o' extension here
727 link::output_type_object | link::output_type_exe => ~"o"
732 // "-" as input file will cause the parser to read from stdin so we
733 // have to make up a name
734 // We want to toss everything after the final '.'
735 let dirpath = match *odir {
737 None => match input {
738 str_input(_) => os::getcwd(),
739 file_input(ifile) => ifile.dir_path()
743 let stem = match input {
744 file_input(ifile) => ifile.filestem().get(),
745 str_input(_) => ~"rust_out"
748 if sess.building_library {
749 out_path = dirpath.push(os::dll_filename(stem));
750 obj_path = dirpath.push(stem).with_filetype(obj_suffix);
752 out_path = dirpath.push(stem);
753 obj_path = dirpath.push(stem).with_filetype(obj_suffix);
759 obj_path = if stop_after_codegen {
762 out_file.with_filetype(obj_suffix)
765 if sess.building_library {
766 // FIXME (#2401): We might want to warn here; we're actually not
767 // going to respect the user's choice of library name when it
768 // comes time to link, we'll be linking to
769 // lib<basename>-<hash>-<version>.so no matter what.
773 sess.warn(~"ignoring --out-dir flag due to -o flag.");
777 return @{out_filename: out_path,
778 obj_filename: obj_path};
781 fn early_error(emitter: diagnostic::emitter, msg: ~str) -> ! {
782 emitter(None, msg, diagnostic::fatal);
786 fn list_metadata(sess: Session, path: &Path, out: io::Writer) {
787 metadata::loader::list_file_metadata(
788 sess.parse_sess.interner,
789 session::sess_os_to_meta_os(sess.targ_cfg.os), path, out);
796 // When the user supplies --test we should implicitly supply --cfg test
798 fn test_switch_implies_cfg_test() {
800 match getopts(~[~"--test"], optgroups()) {
802 Err(f) => fail ~"test_switch_implies_cfg_test: " +
805 let sessopts = build_session_options(
806 ~"rustc", matches, diagnostic::emit);
807 let sess = build_session(sessopts, diagnostic::emit);
808 let cfg = build_configuration(sess, ~"whatever", str_input(~""));
809 assert (attr::contains_name(cfg, ~"test"));
812 // When the user supplies --test and --cfg test, don't implicitly add
813 // another --cfg test
815 fn test_switch_implies_cfg_test_unless_cfg_test() {
817 match getopts(~[~"--test", ~"--cfg=test"], optgroups()) {
820 fail ~"test_switch_implies_cfg_test_unless_cfg_test: " +
821 getopts::fail_str(f);
824 let sessopts = build_session_options(
825 ~"rustc", matches, diagnostic::emit);
826 let sess = build_session(sessopts, diagnostic::emit);
827 let cfg = build_configuration(sess, ~"whatever", str_input(~""));
828 let test_items = attr::find_meta_items_by_name(cfg, ~"test");
829 assert (vec::len(test_items) == 1u);
836 // indent-tabs-mode: nil
838 // buffer-file-coding-system: utf-8-unix