]> git.lizzy.rs Git - rust.git/blob - src/librustc_trans_utils/trans_crate.rs
f51a463fcc23e86c30bb57335f4d5d9b78b58585
[rust.git] / src / librustc_trans_utils / trans_crate.rs
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.
4 //
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.
10
11 //! The Rust compiler.
12 //!
13 //! # Note
14 //!
15 //! This API is completely unstable and subject to change.
16
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/")]
20 #![deny(warnings)]
21
22 #![feature(box_syntax)]
23
24 use std::any::Any;
25 use std::io::prelude::*;
26 use std::io::{self, Cursor};
27 use std::fs::File;
28 use std::path::Path;
29 use std::sync::mpsc;
30
31 use owning_ref::{ErasedBoxRef, OwningRef};
32 use ar::{Archive, Builder, Header};
33 use flate2::Compression;
34 use flate2::write::DeflateEncoder;
35
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, DepNode, DepKind};
45 use rustc_back::target::Target;
46 use link::{build_link_meta, out_filename};
47
48 pub trait TransCrate {
49     type MetadataLoader: MetadataLoaderTrait;
50     type OngoingCrateTranslation;
51     type TranslatedCrate;
52
53     fn metadata_loader() -> Box<MetadataLoaderTrait>;
54     fn provide_local(_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;
60     fn join_trans(
61         trans: Self::OngoingCrateTranslation,
62         sess: &Session,
63         dep_graph: &DepGraph
64     ) -> Self::TranslatedCrate;
65     fn link_binary(sess: &Session, trans: &Self::TranslatedCrate, outputs: &OutputFilenames);
66     fn dump_incremental_data(trans: &Self::TranslatedCrate);
67 }
68
69 pub struct DummyTransCrate;
70
71 impl TransCrate for DummyTransCrate {
72     type MetadataLoader = DummyMetadataLoader;
73     type OngoingCrateTranslation = ();
74     type TranslatedCrate = ();
75
76     fn metadata_loader() -> Box<MetadataLoaderTrait> {
77         box DummyMetadataLoader(())
78     }
79
80     fn provide_local(_providers: &mut Providers) {
81         bug!("DummyTransCrate::provide_local");
82     }
83
84     fn provide_extern(_providers: &mut Providers) {
85         bug!("DummyTransCrate::provide_extern");
86     }
87
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");
93     }
94
95     fn join_trans(
96         _trans: Self::OngoingCrateTranslation,
97         _sess: &Session,
98         _dep_graph: &DepGraph
99     ) -> Self::TranslatedCrate {
100         bug!("DummyTransCrate::join_trans");
101     }
102
103     fn link_binary(_sess: &Session, _trans: &Self::TranslatedCrate, _outputs: &OutputFilenames) {
104         bug!("DummyTransCrate::link_binary");
105     }
106
107     fn dump_incremental_data(_trans: &Self::TranslatedCrate) {
108         bug!("DummyTransCrate::dump_incremental_data");
109     }
110 }
111
112 pub struct DummyMetadataLoader(());
113
114 impl MetadataLoaderTrait for DummyMetadataLoader {
115     fn get_rlib_metadata(
116         &self,
117         _target: &Target,
118         _filename: &Path
119     ) -> Result<ErasedBoxRef<[u8]>, String> {
120         bug!("DummyMetadataLoader::get_rlib_metadata");
121     }
122
123     fn get_dylib_metadata(
124         &self,
125         _target: &Target,
126         _filename: &Path
127     ) -> Result<ErasedBoxRef<[u8]>, String> {
128         bug!("DummyMetadataLoader::get_dylib_metadata");
129     }
130 }
131
132 pub struct NoLlvmMetadataLoader;
133
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);
139
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());
148             }
149         }
150
151         Err("Couldnt find metadata section".to_string())
152     }
153
154     fn get_dylib_metadata(
155         &self,
156         _target: &Target,
157         _filename: &Path,
158     ) -> Result<ErasedBoxRef<[u8]>, String> {
159         // FIXME: Support reading dylibs from llvm enabled rustc
160         self.get_rlib_metadata(_target, _filename)
161     }
162 }
163
164 pub struct MetadataOnlyTransCrate;
165 pub struct OngoingCrateTranslation {
166     metadata: EncodedMetadata,
167     metadata_version: Vec<u8>,
168     crate_name: Symbol,
169 }
170 pub struct TranslatedCrate(OngoingCrateTranslation);
171
172 impl MetadataOnlyTransCrate {
173     #[allow(dead_code)]
174     pub fn new() -> Self {
175         MetadataOnlyTransCrate
176     }
177 }
178
179 impl TransCrate for MetadataOnlyTransCrate {
180     type MetadataLoader = NoLlvmMetadataLoader;
181     type OngoingCrateTranslation = OngoingCrateTranslation;
182     type TranslatedCrate = TranslatedCrate;
183
184     fn metadata_loader() -> Box<MetadataLoaderTrait> {
185         box NoLlvmMetadataLoader
186     }
187
188     fn provide_local(_providers: &mut Providers) {}
189     fn provide_extern(_providers: &mut Providers) {}
190
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();
199
200         let crate_hash = tcx.dep_graph
201                         .fingerprint_of(&DepNode::new_no_params(DepKind::Krate));
202         let link_meta = build_link_meta(crate_hash);
203         let exported_symbols = ::find_exported_symbols(tcx);
204         let (metadata, _hashes) = tcx.encode_metadata(&link_meta, &exported_symbols);
205
206         OngoingCrateTranslation {
207             metadata: metadata,
208             metadata_version: tcx.metadata_encoding_version().to_vec(),
209             crate_name: tcx.crate_name(LOCAL_CRATE),
210         }
211     }
212
213     fn join_trans(
214         trans: Self::OngoingCrateTranslation,
215         _sess: &Session,
216         _dep_graph: &DepGraph,
217     ) -> Self::TranslatedCrate {
218         TranslatedCrate(trans)
219     }
220
221     fn link_binary(sess: &Session, trans: &Self::TranslatedCrate, outputs: &OutputFilenames) {
222         for &crate_type in sess.opts.crate_types.iter() {
223             if crate_type != CrateType::CrateTypeRlib && crate_type != CrateType::CrateTypeDylib {
224                 continue;
225             }
226             let output_name =
227                 out_filename(sess, crate_type, &outputs, &trans.0.crate_name.as_str());
228             let mut compressed = trans.0.metadata_version.clone();
229             let metadata = if crate_type == CrateType::CrateTypeDylib {
230                 DeflateEncoder::new(&mut compressed, Compression::Fast)
231                     .write_all(&trans.0.metadata.raw_data)
232                     .unwrap();
233                 &compressed
234             } else {
235                 &trans.0.metadata.raw_data
236             };
237             let mut builder = Builder::new(File::create(&output_name).unwrap());
238             let header = Header::new("rust.metadata.bin".to_string(), metadata.len() as u64);
239             builder.append(&header, Cursor::new(metadata)).unwrap();
240         }
241
242         if !sess.opts.crate_types.contains(&CrateType::CrateTypeRlib)
243             && !sess.opts.crate_types.contains(&CrateType::CrateTypeDylib) {
244             sess.fatal("Executables are not supported by the metadata-only backend.");
245         }
246     }
247
248     fn dump_incremental_data(_trans: &Self::TranslatedCrate) {}
249 }