Skip to content

Commit 381267b

Browse files
committed
rustc: --emit=rlibmeta outputs an rlib with only metadata, works with -Z no-trans.
1 parent f6c306d commit 381267b

File tree

9 files changed

+214
-145
lines changed

9 files changed

+214
-145
lines changed

src/librustc/metadata/encoder.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -251,8 +251,10 @@ fn encode_symbol(ecx: &EncodeContext,
251251
rbml_w.wr_tagged_str(tag_items_data_item_symbol, x);
252252
}
253253
None => {
254-
ecx.diag.handler().bug(
255-
&format!("encode_symbol: id not found {}", id));
254+
if !ecx.tcx.sess.opts.no_trans {
255+
ecx.diag.handler().bug(
256+
&format!("encode_symbol: id not found {}", id));
257+
}
256258
}
257259
}
258260
}

src/librustc/session/config.rs

+27-21
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ pub enum OutputType {
7070
OutputTypeObject,
7171
OutputTypeExe,
7272
OutputTypeDepInfo,
73+
OutputTypeRlibMeta,
7374
}
7475

7576
#[derive(Clone)]
@@ -183,6 +184,7 @@ impl OutputFilenames {
183184
OutputTypeLlvmAssembly => base.with_extension("ll"),
184185
OutputTypeObject => base.with_extension("o"),
185186
OutputTypeDepInfo => base.with_extension("d"),
187+
OutputTypeRlibMeta => base.with_extension("rmeta"),
186188
OutputTypeExe => base,
187189
}
188190
}
@@ -785,7 +787,7 @@ pub fn rustc_short_optgroups() -> Vec<RustcOptGroup> {
785787
"NAME"),
786788
opt::multi("", "emit", "Comma separated list of types of output for \
787789
the compiler to emit",
788-
"[asm|llvm-bc|llvm-ir|obj|link|dep-info]"),
790+
"[asm|llvm-bc|llvm-ir|obj|link|dep-info|rlibmeta]"),
789791
opt::multi("", "print", "Comma separated list of compiler information to \
790792
print on stdout",
791793
"[crate-name|file-names|sysroot]"),
@@ -886,29 +888,33 @@ pub fn build_session_options(matches: &getopts::Matches) -> Options {
886888
}
887889

