Skip to content

Commit a47fdb9

Browse files
author
Victor Ding
committed
Support linking from a .rlink file
Flag `-Z no-link` was previously introduced, which allows creating an `.rlink` file to perform compilation without linking. This change enables linking from an `.rlink` file.
1 parent fc07615 commit a47fdb9

File tree

7 files changed

+57
-8
lines changed

7 files changed

+57
-8
lines changed

Cargo.lock

+1
Original file line numberDiff line numberDiff line change
@@ -3541,6 +3541,7 @@ dependencies = [
35413541
"log",
35423542
"rustc",
35433543
"rustc_ast_pretty",
3544+
"rustc_codegen_ssa",
35443545
"rustc_codegen_utils",
35453546
"rustc_data_structures",
35463547
"rustc_error_codes",

src/librustc_codegen_llvm/lib.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ use syntax::expand::allocator::AllocatorKind;
3939

4040
use rustc::dep_graph::DepGraph;
4141
use rustc::middle::cstore::{EncodedMetadata, MetadataLoaderDyn};
42-
use rustc::session::config::{OptLevel, OutputFilenames, PrintRequest};
42+
use rustc::session::config::{self, OptLevel, OutputFilenames, PrintRequest};
4343
use rustc::session::Session;
4444
use rustc::ty::{self, TyCtxt};
4545
use rustc::util::common::ErrorReported;
@@ -308,7 +308,7 @@ impl CodegenBackend for LlvmCodegenBackend {
308308
let rlink_data = json::encode(&codegen_results).map_err(|err| {
309309
sess.fatal(&format!("failed to encode rlink: {}", err));
310310
})?;
311-
let rlink_file = outputs.with_extension("rlink");
311+
let rlink_file = outputs.with_extension(config::RLINK_EXT);
312312
fs::write(&rlink_file, rlink_data).map_err(|err| {
313313
sess.fatal(&format!("failed to write file {}: {}", rlink_file.display(), err));
314314
})?;

src/librustc_driver/Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ rustc_mir = { path = "../librustc_mir" }
2626
rustc_parse = { path = "../librustc_parse" }
2727
rustc_plugin_impl = { path = "../librustc_plugin_impl" }
2828
rustc_save_analysis = { path = "../librustc_save_analysis" }
29+
rustc_codegen_ssa = { path = "../librustc_codegen_ssa" }
2930
rustc_codegen_utils = { path = "../librustc_codegen_utils" }
3031
rustc_error_codes = { path = "../librustc_error_codes" }
3132
rustc_interface = { path = "../librustc_interface" }

src/librustc_driver/lib.rs

+35-4
Original file line numberDiff line numberDiff line change
@@ -31,25 +31,27 @@ use rustc::session::{config, DiagnosticOutput, Session};
3131
use rustc::session::{early_error, early_warn};
3232
use rustc::ty::TyCtxt;
3333
use rustc::util::common::ErrorReported;
34+
use rustc_codegen_ssa::CodegenResults;
3435
use rustc_codegen_utils::codegen_backend::CodegenBackend;
3536
use rustc_data_structures::profiling::print_time_passes_entry;
3637
use rustc_data_structures::sync::SeqCst;
3738
use rustc_errors::{registry::Registry, PResult};
3839
use rustc_feature::{find_gated_cfg, UnstableFeatures};
3940
use rustc_hir::def_id::LOCAL_CRATE;
40-
use rustc_interface::util::get_builtin_codegen_backend;
41+
use rustc_interface::util::{collect_crate_types, get_builtin_codegen_backend};
4142
use rustc_interface::{interface, Queries};
4243
use rustc_lint::LintStore;
4344
use rustc_metadata::locator;
4445
use rustc_save_analysis as save;
4546
use rustc_save_analysis::DumpHandler;
46-
use rustc_serialize::json::ToJson;
47+
use rustc_serialize::json::{self, ToJson};
4748

4849
use std::borrow::Cow;
4950
use std::cmp::max;
5051
use std::default::Default;
5152
use std::env;
5253
use std::ffi::OsString;
54+
use std::fs;
5355
use std::io::{self, Read, Write};
5456
use std::mem;
5557
use std::panic::{self, catch_unwind};
@@ -286,7 +288,8 @@ pub fn run_compiler(
286288
&matches,
287289
compiler.input(),
288290
)
289-
});
291+
})
292+
.and_then(|| RustcDefaultCalls::try_process_rlink(sess, compiler));
290293

