diff --git a/src/librustc/middle/dependency_format.rs b/src/librustc/middle/dependency_format.rs index 075b3d7a8e90c..e60d0533c9f81 100644 --- a/src/librustc/middle/dependency_format.rs +++ b/src/librustc/middle/dependency_format.rs @@ -103,6 +103,10 @@ pub fn calculate(sess: &session::Session) { fn calculate_type(sess: &session::Session, ty: config::CrateType) -> DependencyList { + if !sess.opts.output_types.should_trans() { + return Vec::new(); + } + match ty { // If the global prefer_dynamic switch is turned off, first attempt // static linkage (this can fail). @@ -114,7 +118,7 @@ fn calculate_type(sess: &session::Session, // No linkage happens with rlibs, we just needed the metadata (which we // got long ago), so don't bother with anything. - config::CrateTypeRlib | config::CrateTypeMetadata => return Vec::new(), + config::CrateTypeRlib => return Vec::new(), // Staticlibs and cdylibs must have all static dependencies. If any fail // to be found, we generate some nice pretty errors. diff --git a/src/librustc/middle/reachable.rs b/src/librustc/middle/reachable.rs index ee841afc02169..765d93742d8fb 100644 --- a/src/librustc/middle/reachable.rs +++ b/src/librustc/middle/reachable.rs @@ -139,7 +139,7 @@ impl<'a, 'tcx> ReachableContext<'a, 'tcx> { fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> ReachableContext<'a, 'tcx> { let any_library = tcx.sess.crate_types.borrow().iter().any(|ty| { *ty == config::CrateTypeRlib || *ty == config::CrateTypeDylib || - *ty == config::CrateTypeProcMacro || *ty == config::CrateTypeMetadata + *ty == config::CrateTypeProcMacro }); ReachableContext { tcx: tcx, diff --git a/src/librustc/middle/weak_lang_items.rs b/src/librustc/middle/weak_lang_items.rs index c6df1497e681d..acb506878e6b6 100644 --- a/src/librustc/middle/weak_lang_items.rs +++ b/src/librustc/middle/weak_lang_items.rs @@ -75,8 +75,7 @@ fn verify(sess: &Session, items: &lang_items::LanguageItems) { config::CrateTypeCdylib | config::CrateTypeExecutable | config::CrateTypeStaticlib => true, - config::CrateTypeRlib | - config::CrateTypeMetadata => false, + config::CrateTypeRlib => false, } }); if !needs_check { diff --git a/src/librustc/session/config.rs b/src/librustc/session/config.rs index a78482171a0de..b3cb5ace45bc0 100644 --- a/src/librustc/session/config.rs +++ b/src/librustc/session/config.rs @@ -73,6 +73,7 @@ pub enum OutputType { Bitcode, Assembly, LlvmAssembly, + Metadata, Object, Exe, DepInfo, @@ -86,7 +87,8 @@ impl OutputType { OutputType::Bitcode | OutputType::Assembly | OutputType::LlvmAssembly | - OutputType::Object => false, + OutputType::Object | + OutputType::Metadata => false, } } @@ -96,6 +98,7 @@ impl OutputType { OutputType::Assembly => "asm", OutputType::LlvmAssembly => "llvm-ir", OutputType::Object => "obj", + OutputType::Metadata => "metadata", OutputType::Exe => "link", OutputType::DepInfo => "dep-info", } @@ -107,6 +110,7 @@ impl OutputType { OutputType::Assembly => "s", OutputType::LlvmAssembly => "ll", OutputType::Object => "o", + OutputType::Metadata => "rmeta", OutputType::DepInfo => "d", OutputType::Exe => "", } @@ -152,6 +156,19 @@ impl OutputTypes { pub fn values<'a>(&'a self) -> BTreeMapValuesIter<'a, OutputType, Option> { self.0.values() } + + // True if any of the output types require codegen or linking. + pub fn should_trans(&self) -> bool { + self.0.keys().any(|k| match *k { + OutputType::Bitcode | + OutputType::Assembly | + OutputType::LlvmAssembly | + OutputType::Object | + OutputType::Exe => true, + OutputType::Metadata | + OutputType::DepInfo => false, + }) + } } @@ -482,7 +499,6 @@ pub enum CrateType { CrateTypeStaticlib, CrateTypeCdylib, CrateTypeProcMacro, - CrateTypeMetadata, } #[derive(Clone, Hash)] @@ -1159,12 +1175,12 @@ pub fn rustc_short_optgroups() -> Vec { assumed.", "[KIND=]NAME"), opt::multi_s("", "crate-type", "Comma separated list of types of crates for the compiler to emit", - "[bin|lib|rlib|dylib|cdylib|staticlib|metadata]"), + "[bin|lib|rlib|dylib|cdylib|staticlib]"), opt::opt_s("", "crate-name", "Specify the name of the crate being built", "NAME"), opt::multi_s("", "emit", "Comma separated list of types of output for \ the compiler to emit", - "[asm|llvm-bc|llvm-ir|obj|link|dep-info]"), + "[asm|llvm-bc|llvm-ir|obj|metadata|link|dep-info]"), opt::multi_s("", "print", "Comma separated list of compiler information to \ print on stdout", &print_opts.join("|")), opt::flagmulti_s("g", "", "Equivalent to -C debuginfo=2"), @@ -1293,7 +1309,7 @@ pub fn build_session_options_and_crate_config(matches: &getopts::Matches) }; let unparsed_crate_types = matches.opt_strs("crate-type"); - let crate_types = parse_crate_types_from_list(unparsed_crate_types) + let (crate_types, emit_metadata) = parse_crate_types_from_list(unparsed_crate_types) .unwrap_or_else(|e| early_error(error_format, &e[..])); let mut lint_opts = vec![]; @@ -1327,6 +1343,7 @@ pub fn build_session_options_and_crate_config(matches: &getopts::Matches) "llvm-ir" => OutputType::LlvmAssembly, "llvm-bc" => OutputType::Bitcode, "obj" => OutputType::Object, + "metadata" => OutputType::Metadata, "link" => OutputType::Exe, "dep-info" => OutputType::DepInfo, part => { @@ -1339,7 +1356,9 @@ pub fn build_session_options_and_crate_config(matches: &getopts::Matches) } } }; - if output_types.is_empty() { + if emit_metadata { + output_types.insert(OutputType::Metadata, None); + } else if output_types.is_empty() { output_types.insert(OutputType::Exe, None); } @@ -1541,8 +1560,10 @@ pub fn build_session_options_and_crate_config(matches: &getopts::Matches) cfg) } -pub fn parse_crate_types_from_list(list_list: Vec) -> Result, String> { +pub fn parse_crate_types_from_list(list_list: Vec) + -> Result<(Vec, bool), String> { let mut crate_types: Vec = Vec::new(); + let mut emit_metadata = false; for unparsed_crate_type in &list_list { for part in unparsed_crate_type.split(',') { let new_part = match part { @@ -1553,7 +1574,13 @@ pub fn parse_crate_types_from_list(list_list: Vec) -> Result CrateTypeCdylib, "bin" => CrateTypeExecutable, "proc-macro" => CrateTypeProcMacro, - "metadata" => CrateTypeMetadata, + // FIXME(#38640) remove this when Cargo is fixed. + "metadata" => { + early_warn(ErrorOutputType::default(), "--crate-type=metadata is deprecated, \ + prefer --emit=metadata"); + emit_metadata = true; + CrateTypeRlib + } _ => { return Err(format!("unknown crate type: `{}`", part)); @@ -1565,7 +1592,7 @@ pub fn parse_crate_types_from_list(list_list: Vec) -> Result "staticlib".fmt(f), CrateTypeCdylib => "cdylib".fmt(f), CrateTypeProcMacro => "proc-macro".fmt(f), - CrateTypeMetadata => "metadata".fmt(f), } } } diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs index 8da9a23f4faad..291f0e0d50d8f 100644 --- a/src/librustc_driver/driver.rs +++ b/src/librustc_driver/driver.rs @@ -1182,9 +1182,6 @@ pub fn collect_crate_types(session: &Session, attrs: &[ast::Attribute]) -> Vec { Some(config::CrateTypeRlib) } - Some(ref n) if *n == "metadata" => { - Some(config::CrateTypeMetadata) - } Some(ref n) if *n == "dylib" => { Some(config::CrateTypeDylib) } diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs index f84622c2f0285..5ceec9edda3d0 100644 --- a/src/librustc_driver/lib.rs +++ b/src/librustc_driver/lib.rs @@ -493,7 +493,8 @@ impl<'a> CompilerCalls<'a> for RustcDefaultCalls { control.after_hir_lowering.stop = Compilation::Stop; } - if !sess.opts.output_types.keys().any(|&i| i == OutputType::Exe) { + if !sess.opts.output_types.keys().any(|&i| i == OutputType::Exe || + i == OutputType::Metadata) { control.after_llvm.stop = Compilation::Stop; } diff --git a/src/librustc_metadata/creader.rs b/src/librustc_metadata/creader.rs index a9af4118c5957..724c164b3b41a 100644 --- a/src/librustc_metadata/creader.rs +++ b/src/librustc_metadata/creader.rs @@ -799,8 +799,7 @@ impl<'a> CrateLoader<'a> { config::CrateTypeProcMacro | config::CrateTypeCdylib | config::CrateTypeStaticlib => need_lib_alloc = true, - config::CrateTypeRlib | - config::CrateTypeMetadata => {} + config::CrateTypeRlib => {} } } if !need_lib_alloc && !need_exe_alloc { return } diff --git a/src/librustc_trans/back/link.rs b/src/librustc_trans/back/link.rs index 648dc4c24c9a6..defbb44448a9f 100644 --- a/src/librustc_trans/back/link.rs +++ b/src/librustc_trans/back/link.rs @@ -191,7 +191,8 @@ pub fn link_binary(sess: &Session, let mut out_filenames = Vec::new(); for &crate_type in sess.crate_types.borrow().iter() { // Ignore executable crates if we have -Z no-trans, as they will error. - if sess.opts.debugging_opts.no_trans && + if (sess.opts.debugging_opts.no_trans || + !sess.opts.output_types.should_trans()) && crate_type == config::CrateTypeExecutable { continue; } @@ -200,15 +201,16 @@ pub fn link_binary(sess: &Session, bug!("invalid output type `{:?}` for target os `{}`", crate_type, sess.opts.target_triple); } - let out_file = link_binary_output(sess, trans, crate_type, outputs, - crate_name); - out_filenames.push(out_file); + let mut out_files = link_binary_output(sess, trans, crate_type, outputs, crate_name); + out_filenames.append(&mut out_files); } // Remove the temporary object file and metadata if we aren't saving temps if !sess.opts.cg.save_temps { - for obj in object_filenames(trans, outputs) { - remove(sess, &obj); + if sess.opts.output_types.should_trans() { + for obj in object_filenames(trans, outputs) { + remove(sess, &obj); + } } remove(sess, &outputs.with_extension("metadata.o")); } @@ -254,18 +256,25 @@ fn is_writeable(p: &Path) -> bool { } } +fn filename_for_metadata(sess: &Session, crate_name: &str, outputs: &OutputFilenames) -> PathBuf { + let out_filename = outputs.single_output_file.clone() + .unwrap_or(outputs + .out_directory + .join(&format!("lib{}{}.rmeta", crate_name, sess.opts.cg.extra_filename))); + check_file_is_writeable(&out_filename, sess); + 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::CrateTypeMetadata => { - outputs.out_directory.join(&format!("lib{}.rmeta", libname)) - } config::CrateTypeCdylib | config::CrateTypeProcMacro | config::CrateTypeDylib => { @@ -323,27 +332,41 @@ pub fn each_linked_rlib(sess: &Session, } } +fn out_filename(sess: &Session, + crate_type: config::CrateType, + outputs: &OutputFilenames, + crate_name: &str) + -> PathBuf { + let default_filename = filename_for_input(sess, crate_type, crate_name, outputs); + let out_filename = outputs.outputs.get(&OutputType::Exe) + .and_then(|s| s.to_owned()) + .or_else(|| outputs.single_output_file.clone()) + .unwrap_or(default_filename); + + check_file_is_writeable(&out_filename, sess); + + out_filename +} + +// Make sure files are writeable. Mac, FreeBSD, and Windows system linkers +// check this already -- however, the Linux linker will happily overwrite a +// read-only file. We should be consistent. +fn check_file_is_writeable(file: &Path, sess: &Session) { + if !is_writeable(file) { + sess.fatal(&format!("output file {} is not writeable -- check its \ + permissions", file.display())); + } +} + fn link_binary_output(sess: &Session, trans: &CrateTranslation, crate_type: config::CrateType, outputs: &OutputFilenames, - crate_name: &str) -> PathBuf { + crate_name: &str) -> Vec { let objects = object_filenames(trans, outputs); - let default_filename = filename_for_input(sess, crate_type, crate_name, - outputs); - let out_filename = outputs.outputs.get(&OutputType::Exe) - .and_then(|s| s.to_owned()) - .or_else(|| outputs.single_output_file.clone()) - .unwrap_or(default_filename); - // Make sure files are writeable. Mac, FreeBSD, and Windows system linkers - // check this already -- however, the Linux linker will happily overwrite a - // read-only file. We should be consistent. - for file in objects.iter().chain(Some(&out_filename)) { - if !is_writeable(file) { - sess.fatal(&format!("output file {} is not writeable -- check its \ - permissions", file.display())); - } + for file in &objects { + check_file_is_writeable(file, sess); } let tmpdir = match TempDir::new("rustc") { @@ -351,24 +374,33 @@ fn link_binary_output(sess: &Session, Err(err) => sess.fatal(&format!("couldn't create a temp dir: {}", err)), }; - match crate_type { - config::CrateTypeRlib => { - link_rlib(sess, Some(trans), &objects, &out_filename, - tmpdir.path()).build(); - } - config::CrateTypeStaticlib => { - link_staticlib(sess, &objects, &out_filename, tmpdir.path()); - } - config::CrateTypeMetadata => { - emit_metadata(sess, trans, &out_filename); - } - _ => { - link_natively(sess, crate_type, &objects, &out_filename, trans, - outputs, tmpdir.path()); + let mut out_filenames = vec![]; + + if outputs.outputs.contains_key(&OutputType::Metadata) { + let out_filename = filename_for_metadata(sess, crate_name, outputs); + emit_metadata(sess, trans, &out_filename); + out_filenames.push(out_filename); + } + + if outputs.outputs.should_trans() { + let out_filename = out_filename(sess, crate_type, outputs, crate_name); + match crate_type { + config::CrateTypeRlib => { + link_rlib(sess, Some(trans), &objects, &out_filename, + tmpdir.path()).build(); + } + config::CrateTypeStaticlib => { + link_staticlib(sess, &objects, &out_filename, tmpdir.path()); + } + _ => { + link_natively(sess, crate_type, &objects, &out_filename, trans, + outputs, tmpdir.path()); + } } + out_filenames.push(out_filename); } - out_filename + out_filenames } fn object_filenames(trans: &CrateTranslation, diff --git a/src/librustc_trans/back/lto.rs b/src/librustc_trans/back/lto.rs index f137bfff034d0..0ef3f351a2a4b 100644 --- a/src/librustc_trans/back/lto.rs +++ b/src/librustc_trans/back/lto.rs @@ -34,7 +34,6 @@ pub fn crate_type_allows_lto(crate_type: config::CrateType) -> bool { config::CrateTypeDylib | config::CrateTypeRlib | - config::CrateTypeMetadata | config::CrateTypeProcMacro => false, } } diff --git a/src/librustc_trans/back/symbol_export.rs b/src/librustc_trans/back/symbol_export.rs index eef464eb7f4dc..5f16291892387 100644 --- a/src/librustc_trans/back/symbol_export.rs +++ b/src/librustc_trans/back/symbol_export.rs @@ -149,7 +149,6 @@ pub fn crate_export_threshold(crate_type: config::CrateType) config::CrateTypeProcMacro | config::CrateTypeCdylib => SymbolExportLevel::C, config::CrateTypeRlib | - config::CrateTypeMetadata | config::CrateTypeDylib => SymbolExportLevel::Rust, } } diff --git a/src/librustc_trans/back/write.rs b/src/librustc_trans/back/write.rs index de8814f143e04..fb485a7f0f5a2 100644 --- a/src/librustc_trans/back/write.rs +++ b/src/librustc_trans/back/write.rs @@ -701,8 +701,8 @@ pub fn run_passes(sess: &Session, for output_type in output_types.keys() { match *output_type { - OutputType::Bitcode => { modules_config.emit_bc = true; }, - OutputType::LlvmAssembly => { modules_config.emit_ir = true; }, + OutputType::Bitcode => { modules_config.emit_bc = true; } + OutputType::LlvmAssembly => { modules_config.emit_ir = true; } OutputType::Assembly => { modules_config.emit_asm = true; // If we're not using the LLVM assembler, this function @@ -711,8 +711,9 @@ pub fn run_passes(sess: &Session, if !sess.opts.output_types.contains_key(&OutputType::Assembly) { metadata_config.emit_obj = true; } - }, - OutputType::Object => { modules_config.emit_obj = true; }, + } + OutputType::Object => { modules_config.emit_obj = true; } + OutputType::Metadata => { metadata_config.emit_obj = true; } OutputType::Exe => { modules_config.emit_obj = true; metadata_config.emit_obj = true; @@ -853,6 +854,7 @@ pub fn run_passes(sess: &Session, user_wants_objects = true; copy_if_one_unit(OutputType::Object, true); } + OutputType::Metadata | OutputType::Exe | OutputType::DepInfo => {} } diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs index 76bb1c56af381..47b76658bdd14 100644 --- a/src/librustc_trans/base.rs +++ b/src/librustc_trans/base.rs @@ -807,8 +807,7 @@ fn write_metadata(cx: &SharedCrateContext, config::CrateTypeStaticlib | config::CrateTypeCdylib => MetadataKind::None, - config::CrateTypeRlib | - config::CrateTypeMetadata => MetadataKind::Uncompressed, + config::CrateTypeRlib => MetadataKind::Uncompressed, config::CrateTypeDylib | config::CrateTypeProcMacro => MetadataKind::Compressed, @@ -1191,7 +1190,7 @@ pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // Skip crate items and just output metadata in -Z no-trans mode. if tcx.sess.opts.debugging_opts.no_trans || - tcx.sess.crate_types.borrow().iter().all(|ct| ct == &config::CrateTypeMetadata) { + tcx.sess.opts.output_types.contains_key(&config::OutputType::Metadata) { let linker_info = LinkerInfo::new(&shared_ccx, &ExportedSymbols::empty()); return CrateTranslation { modules: modules, diff --git a/src/test/compile-fail/auxiliary/rmeta_meta.rs b/src/test/compile-fail/auxiliary/rmeta_meta.rs index 7bd1a96f452d8..4207fc2373b17 100644 --- a/src/test/compile-fail/auxiliary/rmeta_meta.rs +++ b/src/test/compile-fail/auxiliary/rmeta_meta.rs @@ -9,8 +9,9 @@ // except according to those terms. // no-prefer-dynamic +// compile-flags: --emit=metadata -#![crate_type="metadata"] +#![crate_type="rlib"] pub struct Foo { pub field: i32, diff --git a/src/test/compile-fail/rmeta-lib-pass.rs b/src/test/compile-fail/rmeta-lib-pass.rs index f2ac37a2ce9f5..dde559b018cde 100644 --- a/src/test/compile-fail/rmeta-lib-pass.rs +++ b/src/test/compile-fail/rmeta-lib-pass.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// compile-flags: --emit=metadata // aux-build:rmeta_rlib.rs // no-prefer-dynamic // must-compile-successfully @@ -15,8 +16,6 @@ // Check that building a metadata crate works with a dependent, rlib crate. // This is a cfail test since there is no executable to run. -#![crate_type="metadata"] - extern crate rmeta_rlib; use rmeta_rlib::Foo; diff --git a/src/test/compile-fail/rmeta-pass.rs b/src/test/compile-fail/rmeta-pass.rs index 2c0b6f77c1e08..5b24da79a7e63 100644 --- a/src/test/compile-fail/rmeta-pass.rs +++ b/src/test/compile-fail/rmeta-pass.rs @@ -8,6 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// compile-flags: --emit=metadata // aux-build:rmeta_meta.rs // no-prefer-dynamic // must-compile-successfully @@ -16,8 +17,6 @@ // crate. // This is a cfail test since there is no executable to run. -#![crate_type="metadata"] - extern crate rmeta_meta; use rmeta_meta::Foo; diff --git a/src/test/compile-fail/rmeta-priv-warn.rs b/src/test/compile-fail/rmeta-priv-warn.rs new file mode 100644 index 0000000000000..3e7019e0ccc0e --- /dev/null +++ b/src/test/compile-fail/rmeta-priv-warn.rs @@ -0,0 +1,21 @@ +// Copyright 2016 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. + +// compile-flags: --emit=metadata +// no-prefer-dynamic +// must-compile-successfully + +#[deny(warnings)] + +// Test that we don't get warnings for non-pub main when only emitting metadata. +// (#38273) + +fn main() { +} diff --git a/src/test/compile-fail/rmeta.rs b/src/test/compile-fail/rmeta.rs index 455574bbb9dde..edcf98d996476 100644 --- a/src/test/compile-fail/rmeta.rs +++ b/src/test/compile-fail/rmeta.rs @@ -9,11 +9,10 @@ // except according to those terms. // no-prefer-dynamic +// compile-flags: --emit=metadata // Check that building a metadata crate finds an error. -#![crate_type="metadata"] - fn main() { let _ = Foo; //~ ERROR unresolved value `Foo` } diff --git a/src/test/compile-fail/rmeta_meta_main.rs b/src/test/compile-fail/rmeta_meta_main.rs index 1c922c281397a..ffeb5bc3b858f 100644 --- a/src/test/compile-fail/rmeta_meta_main.rs +++ b/src/test/compile-fail/rmeta_meta_main.rs @@ -8,13 +8,13 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +// compile-flags: --emit=metadata // aux-build:rmeta_meta.rs // no-prefer-dynamic // Check that building a metadata crate finds an error with a dependent, // metadata-only crate. -#![crate_type="metadata"] extern crate rmeta_meta; use rmeta_meta::Foo; diff --git a/src/test/run-pass/auxiliary/rmeta_rmeta.rs b/src/test/run-pass/auxiliary/rmeta_rmeta.rs index 394845b66f3d3..c3cfe89ee5c3e 100644 --- a/src/test/run-pass/auxiliary/rmeta_rmeta.rs +++ b/src/test/run-pass/auxiliary/rmeta_rmeta.rs @@ -9,8 +9,9 @@ // except according to those terms. // no-prefer-dynamic +// compile-flags: --emit=metadata -#![crate_type="metadata"] +#![crate_type="rlib"] #![crate_name="rmeta_aux"] pub struct Foo {