Skip to content

Commit

Permalink
rustc: --emit=rlibmeta outputs an rlib with only metadata, works with…
Browse files Browse the repository at this point in the history
… -Z no-trans.
  • Loading branch information
eddyb committed Jun 12, 2015
1 parent f6c306d commit 381267b
Show file tree
Hide file tree
Showing 9 changed files with 214 additions and 145 deletions.
6 changes: 4 additions & 2 deletions src/librustc/metadata/encoder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -251,8 +251,10 @@ fn encode_symbol(ecx: &EncodeContext,
rbml_w.wr_tagged_str(tag_items_data_item_symbol, x);
}
None => {
ecx.diag.handler().bug(
&format!("encode_symbol: id not found {}", id));
if !ecx.tcx.sess.opts.no_trans {
ecx.diag.handler().bug(
&format!("encode_symbol: id not found {}", id));
}
}
}
}
Expand Down
48 changes: 27 additions & 21 deletions src/librustc/session/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ pub enum OutputType {
OutputTypeObject,
OutputTypeExe,
OutputTypeDepInfo,
OutputTypeRlibMeta,
}

#[derive(Clone)]
Expand Down Expand Up @@ -183,6 +184,7 @@ impl OutputFilenames {
OutputTypeLlvmAssembly => base.with_extension("ll"),
OutputTypeObject => base.with_extension("o"),
OutputTypeDepInfo => base.with_extension("d"),
OutputTypeRlibMeta => base.with_extension("rmeta"),
OutputTypeExe => base,
}
}
Expand Down Expand Up @@ -785,7 +787,7 @@ pub fn rustc_short_optgroups() -> Vec<RustcOptGroup> {
"NAME"),
opt::multi("", "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|link|dep-info|rlibmeta]"),
opt::multi("", "print", "Comma separated list of compiler information to \
print on stdout",
"[crate-name|file-names|sysroot]"),
Expand Down Expand Up @@ -886,29 +888,33 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
}

