]> git.lizzy.rs Git - rust.git/blob - src/librustc/metadata/cstore.rs
d6cee8fadb56d424a3a29129b36eaf81db1832df
[rust.git] / src / librustc / metadata / cstore.rs
1 // Copyright 2012-2014 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 #[allow(non_camel_case_types)];
12
13 // The crate store - a central repo for information collected about external
14 // crates and libraries
15
16 use back::svh::Svh;
17 use metadata::decoder;
18 use metadata::loader;
19
20 use std::cell::RefCell;
21 use collections::HashMap;
22 use extra::c_vec::CVec;
23 use syntax::ast;
24 use syntax::parse::token::IdentInterner;
25 use syntax::crateid::CrateId;
26
27 // A map from external crate numbers (as decoded from some crate file) to
28 // local crate numbers (as generated during this session). Each external
29 // crate may refer to types in other external crates, and each has their
30 // own crate numbers.
31 pub type cnum_map = @RefCell<HashMap<ast::CrateNum, ast::CrateNum>>;
32
33 pub enum MetadataBlob {
34     MetadataVec(CVec<u8>),
35     MetadataArchive(loader::ArchiveMetadata),
36 }
37
38 pub struct crate_metadata {
39     name: ~str,
40     data: MetadataBlob,
41     cnum_map: cnum_map,
42     cnum: ast::CrateNum
43 }
44
45 #[deriving(Eq)]
46 pub enum LinkagePreference {
47     RequireDynamic,
48     RequireStatic,
49 }
50
51 #[deriving(Eq, FromPrimitive)]
52 pub enum NativeLibaryKind {
53     NativeStatic,    // native static library (.a archive)
54     NativeFramework, // OSX-specific
55     NativeUnknown,   // default way to specify a dynamic library
56 }
57
58 // Where a crate came from on the local filesystem. One of these two options
59 // must be non-None.
60 #[deriving(Eq, Clone)]
61 pub struct CrateSource {
62     dylib: Option<Path>,
63     rlib: Option<Path>,
64     cnum: ast::CrateNum,
65 }
66
67 pub struct CStore {
68     priv metas: RefCell<HashMap<ast::CrateNum, @crate_metadata>>,
69     priv extern_mod_crate_map: RefCell<extern_mod_crate_map>,
70     priv used_crate_sources: RefCell<~[CrateSource]>,
71     priv used_libraries: RefCell<~[(~str, NativeLibaryKind)]>,
72     priv used_link_args: RefCell<~[~str]>,
73     intr: @IdentInterner
74 }
75
76 // Map from NodeId's of local extern crate statements to crate numbers
77 type extern_mod_crate_map = HashMap<ast::NodeId, ast::CrateNum>;
78
79 impl CStore {
80     pub fn new(intr: @IdentInterner) -> CStore {
81         CStore {
82             metas: RefCell::new(HashMap::new()),
83             extern_mod_crate_map: RefCell::new(HashMap::new()),
84             used_crate_sources: RefCell::new(~[]),
85             used_libraries: RefCell::new(~[]),
86             used_link_args: RefCell::new(~[]),
87             intr: intr
88         }
89     }
90
91     pub fn get_crate_data(&self, cnum: ast::CrateNum) -> @crate_metadata {
92         let metas = self.metas.borrow();
93         *metas.get().get(&cnum)
94     }
95
96     pub fn get_crate_hash(&self, cnum: ast::CrateNum) -> Svh {
97         let cdata = self.get_crate_data(cnum);
98         decoder::get_crate_hash(cdata.data())
99     }
100
101     pub fn get_crate_id(&self, cnum: ast::CrateNum) -> CrateId {
102         let cdata = self.get_crate_data(cnum);
103         decoder::get_crate_id(cdata.data())
104     }
105
106     pub fn set_crate_data(&self, cnum: ast::CrateNum, data: @crate_metadata) {
107         let mut metas = self.metas.borrow_mut();
108         metas.get().insert(cnum, data);
109     }
110
111     pub fn have_crate_data(&self, cnum: ast::CrateNum) -> bool {
112         let metas = self.metas.borrow();
113         metas.get().contains_key(&cnum)
114     }
115
116     pub fn iter_crate_data(&self, i: |ast::CrateNum, @crate_metadata|) {
117         let metas = self.metas.borrow();
118         for (&k, &v) in metas.get().iter() {
119             i(k, v);
120         }
121     }
122
123     pub fn add_used_crate_source(&self, src: CrateSource) {
124         let mut used_crate_sources = self.used_crate_sources.borrow_mut();
125         if !used_crate_sources.get().contains(&src) {
126             used_crate_sources.get().push(src);
127         }
128     }
129
130     pub fn get_used_crate_source(&self, cnum: ast::CrateNum)
131                                      -> Option<CrateSource> {
132         let mut used_crate_sources = self.used_crate_sources.borrow_mut();
133         used_crate_sources.get().iter().find(|source| source.cnum == cnum)
134             .map(|source| source.clone())
135     }
136
137     pub fn reset(&self) {
138         self.metas.with_mut(|s| s.clear());
139         self.extern_mod_crate_map.with_mut(|s| s.clear());
140         self.used_crate_sources.with_mut(|s| s.clear());
141         self.used_libraries.with_mut(|s| s.clear());
142         self.used_link_args.with_mut(|s| s.clear());
143     }
144
145     pub fn get_used_crates(&self, prefer: LinkagePreference)
146                            -> ~[(ast::CrateNum, Option<Path>)] {
147         let used_crate_sources = self.used_crate_sources.borrow();
148         used_crate_sources.get()
149             .iter()
150             .map(|src| (src.cnum, match prefer {
151                 RequireDynamic => src.dylib.clone(),
152                 RequireStatic => src.rlib.clone(),
153             }))
154             .collect()
155     }
156
157     pub fn add_used_library(&self, lib: ~str, kind: NativeLibaryKind) {
158         assert!(!lib.is_empty());
159         let mut used_libraries = self.used_libraries.borrow_mut();
160         used_libraries.get().push((lib, kind));
161     }
162
163     pub fn get_used_libraries<'a>(&'a self)
164                               -> &'a RefCell<~[(~str, NativeLibaryKind)]> {
165         &self.used_libraries
166     }
167
168     pub fn add_used_link_args(&self, args: &str) {
169         let mut used_link_args = self.used_link_args.borrow_mut();
170         for s in args.split(' ') {
171             used_link_args.get().push(s.to_owned());
172         }
173     }
174
175     pub fn get_used_link_args<'a>(&'a self) -> &'a RefCell<~[~str]> {
176         &self.used_link_args
177     }
178
179     pub fn add_extern_mod_stmt_cnum(&self,
180                                     emod_id: ast::NodeId,
181                                     cnum: ast::CrateNum) {
182         let mut extern_mod_crate_map = self.extern_mod_crate_map.borrow_mut();
183         extern_mod_crate_map.get().insert(emod_id, cnum);
184     }
185
186     pub fn find_extern_mod_stmt_cnum(&self, emod_id: ast::NodeId)
187                                      -> Option<ast::CrateNum> {
188         let extern_mod_crate_map = self.extern_mod_crate_map.borrow();
189         extern_mod_crate_map.get().find(&emod_id).map(|x| *x)
190     }
191 }
192
193 impl crate_metadata {
194     pub fn data<'a>(&'a self) -> &'a [u8] { self.data.as_slice() }
195 }
196
197 impl MetadataBlob {
198     pub fn as_slice<'a>(&'a self) -> &'a [u8] {
199         match *self {
200             MetadataVec(ref vec) => vec.as_slice(),
201             MetadataArchive(ref ar) => ar.as_slice(),
202         }
203     }
204 }