1 // Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
11 //! The Rust compiler.
15 //! This API is completely unstable and subject to change.
17 #![doc(html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png",
18 html_favicon_url = "https://doc.rust-lang.org/favicon.ico",
19 html_root_url = "https://doc.rust-lang.org/nightly/")]
22 #![feature(box_syntax)]
25 use std::io::prelude::*;
26 use std::io::{self, Cursor};
31 use rustc_data_structures::owning_ref::{ErasedBoxRef, OwningRef};
32 use ar::{Archive, Builder, Header};
33 use flate2::Compression;
34 use flate2::write::DeflateEncoder;
36 use syntax::symbol::Symbol;
37 use rustc::hir::def_id::LOCAL_CRATE;
38 use rustc::session::Session;
39 use rustc::session::config::{CrateType, OutputFilenames};
40 use rustc::ty::TyCtxt;
41 use rustc::ty::maps::Providers;
42 use rustc::middle::cstore::EncodedMetadata;
43 use rustc::middle::cstore::MetadataLoader as MetadataLoaderTrait;
44 use rustc::dep_graph::DepGraph;
45 use rustc_back::target::Target;
46 use link::{build_link_meta, out_filename};
48 pub trait TransCrate {
49 type MetadataLoader: MetadataLoaderTrait;
50 type OngoingCrateTranslation;
53 fn metadata_loader() -> Box<MetadataLoaderTrait>;
54 fn provide(_providers: &mut Providers);
55 fn provide_extern(_providers: &mut Providers);
56 fn trans_crate<'a, 'tcx>(
57 tcx: TyCtxt<'a, 'tcx, 'tcx>,
58 rx: mpsc::Receiver<Box<Any + Send>>
59 ) -> Self::OngoingCrateTranslation;
61 trans: Self::OngoingCrateTranslation,
64 ) -> Self::TranslatedCrate;
65 fn link_binary(sess: &Session, trans: &Self::TranslatedCrate, outputs: &OutputFilenames);
66 fn dump_incremental_data(trans: &Self::TranslatedCrate);
69 pub struct DummyTransCrate;
71 impl TransCrate for DummyTransCrate {
72 type MetadataLoader = DummyMetadataLoader;
73 type OngoingCrateTranslation = ();
74 type TranslatedCrate = ();
76 fn metadata_loader() -> Box<MetadataLoaderTrait> {
77 box DummyMetadataLoader(())
80 fn provide(_providers: &mut Providers) {
81 bug!("DummyTransCrate::provide");
84 fn provide_extern(_providers: &mut Providers) {
85 bug!("DummyTransCrate::provide_extern");
88 fn trans_crate<'a, 'tcx>(
89 _tcx: TyCtxt<'a, 'tcx, 'tcx>,
90 _rx: mpsc::Receiver<Box<Any + Send>>
91 ) -> Self::OngoingCrateTranslation {
92 bug!("DummyTransCrate::trans_crate");
96 _trans: Self::OngoingCrateTranslation,
99 ) -> Self::TranslatedCrate {
100 bug!("DummyTransCrate::join_trans");
103 fn link_binary(_sess: &Session, _trans: &Self::TranslatedCrate, _outputs: &OutputFilenames) {
104 bug!("DummyTransCrate::link_binary");
107 fn dump_incremental_data(_trans: &Self::TranslatedCrate) {
108 bug!("DummyTransCrate::dump_incremental_data");
112 pub struct DummyMetadataLoader(());
114 impl MetadataLoaderTrait for DummyMetadataLoader {
115 fn get_rlib_metadata(
119 ) -> Result<ErasedBoxRef<[u8]>, String> {
120 bug!("DummyMetadataLoader::get_rlib_metadata");
123 fn get_dylib_metadata(
127 ) -> Result<ErasedBoxRef<[u8]>, String> {
128 bug!("DummyMetadataLoader::get_dylib_metadata");
132 pub struct NoLlvmMetadataLoader;
134 impl MetadataLoaderTrait for NoLlvmMetadataLoader {
135 fn get_rlib_metadata(&self, _: &Target, filename: &Path) -> Result<ErasedBoxRef<[u8]>, String> {
136 let file = File::open(filename)
137 .map_err(|e| format!("metadata file open err: {:?}", e))?;
138 let mut archive = Archive::new(file);
140 while let Some(entry_result) = archive.next_entry() {
141 let mut entry = entry_result
142 .map_err(|e| format!("metadata section read err: {:?}", e))?;
143 if entry.header().identifier() == "rust.metadata.bin" {
144 let mut buf = Vec::new();
145 io::copy(&mut entry, &mut buf).unwrap();
146 let buf: OwningRef<Vec<u8>, [u8]> = OwningRef::new(buf).into();
147 return Ok(buf.map_owner_box().erase_owner());
151 Err("Couldnt find metadata section".to_string())
154 fn get_dylib_metadata(
158 ) -> Result<ErasedBoxRef<[u8]>, String> {
159 // FIXME: Support reading dylibs from llvm enabled rustc
160 self.get_rlib_metadata(_target, _filename)
164 pub struct MetadataOnlyTransCrate;
165 pub struct OngoingCrateTranslation {
166 metadata: EncodedMetadata,
167 metadata_version: Vec<u8>,
170 pub struct TranslatedCrate(OngoingCrateTranslation);
172 impl MetadataOnlyTransCrate {
174 pub fn new() -> Self {
175 MetadataOnlyTransCrate
179 impl TransCrate for MetadataOnlyTransCrate {
180 type MetadataLoader = NoLlvmMetadataLoader;
181 type OngoingCrateTranslation = OngoingCrateTranslation;
182 type TranslatedCrate = TranslatedCrate;
184 fn metadata_loader() -> Box<MetadataLoaderTrait> {
185 box NoLlvmMetadataLoader
188 fn provide(_providers: &mut Providers) {}
189 fn provide_extern(_providers: &mut Providers) {}
191 fn trans_crate<'a, 'tcx>(
192 tcx: TyCtxt<'a, 'tcx, 'tcx>,
193 _rx: mpsc::Receiver<Box<Any + Send>>
194 ) -> Self::OngoingCrateTranslation {
195 ::check_for_rustc_errors_attr(tcx);
196 let _ = tcx.link_args(LOCAL_CRATE);
197 let _ = tcx.native_libraries(LOCAL_CRATE);
198 tcx.sess.abort_if_errors();
200 let link_meta = build_link_meta(tcx.crate_hash(LOCAL_CRATE));
201 let exported_symbols = ::find_exported_symbols(tcx);
202 let metadata = tcx.encode_metadata(&link_meta, &exported_symbols);
204 OngoingCrateTranslation {
206 metadata_version: tcx.metadata_encoding_version().to_vec(),
207 crate_name: tcx.crate_name(LOCAL_CRATE),
212 trans: Self::OngoingCrateTranslation,
214 _dep_graph: &DepGraph,
215 ) -> Self::TranslatedCrate {
216 TranslatedCrate(trans)
219 fn link_binary(sess: &Session, trans: &Self::TranslatedCrate, outputs: &OutputFilenames) {
220 for &crate_type in sess.opts.crate_types.iter() {
221 if crate_type != CrateType::CrateTypeRlib && crate_type != CrateType::CrateTypeDylib {
225 out_filename(sess, crate_type, &outputs, &trans.0.crate_name.as_str());
226 let mut compressed = trans.0.metadata_version.clone();
227 let metadata = if crate_type == CrateType::CrateTypeDylib {
228 DeflateEncoder::new(&mut compressed, Compression::Fast)
229 .write_all(&trans.0.metadata.raw_data)
233 &trans.0.metadata.raw_data
235 let mut builder = Builder::new(File::create(&output_name).unwrap());
236 let header = Header::new("rust.metadata.bin".to_string(), metadata.len() as u64);
237 builder.append(&header, Cursor::new(metadata)).unwrap();
240 if !sess.opts.crate_types.contains(&CrateType::CrateTypeRlib)
241 && !sess.opts.crate_types.contains(&CrateType::CrateTypeDylib) {
242 sess.fatal("Executables are not supported by the metadata-only backend.");
246 fn dump_incremental_data(_trans: &Self::TranslatedCrate) {}