From 2e2501b199a34f561d23237d98196946ff0dad33 Mon Sep 17 00:00:00 2001 From: bjorn3 Date: Sun, 18 Jun 2017 16:05:42 +0200 Subject: [PATCH] Make rustc compile without LLVM Doesn't yet compile when `llvm-enabled = false` due to crate metadata loading needing LLVM --- src/librustc_driver/Cargo.toml | 5 +- src/librustc_driver/driver.rs | 90 ++++++++++------ src/librustc_driver/lib.rs | 52 +++++++-- src/librustc_driver/target_features.rs | 2 + src/librustc_driver/test.rs | 2 + src/librustc_trans/back/link.rs | 129 ++--------------------- src/librustc_trans/back/no_llvm_link.rs | 133 ++++++++++++++++++++++++ src/librustdoc/html/markdown.rs | 1 + src/librustdoc/lib.rs | 1 + src/librustdoc/markdown.rs | 1 + src/rustc/Cargo.toml | 1 + 11 files changed, 255 insertions(+), 162 deletions(-) create mode 100644 src/librustc_trans/back/no_llvm_link.rs diff --git a/src/librustc_driver/Cargo.toml b/src/librustc_driver/Cargo.toml index 2e949f48c175e..48cf20d35af5f 100644 --- a/src/librustc_driver/Cargo.toml +++ b/src/librustc_driver/Cargo.toml @@ -29,9 +29,12 @@ rustc_plugin = { path = "../librustc_plugin" } rustc_privacy = { path = "../librustc_privacy" } rustc_resolve = { path = "../librustc_resolve" } rustc_save_analysis = { path = "../librustc_save_analysis" } -rustc_trans = { path = "../librustc_trans" } +rustc_trans = { path = "../librustc_trans", optional=true } rustc_typeck = { path = "../librustc_typeck" } serialize = { path = "../libserialize" } syntax = { path = "../libsyntax" } syntax_ext = { path = "../libsyntax_ext" } syntax_pos = { path = "../libsyntax_pos" } + +[features] +llvm = ["rustc_trans"] diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index 159fee6aa4c92..5e3ad1df848c8 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -31,7 +31,11 @@ use rustc_incremental::{self, IncrementalHashesMap}; use rustc_resolve::{MakeGlobMap, Resolver}; use rustc_metadata::creader::CrateLoader; use rustc_metadata::cstore::{self, CStore}; +#[cfg(feature="llvm")] use rustc_trans::back::{link, write}; +#[cfg(not(feature="llvm"))] +use ::link; +#[cfg(feature="llvm")] use rustc_trans as trans; use rustc_typeck as typeck; use rustc_privacy; @@ -111,7 +115,7 @@ pub fn compile_input(sess: &Session, }; let outputs = build_output_filenames(input, outdir, output, &krate.attrs, sess); - let crate_name = link::find_crate_name(Some(sess), &krate.attrs, input); + let crate_name: String = link::find_crate_name(Some(sess), &krate.attrs, input); let ExpansionResult { expanded_crate, defs, analysis, resolutions, mut hir_forest } = { phase_2_configure_and_expand( sess, &cstore, krate, registry, &crate_name, addl_plugins, control.make_glob_map, @@ -204,22 +208,29 @@ pub fn compile_input(sess: &Session, println!("Pre-trans"); tcx.print_debug_stats(); } - let trans = phase_4_translate_to_llvm(tcx, analysis, &incremental_hashes_map, - &outputs); - if log_enabled!(::log::LogLevel::Info) { - println!("Post-trans"); - tcx.print_debug_stats(); - } + #[cfg(feature="llvm")] + { + let trans = phase_4_translate_to_llvm(tcx, analysis, &incremental_hashes_map, + &outputs); + + if log_enabled!(::log::LogLevel::Info) { + println!("Post-trans"); + tcx.print_debug_stats(); + } - if tcx.sess.opts.output_types.contains_key(&OutputType::Mir) { - if let Err(e) = mir::transform::dump_mir::emit_mir(tcx, &outputs) { - sess.err(&format!("could not emit MIR: {}", e)); - sess.abort_if_errors(); + if tcx.sess.opts.output_types.contains_key(&OutputType::Mir) { + if let Err(e) = mir::transform::dump_mir::emit_mir(tcx, &outputs) { + sess.err(&format!("could not emit MIR: {}", e)); + sess.abort_if_errors(); + } } + + return Ok((outputs, trans)) } - Ok((outputs, trans)) + #[cfg(not(feature="llvm"))] + panic!("Unreachable") })?? }; @@ -227,32 +238,41 @@ pub fn compile_input(sess: &Session, sess.code_stats.borrow().print_type_sizes(); } - let phase5_result = phase_5_run_llvm_passes(sess, &trans, &outputs); + #[cfg(feature="llvm")] + { + let phase5_result = phase_5_run_llvm_passes(sess, &trans, &outputs); - controller_entry_point!(after_llvm, - sess, - CompileState::state_after_llvm(input, sess, outdir, output, &trans), - phase5_result); - phase5_result?; + controller_entry_point!(after_llvm, + sess, + CompileState::state_after_llvm(input, sess, outdir, output, &trans), + phase5_result); + phase5_result?; - write::cleanup_llvm(&trans); + write::cleanup_llvm(&trans); - phase_6_link_output(sess, &trans, &outputs); + phase_6_link_output(sess, &trans, &outputs); - // Now that we won't touch anything in the incremental compilation directory - // any more, we can finalize it (which involves renaming it) - rustc_incremental::finalize_session_directory(sess, trans.link.crate_hash); + // Now that we won't touch anything in the incremental compilation directory + // any more, we can finalize it (which involves renaming it) + rustc_incremental::finalize_session_directory(sess, trans.link.crate_hash); - if sess.opts.debugging_opts.perf_stats { - sess.print_perf_stats(); - } + if sess.opts.debugging_opts.perf_stats { + sess.print_perf_stats(); + } + + controller_entry_point!(compilation_done, + sess, + CompileState::state_when_compilation_done(input, + sess, + outdir, + output), + Ok(())); - controller_entry_point!(compilation_done, - sess, - CompileState::state_when_compilation_done(input, sess, outdir, output), - Ok(())); + return Ok(()) + } - Ok(()) + #[cfg(not(feature="llvm"))] + panic!("Unreachable") } fn keep_hygiene_data(sess: &Session) -> bool { @@ -355,6 +375,7 @@ pub struct CompileState<'a, 'tcx: 'a> { pub resolutions: Option<&'a Resolutions>, pub analysis: Option<&'a ty::CrateAnalysis>, pub tcx: Option>, + #[cfg(feature="llvm")] pub trans: Option<&'a trans::CrateTranslation>, } @@ -381,6 +402,7 @@ impl<'a, 'tcx> CompileState<'a, 'tcx> { resolutions: None, analysis: None, tcx: None, + #[cfg(feature="llvm")] trans: None, } } @@ -470,6 +492,7 @@ impl<'a, 'tcx> CompileState<'a, 'tcx> { } + #[cfg(feature="llvm")] fn state_after_llvm(input: &'a Input, session: &'tcx Session, out_dir: &'a Option, @@ -893,6 +916,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session, mir::provide(&mut local_providers); reachable::provide(&mut local_providers); rustc_privacy::provide(&mut local_providers); + #[cfg(feature="llvm")] trans::provide(&mut local_providers); typeck::provide(&mut local_providers); ty::provide(&mut local_providers); @@ -904,6 +928,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session, let mut extern_providers = ty::maps::Providers::default(); cstore::provide(&mut extern_providers); + #[cfg(feature="llvm")] trans::provide(&mut extern_providers); ty::provide_extern(&mut extern_providers); traits::provide_extern(&mut extern_providers); @@ -1045,6 +1070,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session, /// Run the translation phase to LLVM, after which the AST and analysis can /// be discarded. +#[cfg(feature="llvm")] pub fn phase_4_translate_to_llvm<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, analysis: ty::CrateAnalysis, incremental_hashes_map: &IncrementalHashesMap, @@ -1076,6 +1102,7 @@ pub fn phase_4_translate_to_llvm<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, /// Run LLVM itself, producing a bitcode file, assembly file or object file /// as a side effect. +#[cfg(feature="llvm")] pub fn phase_5_run_llvm_passes(sess: &Session, trans: &trans::CrateTranslation, outputs: &OutputFilenames) -> CompileResult { @@ -1124,6 +1151,7 @@ pub fn phase_5_run_llvm_passes(sess: &Session, /// Run the linker on any artifacts that resulted from the LLVM run. /// This should produce either a finished executable or library. +#[cfg(feature="llvm")] pub fn phase_6_link_output(sess: &Session, trans: &trans::CrateTranslation, outputs: &OutputFilenames) { diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index b4a4aaaaf5c81..225456e6389c2 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -48,6 +48,7 @@ extern crate rustc_metadata; extern crate rustc_mir; extern crate rustc_resolve; extern crate rustc_save_analysis; +#[cfg(feature="llvm")] extern crate rustc_trans; extern crate rustc_typeck; extern crate serialize; @@ -63,7 +64,9 @@ use pretty::{PpMode, UserIdentifiedItem}; use rustc_resolve as resolve; use rustc_save_analysis as save; use rustc_save_analysis::DumpHandler; +#[cfg(feature="llvm")] use rustc_trans::back::link; +#[cfg(feature="llvm")] use rustc_trans::back::write::{RELOC_MODEL_ARGS, CODE_GEN_MODEL_ARGS}; use rustc::dep_graph::DepGraph; use rustc::session::{self, config, Session, build_session, CompileResult}; @@ -175,6 +178,7 @@ pub fn run_compiler<'a>(args: &[String], let (sopts, cfg) = config::build_session_options_and_crate_config(&matches); if sopts.debugging_opts.debug_llvm { + #[cfg(feature="llvm")] rustc_trans::enable_llvm_debug(); } @@ -204,6 +208,7 @@ pub fn run_compiler<'a>(args: &[String], let mut sess = session::build_session_with_codemap( sopts, &dep_graph, input_file_path, descriptions, cstore.clone(), codemap, emitter_dest, ); + #[cfg(feature="llvm")] rustc_trans::init(&sess); rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess)); @@ -409,6 +414,7 @@ impl<'a> CompilerCalls<'a> for RustcDefaultCalls { None, descriptions.clone(), cstore.clone()); + #[cfg(feature="llvm")] rustc_trans::init(&sess); rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess)); let mut cfg = config::build_configuration(&sess, cfg.clone()); @@ -607,7 +613,7 @@ impl RustcDefaultCalls { }; let attrs = attrs.as_ref().unwrap(); let t_outputs = driver::build_output_filenames(input, odir, ofile, attrs, sess); - let id = link::find_crate_name(Some(sess), attrs, input); + let id: String = link::find_crate_name(Some(sess), attrs, input); if *req == PrintRequest::CrateName { println!("{}", id); continue; @@ -662,20 +668,36 @@ impl RustcDefaultCalls { } } PrintRequest::RelocationModels => { - println!("Available relocation models:"); - for &(name, _) in RELOC_MODEL_ARGS.iter() { - println!(" {}", name); + #[cfg(not(feature="llvm"))] + panic!("LLVM is not enabled for this rustc version"); + + #[cfg(feature="llvm")] + { + println!("Available relocation models:"); + for &(name, _) in RELOC_MODEL_ARGS.iter() { + println!(" {}", name); + } + println!(""); } - println!(""); } PrintRequest::CodeModels => { - println!("Available code models:"); - for &(name, _) in CODE_GEN_MODEL_ARGS.iter(){ - println!(" {}", name); + #[cfg(not(feature="llvm"))] + panic!("LLVM is not enabled for this rustc version"); + + #[cfg(feature="llvm")] + { + println!("Available code models:"); + for &(name, _) in CODE_GEN_MODEL_ARGS.iter(){ + println!(" {}", name); + } + println!(""); } - println!(""); } PrintRequest::TargetCPUs | PrintRequest::TargetFeatures => { + #[cfg(not(feature="llvm"))] + panic!("LLVM is not enabled for this rustc version"); + + #[cfg(feature="llvm")] rustc_trans::print(*req, sess); } } @@ -715,6 +737,7 @@ pub fn version(binary: &str, matches: &getopts::Matches) { println!("commit-date: {}", unw(commit_date_str())); println!("host: {}", config::host_triple()); println!("release: {}", unw(release_str())); + #[cfg(feature="llvm")] rustc_trans::print_version(); } } @@ -1008,6 +1031,10 @@ pub fn handle_options(args: &[String]) -> Option { } if cg_flags.contains(&"passes=list".to_string()) { + #[cfg(not(feature="llvm"))] + panic!("LLVM is not enabled for this rustc version"); + + #[cfg(feature="llvm")] rustc_trans::print_passes(); return None; } @@ -1135,6 +1162,7 @@ pub fn diagnostics_registry() -> errors::registry::Registry { all_errors.extend_from_slice(&rustc_borrowck::DIAGNOSTICS); all_errors.extend_from_slice(&rustc_resolve::DIAGNOSTICS); all_errors.extend_from_slice(&rustc_privacy::DIAGNOSTICS); + #[cfg(feature="llvm")] all_errors.extend_from_slice(&rustc_trans::DIAGNOSTICS); all_errors.extend_from_slice(&rustc_const_eval::DIAGNOSTICS); all_errors.extend_from_slice(&rustc_metadata::DIAGNOSTICS); @@ -1159,3 +1187,9 @@ pub fn main() { None)); process::exit(result as i32); } + + +#[cfg(not(feature="llvm"))] +mod link { + include!("../librustc_trans/back/no_llvm_link.rs"); +} diff --git a/src/librustc_driver/target_features.rs b/src/librustc_driver/target_features.rs index bee61bb398029..e91e251d65d7e 100644 --- a/src/librustc_driver/target_features.rs +++ b/src/librustc_driver/target_features.rs @@ -11,6 +11,7 @@ use syntax::ast; use rustc::session::Session; use syntax::symbol::Symbol; +#[cfg(feature="llvm")] use rustc_trans; /// Add `target_feature = "..."` cfgs for a variety of platform @@ -21,6 +22,7 @@ use rustc_trans; pub fn add_configuration(cfg: &mut ast::CrateConfig, sess: &Session) { let tf = Symbol::intern("target_feature"); + #[cfg(feature="llvm")] for feat in rustc_trans::target_features(sess) { cfg.insert((tf, Some(feat))); } diff --git a/src/librustc_driver/test.rs b/src/librustc_driver/test.rs index 62e20a90f8a08..fd14d1aae9eaa 100644 --- a/src/librustc_driver/test.rs +++ b/src/librustc_driver/test.rs @@ -14,6 +14,7 @@ use driver; use rustc::dep_graph::DepGraph; use rustc_lint; use rustc_resolve::MakeGlobMap; +#[cfg(feature="llvm")] use rustc_trans; use rustc::middle::lang_items; use rustc::middle::free_region::FreeRegionMap; @@ -113,6 +114,7 @@ fn test_env(source_string: &str, diagnostic_handler, Rc::new(CodeMap::new(FilePathMapping::empty())), cstore.clone()); + #[cfg(feature="llvm")] rustc_trans::init(&sess); rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess)); let input = config::Input::Str { diff --git a/src/librustc_trans/back/link.rs b/src/librustc_trans/back/link.rs index 7cd1ef772981e..8770248df1d60 100644 --- a/src/librustc_trans/back/link.rs +++ b/src/librustc_trans/back/link.rs @@ -13,11 +13,11 @@ use super::linker::Linker; use super::rpath::RPathConfig; use super::rpath; use metadata::METADATA_FILENAME; -use rustc::session::config::{self, NoDebugInfo, OutputFilenames, Input, OutputType}; +use rustc::session::config::{self, NoDebugInfo, OutputFilenames, OutputType}; use rustc::session::filesearch; use rustc::session::search_paths::PathKind; use rustc::session::Session; -use rustc::middle::cstore::{self, LinkMeta, NativeLibrary, LibSource, LinkagePreference, +use rustc::middle::cstore::{LinkMeta, NativeLibrary, LibSource, LinkagePreference, NativeLibraryKind}; use rustc::middle::dependency_format::Linkage; use CrateTranslation; @@ -44,9 +44,13 @@ use std::process::Command; use std::str; use flate2::Compression; use flate2::write::ZlibEncoder; -use syntax::ast; use syntax::attr; -use syntax_pos::Span; + +mod no_llvm_link { + include!("./no_llvm_link.rs"); +} + +pub use self::no_llvm_link::*; /// The LLVM module name containing crate-metadata. This includes a `.` on /// purpose, so it cannot clash with the name of a user-defined module. @@ -84,56 +88,6 @@ pub const RLIB_BYTECODE_OBJECT_V1_DATASIZE_OFFSET: usize = pub const RLIB_BYTECODE_OBJECT_V1_DATA_OFFSET: usize = RLIB_BYTECODE_OBJECT_V1_DATASIZE_OFFSET + 8; - -pub fn find_crate_name(sess: Option<&Session>, - attrs: &[ast::Attribute], - input: &Input) -> String { - let validate = |s: String, span: Option| { - cstore::validate_crate_name(sess, &s, span); - s - }; - - // Look in attributes 100% of the time to make sure the attribute is marked - // as used. After doing this, however, we still prioritize a crate name from - // the command line over one found in the #[crate_name] attribute. If we - // find both we ensure that they're the same later on as well. - let attr_crate_name = attrs.iter().find(|at| at.check_name("crate_name")) - .and_then(|at| at.value_str().map(|s| (at, s))); - - if let Some(sess) = sess { - if let Some(ref s) = sess.opts.crate_name { - if let Some((attr, name)) = attr_crate_name { - if name != &**s { - let msg = format!("--crate-name and #[crate_name] are \ - required to match, but `{}` != `{}`", - s, name); - sess.span_err(attr.span, &msg); - } - } - return validate(s.clone(), None); - } - } - - if let Some((attr, s)) = attr_crate_name { - return validate(s.to_string(), Some(attr.span)); - } - if let Input::File(ref path) = *input { - if let Some(s) = path.file_stem().and_then(|s| s.to_str()) { - if s.starts_with("-") { - let msg = format!("crate names cannot start with a `-`, but \ - `{}` has a leading hyphen", s); - if let Some(sess) = sess { - sess.err(&msg); - } - } else { - return validate(s.replace("-", "_"), None); - } - } - } - - "rust_out".to_string() -} - pub fn build_link_meta(incremental_hashes_map: &IncrementalHashesMap) -> LinkMeta { let krate_dep_node = &DepNode::new_no_params(DepKind::Krate); let r = LinkMeta { @@ -245,37 +199,6 @@ pub fn link_binary(sess: &Session, out_filenames } - -/// Returns default crate type for target -/// -/// Default crate type is used when crate type isn't provided neither -/// through cmd line arguments nor through crate attributes -/// -/// It is CrateTypeExecutable for all platforms but iOS as there is no -/// way to run iOS binaries anyway without jailbreaking and -/// interaction with Rust code through static library is the only -/// option for now -pub fn default_output_for_target(sess: &Session) -> config::CrateType { - if !sess.target.target.options.executables { - config::CrateTypeStaticlib - } else { - config::CrateTypeExecutable - } -} - -/// Checks if target supports crate_type as output -pub fn invalid_output_for_target(sess: &Session, - crate_type: config::CrateType) -> bool { - match (sess.target.target.options.dynamic_linking, - sess.target.target.options.executables, crate_type) { - (false, _, config::CrateTypeCdylib) | - (false, _, config::CrateTypeProcMacro) | - (false, _, config::CrateTypeDylib) => true, - (_, false, config::CrateTypeExecutable) => true, - _ => false - } -} - fn is_writeable(p: &Path) -> bool { match p.metadata() { Err(..) => true, @@ -292,42 +215,6 @@ fn filename_for_metadata(sess: &Session, crate_name: &str, outputs: &OutputFilen out_filename } -pub fn filename_for_input(sess: &Session, - crate_type: config::CrateType, - crate_name: &str, - outputs: &OutputFilenames) -> PathBuf { - let libname = format!("{}{}", crate_name, sess.opts.cg.extra_filename); - - match crate_type { - config::CrateTypeRlib => { - outputs.out_directory.join(&format!("lib{}.rlib", libname)) - } - config::CrateTypeCdylib | - config::CrateTypeProcMacro | - config::CrateTypeDylib => { - let (prefix, suffix) = (&sess.target.target.options.dll_prefix, - &sess.target.target.options.dll_suffix); - outputs.out_directory.join(&format!("{}{}{}", prefix, libname, - suffix)) - } - config::CrateTypeStaticlib => { - let (prefix, suffix) = (&sess.target.target.options.staticlib_prefix, - &sess.target.target.options.staticlib_suffix); - outputs.out_directory.join(&format!("{}{}{}", prefix, libname, - suffix)) - } - config::CrateTypeExecutable => { - let suffix = &sess.target.target.options.exe_suffix; - let out_filename = outputs.path(OutputType::Exe); - if suffix.is_empty() { - out_filename.to_path_buf() - } else { - out_filename.with_extension(&suffix[1..]) - } - } - } -} - pub fn each_linked_rlib(sess: &Session, f: &mut FnMut(CrateNum, &Path)) { let crates = sess.cstore.used_crates(LinkagePreference::RequireStatic).into_iter(); diff --git a/src/librustc_trans/back/no_llvm_link.rs b/src/librustc_trans/back/no_llvm_link.rs new file mode 100644 index 0000000000000..e4ca25df2bc81 --- /dev/null +++ b/src/librustc_trans/back/no_llvm_link.rs @@ -0,0 +1,133 @@ +// Copyright 2017 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 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use std::path::PathBuf; + +use syntax::ast; +use syntax_pos::Span; + +use rustc::session::Session; +use rustc::session::config::{self, OutputFilenames, Input, OutputType}; +use rustc::middle::cstore; + +pub fn filename_for_input(sess: &Session, + crate_type: config::CrateType, + crate_name: &str, + outputs: &OutputFilenames) -> PathBuf { + let libname = format!("{}{}", crate_name, sess.opts.cg.extra_filename); + + match crate_type { + config::CrateTypeRlib => { + outputs.out_directory.join(&format!("lib{}.rlib", libname)) + } + config::CrateTypeCdylib | + config::CrateTypeProcMacro | + config::CrateTypeDylib => { + let (prefix, suffix) = (&sess.target.target.options.dll_prefix, + &sess.target.target.options.dll_suffix); + outputs.out_directory.join(&format!("{}{}{}", prefix, libname, + suffix)) + } + config::CrateTypeStaticlib => { + let (prefix, suffix) = (&sess.target.target.options.staticlib_prefix, + &sess.target.target.options.staticlib_suffix); + outputs.out_directory.join(&format!("{}{}{}", prefix, libname, + suffix)) + } + config::CrateTypeExecutable => { + let suffix = &sess.target.target.options.exe_suffix; + let out_filename = outputs.path(OutputType::Exe); + if suffix.is_empty() { + out_filename.to_path_buf() + } else { + out_filename.with_extension(&suffix[1..]) + } + } + } +} + +pub fn find_crate_name(sess: Option<&Session>, + attrs: &[ast::Attribute], + input: &Input) -> String { + let validate = |s: String, span: Option| { + cstore::validate_crate_name(sess, &s, span); + s + }; + + // Look in attributes 100% of the time to make sure the attribute is marked + // as used. After doing this, however, we still prioritize a crate name from + // the command line over one found in the #[crate_name] attribute. If we + // find both we ensure that they're the same later on as well. + let attr_crate_name = attrs.iter().find(|at| at.check_name("crate_name")) + .and_then(|at| at.value_str().map(|s| (at, s))); + + if let Some(sess) = sess { + if let Some(ref s) = sess.opts.crate_name { + if let Some((attr, name)) = attr_crate_name { + if name != &**s { + let msg = format!("--crate-name and #[crate_name] are \ + required to match, but `{}` != `{}`", + s, name); + sess.span_err(attr.span, &msg); + } + } + return validate(s.clone(), None); + } + } + + if let Some((attr, s)) = attr_crate_name { + return validate(s.to_string(), Some(attr.span)); + } + if let Input::File(ref path) = *input { + if let Some(s) = path.file_stem().and_then(|s| s.to_str()) { + if s.starts_with("-") { + let msg = format!("crate names cannot start with a `-`, but \ + `{}` has a leading hyphen", s); + if let Some(sess) = sess { + sess.err(&msg); + } + } else { + return validate(s.replace("-", "_"), None); + } + } + } + + "rust_out".to_string() +} + +/// Returns default crate type for target +/// +/// Default crate type is used when crate type isn't provided neither +/// through cmd line arguments nor through crate attributes +/// +/// It is CrateTypeExecutable for all platforms but iOS as there is no +/// way to run iOS binaries anyway without jailbreaking and +/// interaction with Rust code through static library is the only +/// option for now +pub fn default_output_for_target(sess: &Session) -> config::CrateType { + if !sess.target.target.options.executables { + config::CrateTypeStaticlib + } else { + config::CrateTypeExecutable + } +} + +/// Checks if target supports crate_type as output +pub fn invalid_output_for_target(sess: &Session, + crate_type: config::CrateType) -> bool { + match (sess.target.target.options.dynamic_linking, + sess.target.target.options.executables, crate_type) { + (false, _, config::CrateTypeCdylib) | + (false, _, config::CrateTypeProcMacro) | + (false, _, config::CrateTypeDylib) => true, + (_, false, config::CrateTypeExecutable) => true, + _ => false + } +} diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index ec4a23b0417bc..6091c43bbfe3d 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -42,6 +42,7 @@ use html::render::derive_id; use html::toc::TocBuilder; use html::highlight; use html::escape::Escape; +#[cfg(feature="llvm")] use test; use pulldown_cmark::{html, Event, Tag, Parser}; diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 496662f442c41..ebeb48729b135 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -87,6 +87,7 @@ pub mod passes; pub mod plugins; pub mod visit_ast; pub mod visit_lib; +#[cfg(feature="llvm")] pub mod test; use clean::AttributesExt; diff --git a/src/librustdoc/markdown.rs b/src/librustdoc/markdown.rs index 057ce69d9de8b..cd2bf997a0b0b 100644 --- a/src/librustdoc/markdown.rs +++ b/src/librustdoc/markdown.rs @@ -27,6 +27,7 @@ use html::escape::Escape; use html::markdown; use html::markdown::{Markdown, MarkdownWithToc, find_testable_code, old_find_testable_code}; use html::markdown::RenderType; +#[cfg(feature="llvm")] use test::{TestOptions, Collector}; /// Separate any lines at the start of the file that begin with `# ` or `%`. diff --git a/src/rustc/Cargo.toml b/src/rustc/Cargo.toml index dce1a0a8ec858..7fcff82e6aaee 100644 --- a/src/rustc/Cargo.toml +++ b/src/rustc/Cargo.toml @@ -20,3 +20,4 @@ rustdoc = { path = "../librustdoc" } [features] jemalloc = ["rustc_back/jemalloc"] +llvm = ["rustc_driver/llvm"] \ No newline at end of file