]> git.proxmox.com Git - rustc.git/blob - src/librustc_trans_utils/trans_crate.rs
New upstream version 1.23.0+dfsg1
[rustc.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(_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(_providers: &mut Providers) {
81 bug!("DummyTransCrate::provide");
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(_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 }