888890
let mut output_types = Vec::new();
889-
if !debugging_opts.parse_only && !no_trans {
890-
let unparsed_output_types = matches.opt_strs("emit");
891-
for unparsed_output_type in &unparsed_output_types {
892-
for part in unparsed_output_type.split(',') {
893-
let output_type = match part {
894-
"asm" => OutputTypeAssembly,
895-
"llvm-ir" => OutputTypeLlvmAssembly,
896-
"llvm-bc" => OutputTypeBitcode,
897-
"obj" => OutputTypeObject,
898-
"link" => OutputTypeExe,
899-
"dep-info" => OutputTypeDepInfo,
900-
_ => {
901-
early_error(&format!("unknown emission type: `{}`",
902-
part))
903-
}
904-
};
905-
output_types.push(output_type)
906-
}
891+
let unparsed_output_types = matches.opt_strs("emit");
892+
for unparsed_output_type in &unparsed_output_types {
893+
for part in unparsed_output_type.split(',') {
894+
let output_type = match part {
895+
"asm" => OutputTypeAssembly,
896+
"llvm-ir" => OutputTypeLlvmAssembly,
897+
"llvm-bc" => OutputTypeBitcode,
898+
"obj" => OutputTypeObject,
899+
"link" => OutputTypeExe,
900+
"dep-info" => OutputTypeDepInfo,
901+
"rlibmeta" => OutputTypeRlibMeta,
902+
_ => {
903+
early_error(&format!("unknown emission type: `{}`",
904+
part))
905+
}
906+
};
907+
output_types.push(output_type)
907908
}
908-
};
909+
}
909910
output_types.sort();
910911
output_types.dedup();
911-
if output_types.is_empty() {
912+
913+
if debugging_opts.parse_only {
914+
output_types = vec![];
915+
} else if no_trans {
916+
output_types.retain(|&x| x == OutputTypeRlibMeta);
917+
} else if output_types.is_empty() {
912918
output_types.push(OutputTypeExe);
913919
}
914920

src/librustc_driver/driver.rs

+18-5
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ pub fn compile_input(sess: Session,
101101
CompileState::state_after_expand(input,
102102
&sess,
103103
outdir,
104+
&outputs,
104105
&expanded_crate,
105106
&id[..]));
106107

@@ -115,6 +116,7 @@ pub fn compile_input(sess: Session,
115116
CompileState::state_after_write_deps(input,
116117
&sess,
117118
outdir,
119+
&outputs,
118120
&ast_map,
119121
&ast_map.krate(),
120122
&id[..]));
@@ -130,6 +132,7 @@ pub fn compile_input(sess: Session,
130132
CompileState::state_after_analysis(input,
131133
&analysis.ty_cx.sess,
132134
outdir,
135+
&outputs,
133136
analysis.ty_cx.map.krate(),
134137
&analysis,
135138
&analysis.ty_cx));
@@ -157,6 +160,7 @@ pub fn compile_input(sess: Session,
157160
CompileState::state_after_llvm(input,
158161
&sess,
159162
outdir,
163+
&outputs,
160164
&trans));
161165

162166
phase_6_link_output(&sess, &trans, &outputs);
@@ -280,19 +284,22 @@ impl<'a, 'ast, 'tcx> CompileState<'a, 'ast, 'tcx> {
280284
fn state_after_expand(input: &'a Input,
281285
session: &'a Session,
282286
out_dir: &'a Option<PathBuf>,
287+
outputs: &'a OutputFilenames,
283288
expanded_crate: &'a ast::Crate,
284289
crate_name: &'a str)
285290
-> CompileState<'a, 'ast, 'tcx> {
286291
CompileState {
287292
crate_name: Some(crate_name),
288293
expanded_crate: Some(expanded_crate),
294+
output_filenames: Some(outputs),
289295
.. CompileState::empty(input, session, out_dir)
290296
}
291297
}
292298

293299
fn state_after_write_deps(input: &'a Input,
294300
session: &'a Session,
295301
out_dir: &'a Option<PathBuf>,
302+
outputs: &'a OutputFilenames,
296303
ast_map: &'a ast_map::Map<'ast>,
297304
expanded_crate: &'a ast::Crate,
298305
crate_name: &'a str)
@@ -301,13 +308,15 @@ impl<'a, 'ast, 'tcx> CompileState<'a, 'ast, 'tcx> {
301308
crate_name: Some(crate_name),
302309
ast_map: Some(ast_map),
303310
expanded_crate: Some(expanded_crate),
311+
output_filenames: Some(outputs),
304312
.. CompileState::empty(input, session, out_dir)
305313
}
306314
}
307315

308316
fn state_after_analysis(input: &'a Input,
309317
session: &'a Session,
310318
out_dir: &'a Option<PathBuf>,
319+
outputs: &'a OutputFilenames,
311320
expanded_crate: &'a ast::Crate,
312321
analysis: &'a ty::CrateAnalysis<'tcx>,
313322
tcx: &'a ty::ctxt<'tcx>)
@@ -316,6 +325,7 @@ impl<'a, 'ast, 'tcx> CompileState<'a, 'ast, 'tcx> {
316325
analysis: Some(analysis),
317326
tcx: Some(tcx),
318327
expanded_crate: Some(expanded_crate),
328+
output_filenames: Some(outputs),
319329
.. CompileState::empty(input, session, out_dir)
320330
}
321331
}
@@ -324,10 +334,12 @@ impl<'a, 'ast, 'tcx> CompileState<'a, 'ast, 'tcx> {
324334
fn state_after_llvm(input: &'a Input,
325335
session: &'a Session,
326336
out_dir: &'a Option<PathBuf>,
337+
outputs: &'a OutputFilenames,
327338
trans: &'a trans::CrateTranslation)
328339
-> CompileState<'a, 'ast, 'tcx> {
329340
CompileState {
330341
trans: Some(trans),
342+
output_filenames: Some(outputs),
331343
.. CompileState::empty(input, session, out_dir)
332344
}
333345
}
@@ -788,12 +800,13 @@ fn write_out_deps(sess: &Session,
788800
id: &str) {
789801

790802
let mut out_filenames = Vec::new();
791-
for output_type in &sess.opts.output_types {
792-
let file = outputs.path(*output_type);
793-
match *output_type {
803+
for &output_type in &sess.opts.output_types {
804+
let file = outputs.path(output_type);
805+
match output_type {
794806
config::OutputTypeExe => {
795-
for output in sess.crate_types.borrow().iter() {
796-
let p = link::filename_for_input(sess, *output,
807+
for &output in sess.crate_types.borrow().iter() {
808+
let p = link::filename_for_input(sess, output,
809+
output_type,
797810
id, &file);
798811
out_filenames.push(p);
799812
}

src/librustc_driver/lib.rs

+15-1
Original file line numberDiff line numberDiff line change
@@ -368,9 +368,22 @@ impl<'a> CompilerCalls<'a> for RustcDefaultCalls {
368368

369369
if sess.opts.no_trans {
370370
control.after_analysis.stop = Compilation::Stop;
371+
if sess.opts.output_types.contains(&config::OutputTypeRlibMeta) {
372+
control.after_analysis.callback = box |state| {
373+
use rustc_trans::trans;
374+
375+
let tcx = state.tcx.unwrap();
376+
let name = state.analysis.unwrap().name.clone();
377+
let trans = trans::trans_only_metadata(tcx, name);
378+
let outputs = state.output_filenames.unwrap();
379+
driver::phase_6_link_output(&tcx.sess, &trans, outputs);
380+
};
381+
}
371382
}
372383

373-
if !sess.opts.output_types.iter().any(|&i| i == config::OutputTypeExe) {
384+
if !sess.opts.output_types.iter().any(|&i|
385+
i == config::OutputTypeExe ||
386+
i == config::OutputTypeRlibMeta) {
374387
control.after_llvm.stop = Compilation::Stop;
375388
}
376389

@@ -456,6 +469,7 @@ impl RustcDefaultCalls {
456469
for &style in &crate_types {
457470
let fname = link::filename_for_input(sess,
458471
style,
472+
config::OutputTypeExe,
459473
&id,
460474
&t_outputs.with_extension(""));
461475
println!("{}", fname.file_name().unwrap()

src/librustc_trans/back/link.rs

+55-20
Original file line numberDiff line numberDiff line change
@@ -389,25 +389,39 @@ pub fn link_binary(sess: &Session,
389389
outputs: &OutputFilenames,
390390
crate_name: &str) -> Vec<PathBuf> {
391391
let mut out_filenames = Vec::new();
392-
for &crate_type in sess.crate_types.borrow().iter() {
392+
if sess.opts.output_types.contains(&config::OutputTypeExe) {
393+
for &crate_type in sess.crate_types.borrow().iter() {
394+
if invalid_output_for_target(sess, crate_type) {
395+
sess.bug(&format!("invalid output type `{:?}` for target os `{}`",
396+
crate_type, sess.opts.target_triple));
397+
}
398+
let out_file = link_binary_output(sess, trans, crate_type, outputs,
399+
crate_name, None);
400+
out_filenames.push(out_file);
401+
}
402+
403+
// Remove the temporary object file and metadata if we aren't saving temps
404+
if !sess.opts.cg.save_temps {
405+
let obj_filename = outputs.temp_path(OutputTypeObject);
406+
if !sess.opts.output_types.contains(&OutputTypeObject) {
407+
remove(sess, &obj_filename);
408+
}
409+
remove(sess, &obj_filename.with_extension("metadata.o"));
410+
}
411+
}
412+
413+
// Attempt to output an rlib with just metadata, if that was requested.
414+
if sess.opts.output_types.contains(&config::OutputTypeRlibMeta) {
415+
let crate_type = config::CrateTypeRlib;
393416
if invalid_output_for_target(sess, crate_type) {
394417
sess.bug(&format!("invalid output type `{:?}` for target os `{}`",
395-
crate_type, sess.opts.target_triple));
418+
crate_type, sess.opts.target_triple));
396419
}
397420
let out_file = link_binary_output(sess, trans, crate_type, outputs,
398-
crate_name);
421+
crate_name, Some(config::OutputTypeRlibMeta));
399422
out_filenames.push(out_file);
400423
}
401424

402-
// Remove the temporary object file and metadata if we aren't saving temps
403-
if !sess.opts.cg.save_temps {
404-
let obj_filename = outputs.temp_path(OutputTypeObject);
405-
if !sess.opts.output_types.contains(&OutputTypeObject) {
406-
remove(sess, &obj_filename);
407-
}
408-
remove(sess, &obj_filename.with_extension("metadata.o"));
409-
}
410-
411425
out_filenames
412426
}
413427

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

450464
pub fn filename_for_input(sess: &Session,
451465
crate_type: config::CrateType,
466+
output_type: config::OutputType,
452467
name: &str,
453468
out_filename: &Path) -> PathBuf {
454469
let libname = format!("{}{}", name, sess.opts.cg.extra_filename);
455470
match crate_type {
456471
config::CrateTypeRlib => {
457-
out_filename.with_file_name(&format!("lib{}.rlib", libname))
472+
let suffix = if output_type == config::OutputTypeRlibMeta {
473+
".rmeta"
474+
} else {
475+
""
476+
};
477+
out_filename.with_file_name(&format!("lib{}{}.rlib", libname, suffix))
458478
}
459479
config::CrateTypeDylib => {
460480
let (prefix, suffix) = (&sess.target.target.options.dll_prefix,
@@ -482,13 +502,16 @@ fn link_binary_output(sess: &Session,
482502
trans: &CrateTranslation,
483503
crate_type: config::CrateType,
484504
outputs: &OutputFilenames,
485-
crate_name: &str) -> PathBuf {
505+
crate_name: &str,
506+
custom_rlib_emission: Option<config::OutputType>)
507+
-> PathBuf {
486508
let obj_filename = outputs.temp_path(OutputTypeObject);
487509
let out_filename = match outputs.single_output_file {
488510
Some(ref file) => file.clone(),
489511
None => {
490-
let out_filename = outputs.path(OutputTypeExe);
491-
filename_for_input(sess, crate_type, crate_name, &out_filename)
512+
let output_type = custom_rlib_emission.unwrap_or(OutputTypeExe);
513+
let out_filename = outputs.path(output_type);
514+
filename_for_input(sess, crate_type, output_type, crate_name, &out_filename)
492515
}
493516
};
494517

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

512535
match crate_type {
513536
config::CrateTypeRlib => {
514-
link_rlib(sess, Some(trans), &obj_filename, &out_filename).build();
537+
let obj_filename = if custom_rlib_emission.is_some() {
538+
None
539+
} else {
540+
Some(&*obj_filename)
541+
};
542+
link_rlib(sess, Some(trans), obj_filename, &out_filename).build();
515543
}
516544
config::CrateTypeStaticlib => {
517545
link_staticlib(sess, &obj_filename, &out_filename);
@@ -544,7 +572,7 @@ fn archive_search_paths(sess: &Session) -> Vec<PathBuf> {
544572
// native libraries and inserting all of the contents into this archive.
545573
fn link_rlib<'a>(sess: &'a Session,
546574
trans: Option<&CrateTranslation>, // None == no metadata/bytecode
547-
obj_filename: &Path,
575+
obj_filename: Option<&Path>,
548576
out_filename: &Path) -> ArchiveBuilder<'a> {
549577
info!("preparing rlib from {:?} to {:?}", obj_filename, out_filename);
550578
let handler = &sess.diagnostic().handler;
@@ -557,7 +585,7 @@ fn link_rlib<'a>(sess: &'a Session,
557585
ar_prog: get_ar_prog(sess),
558586
};
559587
let mut ab = ArchiveBuilder::create(config);
560-
ab.add_file(obj_filename).unwrap();
588+
obj_filename.map(|file| ab.add_file(file).unwrap());
561589

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

650+
// Nothing else to add if we have no code.
651+
let obj_filename = if let Some(file) = obj_filename {
652+
file
653+
} else {
654+
return ab;
655+
};
656+
622657
// For LTO purposes, the bytecode of this library is also inserted
623658
// into the archive. If codegen_units > 1, we insert each of the
624659
// bitcode files.
@@ -734,7 +769,7 @@ fn write_rlib_bytecode_object_v1(writer: &mut Write,
734769
// link in the metadata object file (and also don't prepare the archive with a
735770
// metadata file).
736771
fn link_staticlib(sess: &Session, obj_filename: &Path, out_filename: &Path) {
737-
let ab = link_rlib(sess, None, obj_filename, out_filename);
772+
let ab = link_rlib(sess, None, Some(obj_filename), out_filename);
738773
let mut ab = match sess.target.target.options.is_like_osx {
739774
true => ab.build().extend(),
740775
false => ab,

0 commit comments

Comments
 (0)