]> git.lizzy.rs Git - rust.git/blob - src/librustc/metadata/cstore.rs
Convert most code to new inner attribute syntax.
[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 std::c_vec::CVec;
22 use collections::HashMap;
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<Vec<CrateSource> >,
71     priv used_libraries: RefCell<Vec<(~str, NativeLibaryKind)> >,
72     priv used_link_args: RefCell<Vec<~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(Vec::new()),
85             used_libraries: RefCell::new(Vec::new()),
86             used_link_args: RefCell::new(Vec::new()),
87             intr: intr
88         }
89     }
90
91     pub fn get_crate_data(&self, cnum: ast::CrateNum) -> @crate_metadata {
92         *self.metas.borrow().get(&cnum)
93     }
94
95     pub fn get_crate_hash(&self, cnum: ast::CrateNum) -> Svh {
96         let cdata = self.get_crate_data(cnum);
97         decoder::get_crate_hash(cdata.data())
98     }
99
100     pub fn get_crate_id(&self, cnum: ast::CrateNum) -> CrateId {
101         let cdata = self.get_crate_data(cnum);
102         decoder::get_crate_id(cdata.data())
103     }
104
105     pub fn set_crate_data(&self, cnum: ast::CrateNum, data: @crate_metadata) {
106         self.metas.borrow_mut().insert(cnum, data);
107     }
108
109     pub fn have_crate_data(&self, cnum: ast::CrateNum) -> bool {
110         self.metas.borrow().contains_key(&cnum)
111     }
112
113     pub fn iter_crate_data(&self, i: |ast::CrateNum, @crate_metadata|) {
114         for (&k, &v) in self.metas.borrow().iter() {
115             i(k, v);
116         }
117     }
118
119     pub fn add_used_crate_source(&self, src: CrateSource) {
120         let mut used_crate_sources = self.used_crate_sources.borrow_mut();
121         if !used_crate_sources.contains(&src) {
122             used_crate_sources.push(src);
123         }
124     }
125
126     pub fn get_used_crate_source(&self, cnum: ast::CrateNum)
127                                      -> Option<CrateSource> {
128         self.used_crate_sources.borrow_mut()
129             .iter().find(|source| source.cnum == cnum)
130             .map(|source| source.clone())
131     }
132
133     pub fn reset(&self) {
134         self.metas.borrow_mut().clear();
135         self.extern_mod_crate_map.borrow_mut().clear();
136         self.used_crate_sources.borrow_mut().clear();
137         self.used_libraries.borrow_mut().clear();
138         self.used_link_args.borrow_mut().clear();
139     }
140
141     // This method is used when generating the command line to pass through to
142     // system linker. The linker expects undefined symbols on the left of the
143     // command line to be defined in libraries on the right, not the other way
144     // around. For more info, see some comments in the add_used_library function
145     // below.
146     //
147     // In order to get this left-to-right dependency ordering, we perform a
148     // topological sort of all crates putting the leaves at the right-most
149     // positions.
150     pub fn get_used_crates(&self, prefer: LinkagePreference)
151                            -> Vec<(ast::CrateNum, Option<Path>)> {
152         let mut ordering = Vec::new();
153         fn visit(cstore: &CStore, cnum: ast::CrateNum,
154                  ordering: &mut Vec<ast::CrateNum>) {
155             if ordering.as_slice().contains(&cnum) { return }
156             let meta = cstore.get_crate_data(cnum);
157             for (_, &dep) in meta.cnum_map.borrow().iter() {
158                 visit(cstore, dep, ordering);
159             }
160             ordering.push(cnum);
161         };
162         for (&num, _) in self.metas.borrow().iter() {
163             visit(self, num, &mut ordering);
164         }
165         ordering.as_mut_slice().reverse();
166         let ordering = ordering.as_slice();
167         let mut libs = self.used_crate_sources.borrow()
168             .iter()
169             .map(|src| (src.cnum, match prefer {
170                 RequireDynamic => src.dylib.clone(),
171                 RequireStatic => src.rlib.clone(),
172             }))
173             .collect::<Vec<(ast::CrateNum, Option<Path>)>>();
174         libs.sort_by(|&(a, _), &(b, _)| {
175             ordering.position_elem(&a).cmp(&ordering.position_elem(&b))
176         });
177         libs
178     }
179
180     pub fn add_used_library(&self, lib: ~str, kind: NativeLibaryKind) {
181         assert!(!lib.is_empty());
182         self.used_libraries.borrow_mut().push((lib, kind));
183     }
184
185     pub fn get_used_libraries<'a>(&'a self)
186                               -> &'a RefCell<Vec<(~str, NativeLibaryKind)> > {
187         &self.used_libraries
188     }
189
190     pub fn add_used_link_args(&self, args: &str) {
191         for s in args.split(' ') {
192             self.used_link_args.borrow_mut().push(s.to_owned());
193         }
194     }
195
196     pub fn get_used_link_args<'a>(&'a self) -> &'a RefCell<Vec<~str> > {
197         &self.used_link_args
198     }
199
200     pub fn add_extern_mod_stmt_cnum(&self,
201                                     emod_id: ast::NodeId,
202                                     cnum: ast::CrateNum) {
203         self.extern_mod_crate_map.borrow_mut().insert(emod_id, cnum);
204     }
205
206     pub fn find_extern_mod_stmt_cnum(&self, emod_id: ast::NodeId)
207                                      -> Option<ast::CrateNum> {
208         self.extern_mod_crate_map.borrow().find(&emod_id).map(|x| *x)
209     }
210 }
211
212 impl crate_metadata {
213     pub fn data<'a>(&'a self) -> &'a [u8] { self.data.as_slice() }
214 }
215
216 impl MetadataBlob {
217     pub fn as_slice<'a>(&'a self) -> &'a [u8] {
218         match *self {
219             MetadataVec(ref vec) => vec.as_slice(),
220             MetadataArchive(ref ar) => ar.as_slice(),
221         }
222     }
223 }