let mut output_types = Vec::new();
if !debugging_opts.parse_only && !no_trans {
let unparsed_output_types = matches.opt_strs("emit");
for unparsed_output_type in &unparsed_output_types {
for part in unparsed_output_type.split(',') {
let output_type = match part {
"asm" => OutputTypeAssembly,
"llvm-ir" => OutputTypeLlvmAssembly,
"llvm-bc" => OutputTypeBitcode,
"obj" => OutputTypeObject,
"link" => OutputTypeExe,
"dep-info" => OutputTypeDepInfo,
_ => {
early_error(&format!("unknown emission type: `{}`",
part))
}
};
output_types.push(output_type)
}
let unparsed_output_types = matches.opt_strs("emit");
for unparsed_output_type in &unparsed_output_types {
for part in unparsed_output_type.split(',') {
let output_type = match part {
"asm" => OutputTypeAssembly,
"llvm-ir" => OutputTypeLlvmAssembly,
"llvm-bc" => OutputTypeBitcode,
"obj" => OutputTypeObject,
"link" => OutputTypeExe,
"dep-info" => OutputTypeDepInfo,
"rlibmeta" => OutputTypeRlibMeta,
_ => {
early_error(&format!("unknown emission type: `{}`",
part))
}
};
output_types.push(output_type)
}
};
}
output_types.sort();
output_types.dedup();
if output_types.is_empty() {

if debugging_opts.parse_only {
output_types = vec![];
} else if no_trans {
output_types.retain(|&x| x == OutputTypeRlibMeta);
} else if output_types.is_empty() {
output_types.push(OutputTypeExe);
}

Expand Down
23 changes: 18 additions & 5 deletions src/librustc_driver/driver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ pub fn compile_input(sess: Session,
CompileState::state_after_expand(input,
&sess,
outdir,
&outputs,
&expanded_crate,
&id[..]));

Expand All @@ -115,6 +116,7 @@ pub fn compile_input(sess: Session,
CompileState::state_after_write_deps(input,
&sess,
outdir,
&outputs,
&ast_map,
&ast_map.krate(),
&id[..]));
Expand All @@ -130,6 +132,7 @@ pub fn compile_input(sess: Session,
CompileState::state_after_analysis(input,
&analysis.ty_cx.sess,
outdir,
&outputs,
analysis.ty_cx.map.krate(),
&analysis,
&analysis.ty_cx));
Expand Down Expand Up @@ -157,6 +160,7 @@ pub fn compile_input(sess: Session,
CompileState::state_after_llvm(input,
&sess,
outdir,
&outputs,
&trans));

phase_6_link_output(&sess, &trans, &outputs);
Expand Down Expand Up @@ -280,19 +284,22 @@ impl<'a, 'ast, 'tcx> CompileState<'a, 'ast, 'tcx> {
fn state_after_expand(input: &'a Input,
session: &'a Session,
out_dir: &'a Option<PathBuf>,
outputs: &'a OutputFilenames,
expanded_crate: &'a ast::Crate,
crate_name: &'a str)
-> CompileState<'a, 'ast, 'tcx> {
CompileState {
crate_name: Some(crate_name),
expanded_crate: Some(expanded_crate),
output_filenames: Some(outputs),
.. CompileState::empty(input, session, out_dir)
}
}

fn state_after_write_deps(input: &'a Input,
session: &'a Session,
out_dir: &'a Option<PathBuf>,
outputs: &'a OutputFilenames,
ast_map: &'a ast_map::Map<'ast>,
expanded_crate: &'a ast::Crate,
crate_name: &'a str)
Expand All @@ -301,13 +308,15 @@ impl<'a, 'ast, 'tcx> CompileState<'a, 'ast, 'tcx> {
crate_name: Some(crate_name),
ast_map: Some(ast_map),
expanded_crate: Some(expanded_crate),
output_filenames: Some(outputs),
.. CompileState::empty(input, session, out_dir)
}
}

fn state_after_analysis(input: &'a Input,
session: &'a Session,
out_dir: &'a Option<PathBuf>,
outputs: &'a OutputFilenames,
expanded_crate: &'a ast::Crate,
analysis: &'a ty::CrateAnalysis<'tcx>,
tcx: &'a ty::ctxt<'tcx>)
Expand All @@ -316,6 +325,7 @@ impl<'a, 'ast, 'tcx> CompileState<'a, 'ast, 'tcx> {
analysis: Some(analysis),
tcx: Some(tcx),
expanded_crate: Some(expanded_crate),
output_filenames: Some(outputs),
.. CompileState::empty(input, session, out_dir)
}
}
Expand All @@ -324,10 +334,12 @@ impl<'a, 'ast, 'tcx> CompileState<'a, 'ast, 'tcx> {
fn state_after_llvm(input: &'a Input,
session: &'a Session,
out_dir: &'a Option<PathBuf>,
outputs: &'a OutputFilenames,
trans: &'a trans::CrateTranslation)
-> CompileState<'a, 'ast, 'tcx> {
CompileState {
trans: Some(trans),
output_filenames: Some(outputs),
.. CompileState::empty(input, session, out_dir)
}
}
Expand Down Expand Up @@ -788,12 +800,13 @@ fn write_out_deps(sess: &Session,
id: &str) {

let mut out_filenames = Vec::new();
for output_type in &sess.opts.output_types {
let file = outputs.path(*output_type);
match *output_type {
for &output_type in &sess.opts.output_types {
let file = outputs.path(output_type);
match output_type {
config::OutputTypeExe => {
for output in sess.crate_types.borrow().iter() {
let p = link::filename_for_input(sess, *output,
for &output in sess.crate_types.borrow().iter() {
let p = link::filename_for_input(sess, output,
output_type,
id, &file);
out_filenames.push(p);
}
Expand Down
16 changes: 15 additions & 1 deletion src/librustc_driver/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -368,9 +368,22 @@ impl<'a> CompilerCalls<'a> for RustcDefaultCalls {

if sess.opts.no_trans {
control.after_analysis.stop = Compilation::Stop;
if sess.opts.output_types.contains(&config::OutputTypeRlibMeta) {
control.after_analysis.callback = box |state| {
use rustc_trans::trans;

let tcx = state.tcx.unwrap();
let name = state.analysis.unwrap().name.clone();
let trans = trans::trans_only_metadata(tcx, name);
let outputs = state.output_filenames.unwrap();
driver::phase_6_link_output(&tcx.sess, &trans, outputs);
};
}
}

if !sess.opts.output_types.iter().any(|&i| i == config::OutputTypeExe) {
if !sess.opts.output_types.iter().any(|&i|
i == config::OutputTypeExe ||
i == config::OutputTypeRlibMeta) {
control.after_llvm.stop = Compilation::Stop;
}

Expand Down Expand Up @@ -456,6 +469,7 @@ impl RustcDefaultCalls {
for &style in &crate_types {
let fname = link::filename_for_input(sess,
style,
config::OutputTypeExe,
&id,
&t_outputs.with_extension(""));
println!("{}", fname.file_name().unwrap()
Expand Down
75 changes: 55 additions & 20 deletions src/librustc_trans/back/link.rs
Original file line number Diff line number Diff line change
Expand Up @@ -389,25 +389,39 @@ pub fn link_binary(sess: &Session,
outputs: &OutputFilenames,
crate_name: &str) -> Vec<PathBuf> {
let mut out_filenames = Vec::new();
for &crate_type in sess.crate_types.borrow().iter() {
if sess.opts.output_types.contains(&config::OutputTypeExe) {
for &crate_type in sess.crate_types.borrow().iter() {
if invalid_output_for_target(sess, crate_type) {
sess.bug(&format!("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, None);
out_filenames.push(out_file);
}

// Remove the temporary object file and metadata if we aren't saving temps
if !sess.opts.cg.save_temps {
let obj_filename = outputs.temp_path(OutputTypeObject);
if !sess.opts.output_types.contains(&OutputTypeObject) {
remove(sess, &obj_filename);
}
remove(sess, &obj_filename.with_extension("metadata.o"));
}
}

// Attempt to output an rlib with just metadata, if that was requested.
if sess.opts.output_types.contains(&config::OutputTypeRlibMeta) {
let crate_type = config::CrateTypeRlib;
if invalid_output_for_target(sess, crate_type) {
sess.bug(&format!("invalid output type `{:?}` for target os `{}`",
crate_type, sess.opts.target_triple));
crate_type, sess.opts.target_triple));
}
let out_file = link_binary_output(sess, trans, crate_type, outputs,
crate_name);
crate_name, Some(config::OutputTypeRlibMeta));
out_filenames.push(out_file);
}

// Remove the temporary object file and metadata if we aren't saving temps
if !sess.opts.cg.save_temps {
let obj_filename = outputs.temp_path(OutputTypeObject);
if !sess.opts.output_types.contains(&OutputTypeObject) {
remove(sess, &obj_filename);
}
remove(sess, &obj_filename.with_extension("metadata.o"));
}

out_filenames
}

Expand Down Expand Up @@ -449,12 +463,18 @@ fn is_writeable(p: &Path) -> bool {

pub fn filename_for_input(sess: &Session,
crate_type: config::CrateType,
output_type: config::OutputType,
name: &str,
out_filename: &Path) -> PathBuf {
let libname = format!("{}{}", name, sess.opts.cg.extra_filename);
match crate_type {
config::CrateTypeRlib => {
out_filename.with_file_name(&format!("lib{}.rlib", libname))
let suffix = if output_type == config::OutputTypeRlibMeta {
".rmeta"
} else {
""
};
out_filename.with_file_name(&format!("lib{}{}.rlib", libname, suffix))
}
config::CrateTypeDylib => {
let (prefix, suffix) = (&sess.target.target.options.dll_prefix,
Expand Down Expand Up @@ -482,13 +502,16 @@ fn link_binary_output(sess: &Session,
trans: &CrateTranslation,
crate_type: config::CrateType,
outputs: &OutputFilenames,
crate_name: &str) -> PathBuf {
crate_name: &str,
custom_rlib_emission: Option<config::OutputType>)
-> PathBuf {
let obj_filename = outputs.temp_path(OutputTypeObject);
let out_filename = match outputs.single_output_file {
Some(ref file) => file.clone(),
None => {
let out_filename = outputs.path(OutputTypeExe);
filename_for_input(sess, crate_type, crate_name, &out_filename)
let output_type = custom_rlib_emission.unwrap_or(OutputTypeExe);
let out_filename = outputs.path(output_type);
filename_for_input(sess, crate_type, output_type, crate_name, &out_filename)
}
};

Expand All @@ -511,7 +534,12 @@ fn link_binary_output(sess: &Session,

match crate_type {
config::CrateTypeRlib => {
link_rlib(sess, Some(trans), &obj_filename, &out_filename).build();
let obj_filename = if custom_rlib_emission.is_some() {
None
} else {
Some(&*obj_filename)
};
link_rlib(sess, Some(trans), obj_filename, &out_filename).build();
}
config::CrateTypeStaticlib => {
link_staticlib(sess, &obj_filename, &out_filename);
Expand Down Expand Up @@ -544,7 +572,7 @@ fn archive_search_paths(sess: &Session) -> Vec<PathBuf> {
// native libraries and inserting all of the contents into this archive.
fn link_rlib<'a>(sess: &'a Session,
trans: Option<&CrateTranslation>, // None == no metadata/bytecode
obj_filename: &Path,
obj_filename: Option<&Path>,
out_filename: &Path) -> ArchiveBuilder<'a> {
info!("preparing rlib from {:?} to {:?}", obj_filename, out_filename);
let handler = &sess.diagnostic().handler;
Expand All @@ -557,7 +585,7 @@ fn link_rlib<'a>(sess: &'a Session,
ar_prog: get_ar_prog(sess),
};
let mut ab = ArchiveBuilder::create(config);
ab.add_file(obj_filename).unwrap();
obj_filename.map(|file| ab.add_file(file).unwrap());

for &(ref l, kind) in sess.cstore.get_used_libraries().borrow().iter() {
match kind {
Expand Down Expand Up @@ -619,6 +647,13 @@ fn link_rlib<'a>(sess: &'a Session,
ab.add_file(&metadata).unwrap();
remove(sess, &metadata);

// Nothing else to add if we have no code.
let obj_filename = if let Some(file) = obj_filename {
file
} else {
return ab;
};

// For LTO purposes, the bytecode of this library is also inserted
// into the archive. If codegen_units > 1, we insert each of the
// bitcode files.
Expand Down Expand Up @@ -734,7 +769,7 @@ fn write_rlib_bytecode_object_v1(writer: &mut Write,
// link in the metadata object file (and also don't prepare the archive with a
// metadata file).
fn link_staticlib(sess: &Session, obj_filename: &Path, out_filename: &Path) {
let ab = link_rlib(sess, None, obj_filename, out_filename);
let ab = link_rlib(sess, None, Some(obj_filename), out_filename);
let mut ab = match sess.target.target.options.is_like_osx {
true => ab.build().extend(),
false => ab,
Expand Down
Loading

0 comments on commit 381267b

Please sign in to comment.