Support --emit=foo,metadata

This commit is contained in:
Nick Cameron 2016-12-29 13:23:38 +13:00
parent 9c89166611
commit b059a80d4c
3 changed files with 67 additions and 27 deletions

View File

@ -103,7 +103,7 @@ pub fn calculate(sess: &session::Session) {
fn calculate_type(sess: &session::Session,
ty: config::CrateType) -> DependencyList {
if sess.opts.output_types.contains_key(&config::OutputType::Metadata) {
if !sess.opts.output_types.should_trans() {
return Vec::new();
}

View File

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

View File

@ -192,7 +192,7 @@ pub fn link_binary(sess: &Session,
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 ||
sess.opts.output_types.contains_key(&OutputType::Metadata)) &&
!sess.opts.output_types.should_trans()) &&
crate_type == config::CrateTypeExecutable {
continue;
}
@ -201,13 +201,13 @@ 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 {
if !sess.opts.output_types.contains_key(&OutputType::Metadata) {
if sess.opts.output_types.should_trans() {
for obj in object_filenames(trans, outputs) {
remove(sess, &obj);
}
@ -256,16 +256,21 @@ 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);
if outputs.outputs.contains_key(&OutputType::Metadata) {
return outputs.out_directory.join(&format!("lib{}.rmeta", libname));
}
match crate_type {
config::CrateTypeRlib => {
outputs.out_directory.join(&format!("lib{}.rlib", libname))
@ -327,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") {
@ -355,9 +374,16 @@ fn link_binary_output(sess: &Session,
Err(err) => sess.fatal(&format!("couldn't create a temp dir: {}", err)),
};
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);
} else {
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,
@ -371,9 +397,10 @@ fn link_binary_output(sess: &Session,
outputs, tmpdir.path());
}
}
out_filenames.push(out_filename);
}
out_filename
out_filenames
}
fn object_filenames(trans: &CrateTranslation,