291294
if should_stop == Compilation::Stop {
292295
return sess.compile_status();
@@ -593,6 +596,34 @@ fn show_content_with_pager(content: &String) {
593596
}
594597

595598
impl RustcDefaultCalls {
599+
fn process_rlink(sess: &Session, compiler: &interface::Compiler) -> Result<(), ErrorReported> {
600+
if let Input::File(file) = compiler.input() {
601+
// FIXME: #![crate_type] and #![crate_name] support not implemented yet
602+
let attrs = vec![];
603+
sess.crate_types.set(collect_crate_types(sess, &attrs));
604+
let outputs = compiler.build_output_filenames(&sess, &attrs);
605+
let rlink_data = fs::read_to_string(file).unwrap_or_else(|err| {
606+
sess.fatal(&format!("failed to read rlink file: {}", err));
607+
});
608+
let codegen_results: CodegenResults = json::decode(&rlink_data).unwrap_or_else(|err| {
609+
sess.fatal(&format!("failed to decode rlink: {}", err));
610+
});
611+
compiler.codegen_backend().link(&sess, Box::new(codegen_results), &outputs)
612+
} else {
613+
sess.fatal(&format!("rlink must be a file"))
614+
}
615+
}
616+
617+
pub fn try_process_rlink(sess: &Session, compiler: &interface::Compiler) -> Compilation {
618+
if sess.opts.debugging_opts.link_only {
619+
let result = RustcDefaultCalls::process_rlink(sess, compiler);
620+
abort_on_err(result, sess);
621+
Compilation::Stop
622+
} else {
623+
Compilation::Continue
624+
}
625+
}
626+
596627
pub fn list_metadata(
597628
sess: &Session,
598629
metadata_loader: &dyn MetadataLoader,
@@ -668,7 +699,7 @@ impl RustcDefaultCalls {
668699
println!("{}", id);
669700
continue;
670701
}
671-
let crate_types = rustc_interface::util::collect_crate_types(sess, attrs);
702+
let crate_types = collect_crate_types(sess, attrs);
672703
for &style in &crate_types {
673704
let fname = rustc_codegen_utils::link::filename_for_input(
674705
sess, style, &id, &t_outputs,

src/librustc_interface/interface.rs

+15-2
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ pub use crate::passes::BoxedResolver;
22
use crate::util;
33

44
use rustc::lint;
5-
use rustc::session::config::{self, ErrorOutputType, Input};
5+
use rustc::session::config::{self, ErrorOutputType, Input, OutputFilenames};
66
use rustc::session::early_error;
77
use rustc::session::{DiagnosticOutput, Session};
88
use rustc::ty;
@@ -20,7 +20,7 @@ use rustc_span::source_map::{FileLoader, FileName, SourceMap};
2020
use std::path::PathBuf;
2121
use std::result;
2222
use std::sync::{Arc, Mutex};
23-
use syntax::ast::MetaItemKind;
23+
use syntax::ast::{self, MetaItemKind};
2424
use syntax::token;
2525

2626
pub type Result<T> = result::Result<T, ErrorReported>;
@@ -61,6 +61,19 @@ impl Compiler {
6161
pub fn output_file(&self) -> &Option<PathBuf> {
6262
&self.output_file
6363
}
64+
pub fn build_output_filenames(
65+
&self,
66+
sess: &Session,
67+
attrs: &[ast::Attribute],
68+
) -> OutputFilenames {
69+
util::build_output_filenames(
70+
&self.input,
71+
&self.output_dir,
72+
&self.output_file,
73+
&attrs,
74+
&sess,
75+
)
76+
}
6477
}
6578

6679
/// Converts strings provided as `--cfg [cfgspec]` into a `crate_cfg`.

src/librustc_session/config.rs

+1
Original file line numberDiff line numberDiff line change
@@ -467,6 +467,7 @@ pub struct OutputFilenames {
467467

468468
impl_stable_hash_via_hash!(OutputFilenames);
469469

470+
pub const RLINK_EXT: &str = "rlink";
470471
pub const RUST_CGU_EXT: &str = "rcgu";
471472

472473
impl OutputFilenames {

src/librustc_session/options.rs

+2
Original file line numberDiff line numberDiff line change
@@ -968,4 +968,6 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
968968
"use Windows Control Flow Guard (`disabled`, `nochecks` or `checks`)"),
969969
no_link: bool = (false, parse_bool, [TRACKED],
970970
"compile without linking"),
971+
link_only: bool = (false, parse_bool, [TRACKED],
972+
"link the `.rlink` file generated by `-Z no-link`"),
971973
}

0 commit comments

Comments
 (0)