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.
This commit is contained in:
Victor Ding 2020-01-23 21:48:48 +11:00
parent fc07615c49
commit a47fdb99c0
7 changed files with 57 additions and 8 deletions

View File

@ -3541,6 +3541,7 @@ dependencies = [
"log",
"rustc",
"rustc_ast_pretty",
"rustc_codegen_ssa",
"rustc_codegen_utils",
"rustc_data_structures",
"rustc_error_codes",

View File

@ -39,7 +39,7 @@ use syntax::expand::allocator::AllocatorKind;
use rustc::dep_graph::DepGraph;
use rustc::middle::cstore::{EncodedMetadata, MetadataLoaderDyn};
use rustc::session::config::{OptLevel, OutputFilenames, PrintRequest};
use rustc::session::config::{self, OptLevel, OutputFilenames, PrintRequest};
use rustc::session::Session;
use rustc::ty::{self, TyCtxt};
use rustc::util::common::ErrorReported;
@ -308,7 +308,7 @@ impl CodegenBackend for LlvmCodegenBackend {
let rlink_data = json::encode(&codegen_results).map_err(|err| {
sess.fatal(&format!("failed to encode rlink: {}", err));
})?;
let rlink_file = outputs.with_extension("rlink");
let rlink_file = outputs.with_extension(config::RLINK_EXT);
fs::write(&rlink_file, rlink_data).map_err(|err| {
sess.fatal(&format!("failed to write file {}: {}", rlink_file.display(), err));
})?;

View File

@ -26,6 +26,7 @@ rustc_mir = { path = "../librustc_mir" }
rustc_parse = { path = "../librustc_parse" }
rustc_plugin_impl = { path = "../librustc_plugin_impl" }
rustc_save_analysis = { path = "../librustc_save_analysis" }
rustc_codegen_ssa = { path = "../librustc_codegen_ssa" }
rustc_codegen_utils = { path = "../librustc_codegen_utils" }
rustc_error_codes = { path = "../librustc_error_codes" }
rustc_interface = { path = "../librustc_interface" }

View File

@ -31,25 +31,27 @@ use rustc::session::{config, DiagnosticOutput, Session};
use rustc::session::{early_error, early_warn};
use rustc::ty::TyCtxt;
use rustc::util::common::ErrorReported;
use rustc_codegen_ssa::CodegenResults;
use rustc_codegen_utils::codegen_backend::CodegenBackend;
use rustc_data_structures::profiling::print_time_passes_entry;
use rustc_data_structures::sync::SeqCst;
use rustc_errors::{registry::Registry, PResult};
use rustc_feature::{find_gated_cfg, UnstableFeatures};
use rustc_hir::def_id::LOCAL_CRATE;
use rustc_interface::util::get_builtin_codegen_backend;
use rustc_interface::util::{collect_crate_types, get_builtin_codegen_backend};
use rustc_interface::{interface, Queries};
use rustc_lint::LintStore;
use rustc_metadata::locator;
use rustc_save_analysis as save;
use rustc_save_analysis::DumpHandler;
use rustc_serialize::json::ToJson;
use rustc_serialize::json::{self, ToJson};
use std::borrow::Cow;
use std::cmp::max;
use std::default::Default;
use std::env;
use std::ffi::OsString;
use std::fs;
use std::io::{self, Read, Write};
use std::mem;
use std::panic::{self, catch_unwind};
@ -286,7 +288,8 @@ pub fn run_compiler(
&matches,
compiler.input(),
)
});
})
.and_then(|| RustcDefaultCalls::try_process_rlink(sess, compiler));
if should_stop == Compilation::Stop {
return sess.compile_status();
@ -593,6 +596,34 @@ fn show_content_with_pager(content: &String) {
}
impl RustcDefaultCalls {
fn process_rlink(sess: &Session, compiler: &interface::Compiler) -> Result<(), ErrorReported> {
if let Input::File(file) = compiler.input() {
// FIXME: #![crate_type] and #![crate_name] support not implemented yet
let attrs = vec![];
sess.crate_types.set(collect_crate_types(sess, &attrs));
let outputs = compiler.build_output_filenames(&sess, &attrs);
let rlink_data = fs::read_to_string(file).unwrap_or_else(|err| {
sess.fatal(&format!("failed to read rlink file: {}", err));
});
let codegen_results: CodegenResults = json::decode(&rlink_data).unwrap_or_else(|err| {
sess.fatal(&format!("failed to decode rlink: {}", err));
});
compiler.codegen_backend().link(&sess, Box::new(codegen_results), &outputs)
} else {
sess.fatal(&format!("rlink must be a file"))
}
}
pub fn try_process_rlink(sess: &Session, compiler: &interface::Compiler) -> Compilation {
if sess.opts.debugging_opts.link_only {
let result = RustcDefaultCalls::process_rlink(sess, compiler);
abort_on_err(result, sess);
Compilation::Stop
} else {
Compilation::Continue
}
}
pub fn list_metadata(
sess: &Session,
metadata_loader: &dyn MetadataLoader,
@ -668,7 +699,7 @@ impl RustcDefaultCalls {
println!("{}", id);
continue;
}
let crate_types = rustc_interface::util::collect_crate_types(sess, attrs);
let crate_types = collect_crate_types(sess, attrs);
for &style in &crate_types {
let fname = rustc_codegen_utils::link::filename_for_input(
sess, style, &id, &t_outputs,

View File

@ -2,7 +2,7 @@ pub use crate::passes::BoxedResolver;
use crate::util;
use rustc::lint;
use rustc::session::config::{self, ErrorOutputType, Input};
use rustc::session::config::{self, ErrorOutputType, Input, OutputFilenames};
use rustc::session::early_error;
use rustc::session::{DiagnosticOutput, Session};
use rustc::ty;
@ -20,7 +20,7 @@ use rustc_span::source_map::{FileLoader, FileName, SourceMap};
use std::path::PathBuf;
use std::result;
use std::sync::{Arc, Mutex};
use syntax::ast::MetaItemKind;
use syntax::ast::{self, MetaItemKind};
use syntax::token;
pub type Result<T> = result::Result<T, ErrorReported>;
@ -61,6 +61,19 @@ impl Compiler {
pub fn output_file(&self) -> &Option<PathBuf> {
&self.output_file
}
pub fn build_output_filenames(
&self,
sess: &Session,
attrs: &[ast::Attribute],
) -> OutputFilenames {
util::build_output_filenames(
&self.input,
&self.output_dir,
&self.output_file,
&attrs,
&sess,
)
}
}
/// Converts strings provided as `--cfg [cfgspec]` into a `crate_cfg`.

View File

@ -467,6 +467,7 @@ pub struct OutputFilenames {
impl_stable_hash_via_hash!(OutputFilenames);
pub const RLINK_EXT: &str = "rlink";
pub const RUST_CGU_EXT: &str = "rcgu";
impl OutputFilenames {

View File

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