Auto merge of #38571 - nrc:emit-metadata-change, r=alexcrichton

Change --crate-type metadata to --emit=metadata

WIP
This commit is contained in:
bors 2016-12-29 11:01:11 +00:00
commit e571f2d778
19 changed files with 156 additions and 79 deletions

View File

@ -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.

View File

@ -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,

View File

@ -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 {

View File

@ -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<PathBuf>> {
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<RustcOptGroup> {
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<String>) -> Result<Vec<CrateType>, String> {
pub fn parse_crate_types_from_list(list_list: Vec<String>)
-> Result<(Vec<CrateType>, bool), String> {
let mut crate_types: Vec<CrateType> = 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<String>) -> Result<Vec<CrateTy
"cdylib" => 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<String>) -> Result<Vec<CrateTy
}
}
return Ok(crate_types);
return Ok((crate_types, emit_metadata));
}
pub mod nightly_options {
@ -1638,7 +1665,6 @@ impl fmt::Display for CrateType {
CrateTypeStaticlib => "staticlib".fmt(f),
CrateTypeCdylib => "cdylib".fmt(f),
CrateTypeProcMacro => "proc-macro".fmt(f),
CrateTypeMetadata => "metadata".fmt(f),
}
}
}

View File

@ -1182,9 +1182,6 @@ pub fn collect_crate_types(session: &Session, attrs: &[ast::Attribute]) -> Vec<c
Some(ref n) if *n == "rlib" => {
Some(config::CrateTypeRlib)
}
Some(ref n) if *n == "metadata" => {
Some(config::CrateTypeMetadata)
}
Some(ref n) if *n == "dylib" => {
Some(config::CrateTypeDylib)
}

View File

@ -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;
}

View File

@ -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 }

View File

@ -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 link_binary_output(sess: &Session,
trans: &CrateTranslation,
crate_type: config::CrateType,
outputs: &OutputFilenames,
crate_name: &str) -> PathBuf {
let objects = object_filenames(trans, outputs);
let default_filename = filename_for_input(sess, crate_type, crate_name,
outputs);
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);
// 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()));
}
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) -> Vec<PathBuf> {
let objects = object_filenames(trans, outputs);
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);
}
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_filenames
}
fn object_filenames(trans: &CrateTranslation,

View File

@ -34,7 +34,6 @@ pub fn crate_type_allows_lto(crate_type: config::CrateType) -> bool {
config::CrateTypeDylib |
config::CrateTypeRlib |
config::CrateTypeMetadata |
config::CrateTypeProcMacro => false,
}
}

View File

@ -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,
}
}

View File

@ -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 => {}
}

View File

@ -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,

View File

@ -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,

View File

@ -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;

View File

@ -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;

View File

@ -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 <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.
// 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() {
}

View File

@ -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`
}

View File

@ -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;

View File

@ -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 {