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 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, DepNode, DepKind}
;
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 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
);
206 OngoingCrateTranslation
{
208 metadata_version
: tcx
.metadata_encoding_version().to_vec(),
209 crate_name
: tcx
.crate_name(LOCAL_CRATE
),
214 trans
: Self::OngoingCrateTranslation
,
216 _dep_graph
: &DepGraph
,
217 ) -> Self::TranslatedCrate
{
218 TranslatedCrate(trans
)
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
{
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
)
235 &trans
.0.metadata
.raw_data
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();
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.");
248 fn dump_incremental_data(_trans
: &Self::TranslatedCrate
) {}