]>
Commit | Line | Data |
---|---|---|
1a4d82fc JJ |
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 | ||
c1a9b12d | 11 | use super::archive::{ArchiveBuilder, ArchiveConfig}; |
62682a34 | 12 | use super::linker::{Linker, GnuLinker, MsvcLinker}; |
1a4d82fc | 13 | use super::rpath::RPathConfig; |
62682a34 | 14 | use super::rpath; |
c1a9b12d | 15 | use super::msvc; |
1a4d82fc JJ |
16 | use session::config; |
17 | use session::config::NoDebugInfo; | |
b039eaaf | 18 | use session::config::{OutputFilenames, Input, OutputType}; |
92a42be0 | 19 | use session::filesearch; |
1a4d82fc JJ |
20 | use session::search_paths::PathKind; |
21 | use session::Session; | |
92a42be0 SL |
22 | use middle::cstore::{self, CrateStore, LinkMeta}; |
23 | use middle::cstore::{LinkagePreference, NativeLibraryKind}; | |
e9174d1e | 24 | use middle::dependency_format::Linkage; |
54a0048b | 25 | use CrateTranslation; |
1a4d82fc | 26 | use util::common::time; |
d9579d0f | 27 | use util::fs::fix_windows_verbatim_for_gcc; |
54a0048b | 28 | use rustc::ty::TyCtxt; |
c34b1796 | 29 | use rustc_back::tempdir::TempDir; |
1a4d82fc | 30 | |
54a0048b | 31 | use rustc_incremental::SvhCalculate; |
b039eaaf SL |
32 | use std::ascii; |
33 | use std::char; | |
62682a34 | 34 | use std::env; |
c34b1796 | 35 | use std::ffi::OsString; |
b039eaaf | 36 | use std::fs; |
c34b1796 | 37 | use std::io::{self, Read, Write}; |
1a4d82fc | 38 | use std::mem; |
c34b1796 AL |
39 | use std::path::{Path, PathBuf}; |
40 | use std::process::Command; | |
1a4d82fc | 41 | use std::str; |
1a4d82fc | 42 | use flate; |
1a4d82fc | 43 | use syntax::ast; |
1a4d82fc | 44 | use syntax::codemap::Span; |
e9174d1e | 45 | use syntax::attr::AttrMetaMethods; |
e9174d1e | 46 | |
1a4d82fc JJ |
47 | // RLIB LLVM-BYTECODE OBJECT LAYOUT |
48 | // Version 1 | |
49 | // Bytes Data | |
50 | // 0..10 "RUST_OBJECT" encoded in ASCII | |
51 | // 11..14 format version as little-endian u32 | |
52 | // 15..22 size in bytes of deflate compressed LLVM bitcode as | |
53 | // little-endian u64 | |
54 | // 23.. compressed LLVM bitcode | |
55 | ||
56 | // This is the "magic number" expected at the beginning of a LLVM bytecode | |
57 | // object in an rlib. | |
58 | pub const RLIB_BYTECODE_OBJECT_MAGIC: &'static [u8] = b"RUST_OBJECT"; | |
59 | ||
60 | // The version number this compiler will write to bytecode objects in rlibs | |
61 | pub const RLIB_BYTECODE_OBJECT_VERSION: u32 = 1; | |
62 | ||
63 | // The offset in bytes the bytecode object format version number can be found at | |
c34b1796 | 64 | pub const RLIB_BYTECODE_OBJECT_VERSION_OFFSET: usize = 11; |
1a4d82fc JJ |
65 | |
66 | // The offset in bytes the size of the compressed bytecode can be found at in | |
67 | // format version 1 | |
c34b1796 | 68 | pub const RLIB_BYTECODE_OBJECT_V1_DATASIZE_OFFSET: usize = |
1a4d82fc JJ |
69 | RLIB_BYTECODE_OBJECT_VERSION_OFFSET + 4; |
70 | ||
71 | // The offset in bytes the compressed LLVM bytecode can be found at in format | |
72 | // version 1 | |
c34b1796 | 73 | pub const RLIB_BYTECODE_OBJECT_V1_DATA_OFFSET: usize = |
1a4d82fc JJ |
74 | RLIB_BYTECODE_OBJECT_V1_DATASIZE_OFFSET + 8; |
75 | ||
76 | ||
1a4d82fc JJ |
77 | pub fn find_crate_name(sess: Option<&Session>, |
78 | attrs: &[ast::Attribute], | |
79 | input: &Input) -> String { | |
85aaf69f | 80 | let validate = |s: String, span: Option<Span>| { |
92a42be0 | 81 | cstore::validate_crate_name(sess, &s[..], span); |
1a4d82fc JJ |
82 | s |
83 | }; | |
84 | ||
85 | // Look in attributes 100% of the time to make sure the attribute is marked | |
86 | // as used. After doing this, however, we still prioritize a crate name from | |
87 | // the command line over one found in the #[crate_name] attribute. If we | |
88 | // find both we ensure that they're the same later on as well. | |
89 | let attr_crate_name = attrs.iter().find(|at| at.check_name("crate_name")) | |
90 | .and_then(|at| at.value_str().map(|s| (at, s))); | |
91 | ||
92 | if let Some(sess) = sess { | |
93 | if let Some(ref s) = sess.opts.crate_name { | |
94 | if let Some((attr, ref name)) = attr_crate_name { | |
85aaf69f | 95 | if *s != &name[..] { |
1a4d82fc JJ |
96 | let msg = format!("--crate-name and #[crate_name] are \ |
97 | required to match, but `{}` != `{}`", | |
98 | s, name); | |
85aaf69f | 99 | sess.span_err(attr.span, &msg[..]); |
1a4d82fc JJ |
100 | } |
101 | } | |
102 | return validate(s.clone(), None); | |
103 | } | |
104 | } | |
105 | ||
106 | if let Some((attr, s)) = attr_crate_name { | |
85aaf69f | 107 | return validate(s.to_string(), Some(attr.span)); |
1a4d82fc JJ |
108 | } |
109 | if let Input::File(ref path) = *input { | |
c34b1796 AL |
110 | if let Some(s) = path.file_stem().and_then(|s| s.to_str()) { |
111 | if s.starts_with("-") { | |
112 | let msg = format!("crate names cannot start with a `-`, but \ | |
113 | `{}` has a leading hyphen", s); | |
114 | if let Some(sess) = sess { | |
115 | sess.err(&msg); | |
116 | } | |
117 | } else { | |
118 | return validate(s.replace("-", "_"), None); | |
119 | } | |
1a4d82fc JJ |
120 | } |
121 | } | |
122 | ||
c34b1796 | 123 | "rust_out".to_string() |
54a0048b | 124 | |
1a4d82fc JJ |
125 | } |
126 | ||
54a0048b | 127 | pub fn build_link_meta(tcx: &TyCtxt, |
9cc50fc6 SL |
128 | name: &str) |
129 | -> LinkMeta { | |
1a4d82fc | 130 | let r = LinkMeta { |
b039eaaf | 131 | crate_name: name.to_owned(), |
54a0048b | 132 | crate_hash: tcx.calculate_krate_hash(), |
1a4d82fc JJ |
133 | }; |
134 | info!("{:?}", r); | |
135 | return r; | |
136 | } | |
137 | ||
c1a9b12d SL |
138 | pub fn get_linker(sess: &Session) -> (String, Command) { |
139 | if let Some(ref linker) = sess.opts.cg.linker { | |
140 | (linker.clone(), Command::new(linker)) | |
141 | } else if sess.target.target.options.is_like_msvc { | |
142 | ("link.exe".to_string(), msvc::link_exe_cmd(sess)) | |
143 | } else { | |
144 | (sess.target.target.options.linker.clone(), | |
145 | Command::new(&sess.target.target.options.linker)) | |
1a4d82fc JJ |
146 | } |
147 | } | |
148 | ||
62682a34 SL |
149 | pub fn get_ar_prog(sess: &Session) -> String { |
150 | sess.opts.cg.ar.clone().unwrap_or_else(|| { | |
151 | sess.target.target.options.ar.clone() | |
152 | }) | |
153 | } | |
154 | ||
155 | fn command_path(sess: &Session) -> OsString { | |
156 | // The compiler's sysroot often has some bundled tools, so add it to the | |
157 | // PATH for the child. | |
158 | let mut new_path = sess.host_filesearch(PathKind::All) | |
159 | .get_tools_search_paths(); | |
160 | if let Some(path) = env::var_os("PATH") { | |
161 | new_path.extend(env::split_paths(&path)); | |
162 | } | |
7453a54e SL |
163 | if sess.target.target.options.is_like_msvc { |
164 | new_path.extend(msvc::host_dll_path()); | |
165 | } | |
62682a34 SL |
166 | env::join_paths(new_path).unwrap() |
167 | } | |
168 | ||
1a4d82fc | 169 | pub fn remove(sess: &Session, path: &Path) { |
c34b1796 | 170 | match fs::remove_file(path) { |
1a4d82fc JJ |
171 | Ok(..) => {} |
172 | Err(e) => { | |
173 | sess.err(&format!("failed to remove {}: {}", | |
174 | path.display(), | |
c34b1796 | 175 | e)); |
1a4d82fc JJ |
176 | } |
177 | } | |
178 | } | |
179 | ||
180 | /// Perform the linkage portion of the compilation phase. This will generate all | |
181 | /// of the requested outputs for this compilation session. | |
182 | pub fn link_binary(sess: &Session, | |
183 | trans: &CrateTranslation, | |
184 | outputs: &OutputFilenames, | |
c34b1796 | 185 | crate_name: &str) -> Vec<PathBuf> { |
1a4d82fc | 186 | let mut out_filenames = Vec::new(); |
62682a34 | 187 | for &crate_type in sess.crate_types.borrow().iter() { |
1a4d82fc | 188 | if invalid_output_for_target(sess, crate_type) { |
54a0048b SL |
189 | bug!("invalid output type `{:?}` for target os `{}`", |
190 | crate_type, sess.opts.target_triple); | |
1a4d82fc JJ |
191 | } |
192 | let out_file = link_binary_output(sess, trans, crate_type, outputs, | |
193 | crate_name); | |
194 | out_filenames.push(out_file); | |
195 | } | |
196 | ||
197 | // Remove the temporary object file and metadata if we aren't saving temps | |
198 | if !sess.opts.cg.save_temps { | |
c1a9b12d SL |
199 | for obj in object_filenames(sess, outputs) { |
200 | remove(sess, &obj); | |
1a4d82fc | 201 | } |
c1a9b12d | 202 | remove(sess, &outputs.with_extension("metadata.o")); |
1a4d82fc JJ |
203 | } |
204 | ||
205 | out_filenames | |
206 | } | |
207 | ||
208 | ||
209 | /// Returns default crate type for target | |
210 | /// | |
211 | /// Default crate type is used when crate type isn't provided neither | |
212 | /// through cmd line arguments nor through crate attributes | |
213 | /// | |
214 | /// It is CrateTypeExecutable for all platforms but iOS as there is no | |
215 | /// way to run iOS binaries anyway without jailbreaking and | |
216 | /// interaction with Rust code through static library is the only | |
217 | /// option for now | |
218 | pub fn default_output_for_target(sess: &Session) -> config::CrateType { | |
219 | if !sess.target.target.options.executables { | |
220 | config::CrateTypeStaticlib | |
221 | } else { | |
222 | config::CrateTypeExecutable | |
223 | } | |
224 | } | |
225 | ||
226 | /// Checks if target supports crate_type as output | |
227 | pub fn invalid_output_for_target(sess: &Session, | |
228 | crate_type: config::CrateType) -> bool { | |
229 | match (sess.target.target.options.dynamic_linking, | |
230 | sess.target.target.options.executables, crate_type) { | |
231 | (false, _, config::CrateTypeDylib) => true, | |
232 | (_, false, config::CrateTypeExecutable) => true, | |
233 | _ => false | |
234 | } | |
235 | } | |
236 | ||
237 | fn is_writeable(p: &Path) -> bool { | |
c34b1796 | 238 | match p.metadata() { |
1a4d82fc | 239 | Err(..) => true, |
c34b1796 | 240 | Ok(m) => !m.permissions().readonly() |
1a4d82fc JJ |
241 | } |
242 | } | |
243 | ||
244 | pub fn filename_for_input(sess: &Session, | |
245 | crate_type: config::CrateType, | |
c1a9b12d SL |
246 | crate_name: &str, |
247 | outputs: &OutputFilenames) -> PathBuf { | |
248 | let libname = format!("{}{}", crate_name, sess.opts.cg.extra_filename); | |
1a4d82fc JJ |
249 | match crate_type { |
250 | config::CrateTypeRlib => { | |
c1a9b12d | 251 | outputs.out_directory.join(&format!("lib{}.rlib", libname)) |
1a4d82fc JJ |
252 | } |
253 | config::CrateTypeDylib => { | |
c34b1796 AL |
254 | let (prefix, suffix) = (&sess.target.target.options.dll_prefix, |
255 | &sess.target.target.options.dll_suffix); | |
c1a9b12d SL |
256 | outputs.out_directory.join(&format!("{}{}{}", prefix, libname, |
257 | suffix)) | |
1a4d82fc JJ |
258 | } |
259 | config::CrateTypeStaticlib => { | |
7453a54e SL |
260 | let (prefix, suffix) = (&sess.target.target.options.staticlib_prefix, |
261 | &sess.target.target.options.staticlib_suffix); | |
262 | outputs.out_directory.join(&format!("{}{}{}", prefix, libname, | |
263 | suffix)) | |
1a4d82fc JJ |
264 | } |
265 | config::CrateTypeExecutable => { | |
c34b1796 | 266 | let suffix = &sess.target.target.options.exe_suffix; |
b039eaaf | 267 | let out_filename = outputs.path(OutputType::Exe); |
9346a6ac | 268 | if suffix.is_empty() { |
c34b1796 AL |
269 | out_filename.to_path_buf() |
270 | } else { | |
271 | out_filename.with_extension(&suffix[1..]) | |
272 | } | |
1a4d82fc JJ |
273 | } |
274 | } | |
275 | } | |
276 | ||
e9174d1e SL |
277 | pub fn each_linked_rlib(sess: &Session, |
278 | f: &mut FnMut(ast::CrateNum, &Path)) { | |
92a42be0 | 279 | let crates = sess.cstore.used_crates(LinkagePreference::RequireStatic).into_iter(); |
e9174d1e SL |
280 | let fmts = sess.dependency_formats.borrow(); |
281 | let fmts = fmts.get(&config::CrateTypeExecutable).or_else(|| { | |
282 | fmts.get(&config::CrateTypeStaticlib) | |
283 | }).unwrap_or_else(|| { | |
54a0048b | 284 | bug!("could not find formats for rlibs") |
e9174d1e SL |
285 | }); |
286 | for (cnum, path) in crates { | |
287 | match fmts[cnum as usize - 1] { | |
288 | Linkage::NotLinked | Linkage::IncludedFromDylib => continue, | |
289 | _ => {} | |
290 | } | |
92a42be0 | 291 | let name = sess.cstore.crate_name(cnum).clone(); |
e9174d1e SL |
292 | let path = match path { |
293 | Some(p) => p, | |
294 | None => { | |
295 | sess.fatal(&format!("could not find rlib for: `{}`", name)); | |
296 | } | |
297 | }; | |
298 | f(cnum, &path); | |
299 | } | |
300 | } | |
301 | ||
1a4d82fc JJ |
302 | fn link_binary_output(sess: &Session, |
303 | trans: &CrateTranslation, | |
304 | crate_type: config::CrateType, | |
305 | outputs: &OutputFilenames, | |
c34b1796 | 306 | crate_name: &str) -> PathBuf { |
c1a9b12d | 307 | let objects = object_filenames(sess, outputs); |
b039eaaf SL |
308 | let default_filename = filename_for_input(sess, crate_type, crate_name, |
309 | outputs); | |
310 | let out_filename = outputs.outputs.get(&OutputType::Exe) | |
311 | .and_then(|s| s.to_owned()) | |
312 | .or_else(|| outputs.single_output_file.clone()) | |
313 | .unwrap_or(default_filename); | |
1a4d82fc | 314 | |
c1a9b12d SL |
315 | // Make sure files are writeable. Mac, FreeBSD, and Windows system linkers |
316 | // check this already -- however, the Linux linker will happily overwrite a | |
317 | // read-only file. We should be consistent. | |
318 | for file in objects.iter().chain(Some(&out_filename)) { | |
319 | if !is_writeable(file) { | |
320 | sess.fatal(&format!("output file {} is not writeable -- check its \ | |
321 | permissions", file.display())); | |
322 | } | |
1a4d82fc JJ |
323 | } |
324 | ||
b039eaaf SL |
325 | let tmpdir = match TempDir::new("rustc") { |
326 | Ok(tmpdir) => tmpdir, | |
327 | Err(err) => sess.fatal(&format!("couldn't create a temp dir: {}", err)), | |
328 | }; | |
329 | ||
1a4d82fc JJ |
330 | match crate_type { |
331 | config::CrateTypeRlib => { | |
c1a9b12d SL |
332 | link_rlib(sess, Some(trans), &objects, &out_filename, |
333 | tmpdir.path()).build(); | |
1a4d82fc JJ |
334 | } |
335 | config::CrateTypeStaticlib => { | |
c1a9b12d | 336 | link_staticlib(sess, &objects, &out_filename, tmpdir.path()); |
1a4d82fc JJ |
337 | } |
338 | config::CrateTypeExecutable => { | |
e9174d1e | 339 | link_natively(sess, false, &objects, &out_filename, trans, outputs, |
c1a9b12d | 340 | tmpdir.path()); |
1a4d82fc JJ |
341 | } |
342 | config::CrateTypeDylib => { | |
e9174d1e | 343 | link_natively(sess, true, &objects, &out_filename, trans, outputs, |
c1a9b12d | 344 | tmpdir.path()); |
1a4d82fc JJ |
345 | } |
346 | } | |
347 | ||
348 | out_filename | |
349 | } | |
350 | ||
c1a9b12d SL |
351 | fn object_filenames(sess: &Session, outputs: &OutputFilenames) -> Vec<PathBuf> { |
352 | (0..sess.opts.cg.codegen_units).map(|i| { | |
353 | let ext = format!("{}.o", i); | |
b039eaaf | 354 | outputs.temp_path(OutputType::Object).with_extension(&ext) |
c1a9b12d SL |
355 | }).collect() |
356 | } | |
357 | ||
c34b1796 | 358 | fn archive_search_paths(sess: &Session) -> Vec<PathBuf> { |
1a4d82fc | 359 | let mut search = Vec::new(); |
85aaf69f | 360 | sess.target_filesearch(PathKind::Native).for_each_lib_search_path(|path, _| { |
c34b1796 | 361 | search.push(path.to_path_buf()); |
1a4d82fc JJ |
362 | }); |
363 | return search; | |
364 | } | |
365 | ||
c1a9b12d SL |
366 | fn archive_config<'a>(sess: &'a Session, |
367 | output: &Path, | |
368 | input: Option<&Path>) -> ArchiveConfig<'a> { | |
369 | ArchiveConfig { | |
370 | sess: sess, | |
371 | dst: output.to_path_buf(), | |
372 | src: input.map(|p| p.to_path_buf()), | |
373 | lib_search_paths: archive_search_paths(sess), | |
374 | ar_prog: get_ar_prog(sess), | |
375 | command_path: command_path(sess), | |
376 | } | |
377 | } | |
378 | ||
1a4d82fc JJ |
379 | // Create an 'rlib' |
380 | // | |
381 | // An rlib in its current incarnation is essentially a renamed .a file. The | |
382 | // rlib primarily contains the object file of the crate, but it also contains | |
383 | // all of the object files from native libraries. This is done by unzipping | |
384 | // native libraries and inserting all of the contents into this archive. | |
385 | fn link_rlib<'a>(sess: &'a Session, | |
386 | trans: Option<&CrateTranslation>, // None == no metadata/bytecode | |
c1a9b12d SL |
387 | objects: &[PathBuf], |
388 | out_filename: &Path, | |
389 | tmpdir: &Path) -> ArchiveBuilder<'a> { | |
390 | info!("preparing rlib from {:?} to {:?}", objects, out_filename); | |
391 | let mut ab = ArchiveBuilder::new(archive_config(sess, out_filename, None)); | |
392 | for obj in objects { | |
393 | ab.add_file(obj); | |
394 | } | |
1a4d82fc | 395 | |
92a42be0 | 396 | for (l, kind) in sess.cstore.used_libraries() { |
1a4d82fc | 397 | match kind { |
92a42be0 SL |
398 | NativeLibraryKind::NativeStatic => ab.add_native_library(&l), |
399 | NativeLibraryKind::NativeFramework | | |
400 | NativeLibraryKind::NativeUnknown => {} | |
1a4d82fc JJ |
401 | } |
402 | } | |
403 | ||
404 | // After adding all files to the archive, we need to update the | |
405 | // symbol table of the archive. | |
406 | ab.update_symbols(); | |
407 | ||
c1a9b12d SL |
408 | // For OSX/iOS, we must be careful to update symbols only when adding |
409 | // object files. We're about to start adding non-object files, so run | |
410 | // `ar` now to process the object files. | |
411 | if sess.target.target.options.is_like_osx && !ab.using_llvm() { | |
412 | ab.build(); | |
413 | } | |
1a4d82fc JJ |
414 | |
415 | // Note that it is important that we add all of our non-object "magical | |
416 | // files" *after* all of the object files in the archive. The reason for | |
417 | // this is as follows: | |
418 | // | |
419 | // * When performing LTO, this archive will be modified to remove | |
c1a9b12d | 420 | // objects from above. The reason for this is described below. |
1a4d82fc JJ |
421 | // |
422 | // * When the system linker looks at an archive, it will attempt to | |
423 | // determine the architecture of the archive in order to see whether its | |
424 | // linkable. | |
425 | // | |
426 | // The algorithm for this detection is: iterate over the files in the | |
427 | // archive. Skip magical SYMDEF names. Interpret the first file as an | |
428 | // object file. Read architecture from the object file. | |
429 | // | |
430 | // * As one can probably see, if "metadata" and "foo.bc" were placed | |
431 | // before all of the objects, then the architecture of this archive would | |
432 | // not be correctly inferred once 'foo.o' is removed. | |
433 | // | |
434 | // Basically, all this means is that this code should not move above the | |
435 | // code above. | |
436 | match trans { | |
437 | Some(trans) => { | |
438 | // Instead of putting the metadata in an object file section, rlibs | |
439 | // contain the metadata in a separate file. We use a temp directory | |
440 | // here so concurrent builds in the same directory don't try to use | |
441 | // the same filename for metadata (stomping over one another) | |
92a42be0 | 442 | let metadata = tmpdir.join(sess.cstore.metadata_filename()); |
c34b1796 AL |
443 | match fs::File::create(&metadata).and_then(|mut f| { |
444 | f.write_all(&trans.metadata) | |
445 | }) { | |
1a4d82fc JJ |
446 | Ok(..) => {} |
447 | Err(e) => { | |
62682a34 SL |
448 | sess.fatal(&format!("failed to write {}: {}", |
449 | metadata.display(), e)); | |
1a4d82fc JJ |
450 | } |
451 | } | |
c1a9b12d | 452 | ab.add_file(&metadata); |
1a4d82fc JJ |
453 | |
454 | // For LTO purposes, the bytecode of this library is also inserted | |
455 | // into the archive. If codegen_units > 1, we insert each of the | |
456 | // bitcode files. | |
c1a9b12d | 457 | for obj in objects { |
1a4d82fc JJ |
458 | // Note that we make sure that the bytecode filename in the |
459 | // archive is never exactly 16 bytes long by adding a 16 byte | |
460 | // extension to it. This is to work around a bug in LLDB that | |
461 | // would cause it to crash if the name of a file in an archive | |
462 | // was exactly 16 bytes. | |
c1a9b12d SL |
463 | let bc_filename = obj.with_extension("bc"); |
464 | let bc_deflated_filename = tmpdir.join({ | |
465 | obj.with_extension("bytecode.deflate").file_name().unwrap() | |
466 | }); | |
1a4d82fc | 467 | |
c34b1796 AL |
468 | let mut bc_data = Vec::new(); |
469 | match fs::File::open(&bc_filename).and_then(|mut f| { | |
470 | f.read_to_end(&mut bc_data) | |
471 | }) { | |
472 | Ok(..) => {} | |
1a4d82fc | 473 | Err(e) => sess.fatal(&format!("failed to read bytecode: {}", |
c34b1796 AL |
474 | e)) |
475 | } | |
1a4d82fc | 476 | |
c34b1796 | 477 | let bc_data_deflated = flate::deflate_bytes(&bc_data[..]); |
1a4d82fc JJ |
478 | |
479 | let mut bc_file_deflated = match fs::File::create(&bc_deflated_filename) { | |
480 | Ok(file) => file, | |
481 | Err(e) => { | |
c34b1796 AL |
482 | sess.fatal(&format!("failed to create compressed \ |
483 | bytecode file: {}", e)) | |
1a4d82fc JJ |
484 | } |
485 | }; | |
486 | ||
487 | match write_rlib_bytecode_object_v1(&mut bc_file_deflated, | |
c34b1796 | 488 | &bc_data_deflated) { |
1a4d82fc JJ |
489 | Ok(()) => {} |
490 | Err(e) => { | |
62682a34 SL |
491 | sess.fatal(&format!("failed to write compressed \ |
492 | bytecode: {}", e)); | |
1a4d82fc JJ |
493 | } |
494 | }; | |
495 | ||
c1a9b12d | 496 | ab.add_file(&bc_deflated_filename); |
1a4d82fc JJ |
497 | |
498 | // See the bottom of back::write::run_passes for an explanation | |
499 | // of when we do and don't keep .0.bc files around. | |
500 | let user_wants_numbered_bitcode = | |
b039eaaf | 501 | sess.opts.output_types.contains_key(&OutputType::Bitcode) && |
1a4d82fc JJ |
502 | sess.opts.cg.codegen_units > 1; |
503 | if !sess.opts.cg.save_temps && !user_wants_numbered_bitcode { | |
504 | remove(sess, &bc_filename); | |
505 | } | |
506 | } | |
507 | ||
508 | // After adding all files to the archive, we need to update the | |
509 | // symbol table of the archive. This currently dies on OSX (see | |
510 | // #11162), and isn't necessary there anyway | |
c1a9b12d | 511 | if !sess.target.target.options.is_like_osx || ab.using_llvm() { |
1a4d82fc JJ |
512 | ab.update_symbols(); |
513 | } | |
514 | } | |
515 | ||
516 | None => {} | |
517 | } | |
518 | ||
519 | ab | |
520 | } | |
521 | ||
c34b1796 AL |
522 | fn write_rlib_bytecode_object_v1(writer: &mut Write, |
523 | bc_data_deflated: &[u8]) -> io::Result<()> { | |
1a4d82fc JJ |
524 | let bc_data_deflated_size: u64 = bc_data_deflated.len() as u64; |
525 | ||
54a0048b SL |
526 | writer.write_all(RLIB_BYTECODE_OBJECT_MAGIC)?; |
527 | writer.write_all(&[1, 0, 0, 0])?; | |
528 | writer.write_all(&[ | |
c34b1796 AL |
529 | (bc_data_deflated_size >> 0) as u8, |
530 | (bc_data_deflated_size >> 8) as u8, | |
531 | (bc_data_deflated_size >> 16) as u8, | |
532 | (bc_data_deflated_size >> 24) as u8, | |
533 | (bc_data_deflated_size >> 32) as u8, | |
534 | (bc_data_deflated_size >> 40) as u8, | |
535 | (bc_data_deflated_size >> 48) as u8, | |
536 | (bc_data_deflated_size >> 56) as u8, | |
54a0048b SL |
537 | ])?; |
538 | writer.write_all(&bc_data_deflated)?; | |
1a4d82fc JJ |
539 | |
540 | let number_of_bytes_written_so_far = | |
541 | RLIB_BYTECODE_OBJECT_MAGIC.len() + // magic id | |
542 | mem::size_of_val(&RLIB_BYTECODE_OBJECT_VERSION) + // version | |
543 | mem::size_of_val(&bc_data_deflated_size) + // data size field | |
c34b1796 | 544 | bc_data_deflated_size as usize; // actual data |
1a4d82fc JJ |
545 | |
546 | // If the number of bytes written to the object so far is odd, add a | |
547 | // padding byte to make it even. This works around a crash bug in LLDB | |
548 | // (see issue #15950) | |
549 | if number_of_bytes_written_so_far % 2 == 1 { | |
54a0048b | 550 | writer.write_all(&[0])?; |
1a4d82fc JJ |
551 | } |
552 | ||
553 | return Ok(()); | |
554 | } | |
555 | ||
556 | // Create a static archive | |
557 | // | |
558 | // This is essentially the same thing as an rlib, but it also involves adding | |
559 | // all of the upstream crates' objects into the archive. This will slurp in | |
560 | // all of the native libraries of upstream dependencies as well. | |
561 | // | |
562 | // Additionally, there's no way for us to link dynamic libraries, so we warn | |
563 | // about all dynamic library dependencies that they're not linked in. | |
564 | // | |
565 | // There's no need to include metadata in a static archive, so ensure to not | |
566 | // link in the metadata object file (and also don't prepare the archive with a | |
567 | // metadata file). | |
c1a9b12d SL |
568 | fn link_staticlib(sess: &Session, objects: &[PathBuf], out_filename: &Path, |
569 | tempdir: &Path) { | |
570 | let mut ab = link_rlib(sess, None, objects, out_filename, tempdir); | |
571 | if sess.target.target.options.is_like_osx && !ab.using_llvm() { | |
572 | ab.build(); | |
573 | } | |
1a4d82fc | 574 | if !sess.target.target.options.no_compiler_rt { |
b039eaaf | 575 | ab.add_native_library("compiler-rt"); |
1a4d82fc JJ |
576 | } |
577 | ||
1a4d82fc JJ |
578 | let mut all_native_libs = vec![]; |
579 | ||
e9174d1e | 580 | each_linked_rlib(sess, &mut |cnum, path| { |
92a42be0 | 581 | let name = sess.cstore.crate_name(cnum); |
e9174d1e | 582 | ab.add_rlib(path, &name, sess.lto()).unwrap(); |
1a4d82fc | 583 | |
92a42be0 | 584 | let native_libs = sess.cstore.native_libraries(cnum); |
62682a34 | 585 | all_native_libs.extend(native_libs); |
e9174d1e | 586 | }); |
1a4d82fc JJ |
587 | |
588 | ab.update_symbols(); | |
c1a9b12d | 589 | ab.build(); |
1a4d82fc JJ |
590 | |
591 | if !all_native_libs.is_empty() { | |
9cc50fc6 SL |
592 | sess.note_without_error("link against the following native artifacts when linking against \ |
593 | this static library"); | |
594 | sess.note_without_error("the order and any duplication can be significant on some \ | |
595 | platforms, and so may need to be preserved"); | |
1a4d82fc JJ |
596 | } |
597 | ||
85aaf69f | 598 | for &(kind, ref lib) in &all_native_libs { |
1a4d82fc | 599 | let name = match kind { |
92a42be0 SL |
600 | NativeLibraryKind::NativeStatic => "static library", |
601 | NativeLibraryKind::NativeUnknown => "library", | |
602 | NativeLibraryKind::NativeFramework => "framework", | |
1a4d82fc | 603 | }; |
9cc50fc6 | 604 | sess.note_without_error(&format!("{}: {}", name, *lib)); |
1a4d82fc JJ |
605 | } |
606 | } | |
607 | ||
608 | // Create a dynamic library or executable | |
609 | // | |
610 | // This will invoke the system linker/cc to create the resulting file. This | |
611 | // links to all upstream files as well. | |
e9174d1e | 612 | fn link_natively(sess: &Session, dylib: bool, |
c1a9b12d | 613 | objects: &[PathBuf], out_filename: &Path, |
e9174d1e | 614 | trans: &CrateTranslation, |
c1a9b12d SL |
615 | outputs: &OutputFilenames, |
616 | tmpdir: &Path) { | |
617 | info!("preparing dylib? ({}) from {:?} to {:?}", dylib, objects, | |
62682a34 | 618 | out_filename); |
1a4d82fc JJ |
619 | |
620 | // The invocations of cc share some flags across platforms | |
c1a9b12d | 621 | let (pname, mut cmd) = get_linker(sess); |
62682a34 | 622 | cmd.env("PATH", command_path(sess)); |
1a4d82fc | 623 | |
d9579d0f | 624 | let root = sess.target_filesearch(PathKind::Native).get_lib_path(); |
c34b1796 | 625 | cmd.args(&sess.target.target.options.pre_link_args); |
92a42be0 SL |
626 | |
627 | let pre_link_objects = if dylib { | |
628 | &sess.target.target.options.pre_link_objects_dll | |
629 | } else { | |
630 | &sess.target.target.options.pre_link_objects_exe | |
631 | }; | |
632 | for obj in pre_link_objects { | |
d9579d0f AL |
633 | cmd.arg(root.join(obj)); |
634 | } | |
635 | ||
62682a34 SL |
636 | { |
637 | let mut linker = if sess.target.target.options.is_like_msvc { | |
638 | Box::new(MsvcLinker { cmd: &mut cmd, sess: &sess }) as Box<Linker> | |
639 | } else { | |
640 | Box::new(GnuLinker { cmd: &mut cmd, sess: &sess }) as Box<Linker> | |
641 | }; | |
c1a9b12d | 642 | link_args(&mut *linker, sess, dylib, tmpdir, |
e9174d1e | 643 | objects, out_filename, trans, outputs); |
62682a34 SL |
644 | if !sess.target.target.options.no_compiler_rt { |
645 | linker.link_staticlib("compiler-rt"); | |
646 | } | |
1a4d82fc | 647 | } |
92a42be0 | 648 | cmd.args(&sess.target.target.options.late_link_args); |
d9579d0f AL |
649 | for obj in &sess.target.target.options.post_link_objects { |
650 | cmd.arg(root.join(obj)); | |
651 | } | |
652 | cmd.args(&sess.target.target.options.post_link_args); | |
1a4d82fc JJ |
653 | |
654 | if sess.opts.debugging_opts.print_link_args { | |
85aaf69f | 655 | println!("{:?}", &cmd); |
1a4d82fc JJ |
656 | } |
657 | ||
658 | // May have not found libraries in the right formats. | |
659 | sess.abort_if_errors(); | |
660 | ||
661 | // Invoke the system linker | |
62682a34 | 662 | info!("{:?}", &cmd); |
e9174d1e | 663 | let prog = time(sess.time_passes(), "running linker", || cmd.output()); |
1a4d82fc JJ |
664 | match prog { |
665 | Ok(prog) => { | |
b039eaaf SL |
666 | fn escape_string(s: &[u8]) -> String { |
667 | str::from_utf8(s).map(|s| s.to_owned()) | |
668 | .unwrap_or_else(|_| { | |
669 | let mut x = "Non-UTF-8 output: ".to_string(); | |
670 | x.extend(s.iter() | |
671 | .flat_map(|&b| ascii::escape_default(b)) | |
672 | .map(|b| char::from_u32(b as u32).unwrap())); | |
673 | x | |
674 | }) | |
675 | } | |
1a4d82fc | 676 | if !prog.status.success() { |
c34b1796 | 677 | let mut output = prog.stderr.clone(); |
92a42be0 | 678 | output.extend_from_slice(&prog.stdout); |
9cc50fc6 SL |
679 | sess.struct_err(&format!("linking with `{}` failed: {}", |
680 | pname, | |
681 | prog.status)) | |
682 | .note(&format!("{:?}", &cmd)) | |
7453a54e | 683 | .note(&escape_string(&output[..])) |
9cc50fc6 | 684 | .emit(); |
1a4d82fc JJ |
685 | sess.abort_if_errors(); |
686 | } | |
b039eaaf SL |
687 | info!("linker stderr:\n{}", escape_string(&prog.stderr[..])); |
688 | info!("linker stdout:\n{}", escape_string(&prog.stdout[..])); | |
1a4d82fc JJ |
689 | }, |
690 | Err(e) => { | |
62682a34 | 691 | sess.fatal(&format!("could not exec the linker `{}`: {}", pname, e)); |
1a4d82fc JJ |
692 | } |
693 | } | |
694 | ||
695 | ||
696 | // On OSX, debuggers need this utility to get run to do some munging of | |
697 | // the symbols | |
698 | if sess.target.target.options.is_like_osx && sess.opts.debuginfo != NoDebugInfo { | |
699 | match Command::new("dsymutil").arg(out_filename).output() { | |
700 | Ok(..) => {} | |
62682a34 | 701 | Err(e) => sess.fatal(&format!("failed to run dsymutil: {}", e)), |
1a4d82fc JJ |
702 | } |
703 | } | |
704 | } | |
705 | ||
62682a34 | 706 | fn link_args(cmd: &mut Linker, |
1a4d82fc JJ |
707 | sess: &Session, |
708 | dylib: bool, | |
709 | tmpdir: &Path, | |
c1a9b12d SL |
710 | objects: &[PathBuf], |
711 | out_filename: &Path, | |
e9174d1e | 712 | trans: &CrateTranslation, |
c1a9b12d | 713 | outputs: &OutputFilenames) { |
1a4d82fc JJ |
714 | |
715 | // The default library location, we need this to find the runtime. | |
716 | // The location of crates will be determined as needed. | |
717 | let lib_path = sess.target_filesearch(PathKind::All).get_lib_path(); | |
718 | ||
719 | // target descriptor | |
720 | let t = &sess.target.target; | |
721 | ||
62682a34 | 722 | cmd.include_path(&fix_windows_verbatim_for_gcc(&lib_path)); |
c1a9b12d SL |
723 | for obj in objects { |
724 | cmd.add_object(obj); | |
725 | } | |
62682a34 | 726 | cmd.output_filename(out_filename); |
1a4d82fc | 727 | |
e9174d1e SL |
728 | // If we're building a dynamic library then some platforms need to make sure |
729 | // that all symbols are exported correctly from the dynamic library. | |
730 | if dylib { | |
731 | cmd.export_symbols(sess, trans, tmpdir); | |
1a4d82fc JJ |
732 | } |
733 | ||
734 | // When linking a dynamic library, we put the metadata into a section of the | |
735 | // executable. This metadata is in a separate object file from the main | |
736 | // object file, so we link that in here. | |
737 | if dylib { | |
c1a9b12d | 738 | cmd.add_object(&outputs.with_extension("metadata.o")); |
1a4d82fc JJ |
739 | } |
740 | ||
62682a34 SL |
741 | // Try to strip as much out of the generated object by removing unused |
742 | // sections if possible. See more comments in linker.rs | |
7453a54e SL |
743 | if !sess.opts.cg.link_dead_code { |
744 | cmd.gc_sections(dylib); | |
745 | } | |
1a4d82fc | 746 | |
92a42be0 | 747 | let used_link_args = sess.cstore.used_link_args(); |
1a4d82fc | 748 | |
62682a34 | 749 | if !dylib && t.options.position_independent_executables { |
1a4d82fc JJ |
750 | let empty_vec = Vec::new(); |
751 | let empty_str = String::new(); | |
752 | let args = sess.opts.cg.link_args.as_ref().unwrap_or(&empty_vec); | |
753 | let mut args = args.iter().chain(used_link_args.iter()); | |
62682a34 SL |
754 | let relocation_model = sess.opts.cg.relocation_model.as_ref() |
755 | .unwrap_or(&empty_str); | |
756 | if (t.options.relocation_model == "pic" || *relocation_model == "pic") | |
1a4d82fc | 757 | && !args.any(|x| *x == "-static") { |
62682a34 | 758 | cmd.position_independent_executable(); |
1a4d82fc JJ |
759 | } |
760 | } | |
761 | ||
62682a34 SL |
762 | // Pass optimization flags down to the linker. |
763 | cmd.optimize(); | |
1a4d82fc | 764 | |
c1a9b12d SL |
765 | // Pass debuginfo flags down to the linker. |
766 | cmd.debuginfo(); | |
767 | ||
1a4d82fc JJ |
768 | // We want to prevent the compiler from accidentally leaking in any system |
769 | // libraries, so we explicitly ask gcc to not link to any libraries by | |
770 | // default. Note that this does not happen for windows because windows pulls | |
771 | // in some large number of libraries and I couldn't quite figure out which | |
772 | // subset we wanted. | |
b039eaaf SL |
773 | if t.options.no_default_libraries { |
774 | cmd.no_default_libraries(); | |
775 | } | |
1a4d82fc JJ |
776 | |
777 | // Take careful note of the ordering of the arguments we pass to the linker | |
778 | // here. Linkers will assume that things on the left depend on things to the | |
779 | // right. Things on the right cannot depend on things on the left. This is | |
780 | // all formally implemented in terms of resolving symbols (libs on the right | |
781 | // resolve unknown symbols of libs on the left, but not vice versa). | |
782 | // | |
783 | // For this reason, we have organized the arguments we pass to the linker as | |
784 | // such: | |
785 | // | |
786 | // 1. The local object that LLVM just generated | |
b039eaaf SL |
787 | // 2. Local native libraries |
788 | // 3. Upstream rust libraries | |
1a4d82fc JJ |
789 | // 4. Upstream native libraries |
790 | // | |
b039eaaf SL |
791 | // The rationale behind this ordering is that those items lower down in the |
792 | // list can't depend on items higher up in the list. For example nothing can | |
793 | // depend on what we just generated (e.g. that'd be a circular dependency). | |
794 | // Upstream rust libraries are not allowed to depend on our local native | |
795 | // libraries as that would violate the structure of the DAG, in that | |
796 | // scenario they are required to link to them as well in a shared fashion. | |
1a4d82fc | 797 | // |
b039eaaf SL |
798 | // Note that upstream rust libraries may contain native dependencies as |
799 | // well, but they also can't depend on what we just started to add to the | |
800 | // link line. And finally upstream native libraries can't depend on anything | |
801 | // in this DAG so far because they're only dylibs and dylibs can only depend | |
802 | // on other dylibs (e.g. other native deps). | |
1a4d82fc | 803 | add_local_native_libraries(cmd, sess); |
b039eaaf | 804 | add_upstream_rust_crates(cmd, sess, dylib, tmpdir); |
1a4d82fc JJ |
805 | add_upstream_native_libraries(cmd, sess); |
806 | ||
807 | // # Telling the linker what we're doing | |
808 | ||
809 | if dylib { | |
62682a34 | 810 | cmd.build_dylib(out_filename); |
1a4d82fc JJ |
811 | } |
812 | ||
813 | // FIXME (#2397): At some point we want to rpath our guesses as to | |
814 | // where extern libraries might live, based on the | |
815 | // addl_lib_search_paths | |
816 | if sess.opts.cg.rpath { | |
817 | let sysroot = sess.sysroot(); | |
c34b1796 AL |
818 | let target_triple = &sess.opts.target_triple; |
819 | let mut get_install_prefix_lib_path = || { | |
1a4d82fc JJ |
820 | let install_prefix = option_env!("CFG_PREFIX").expect("CFG_PREFIX"); |
821 | let tlib = filesearch::relative_target_lib_path(sysroot, target_triple); | |
c34b1796 | 822 | let mut path = PathBuf::from(install_prefix); |
1a4d82fc JJ |
823 | path.push(&tlib); |
824 | ||
825 | path | |
826 | }; | |
c34b1796 | 827 | let mut rpath_config = RPathConfig { |
92a42be0 | 828 | used_crates: sess.cstore.used_crates(LinkagePreference::RequireDynamic), |
c34b1796 | 829 | out_filename: out_filename.to_path_buf(), |
1a4d82fc JJ |
830 | has_rpath: sess.target.target.options.has_rpath, |
831 | is_like_osx: sess.target.target.options.is_like_osx, | |
9cc50fc6 | 832 | linker_is_gnu: sess.target.target.options.linker_is_gnu, |
c34b1796 | 833 | get_install_prefix_lib_path: &mut get_install_prefix_lib_path, |
1a4d82fc | 834 | }; |
c34b1796 | 835 | cmd.args(&rpath::get_rpath_flags(&mut rpath_config)); |
1a4d82fc JJ |
836 | } |
837 | ||
838 | // Finally add all the linker arguments provided on the command line along | |
839 | // with any #[link_args] attributes found inside the crate | |
62682a34 SL |
840 | if let Some(ref args) = sess.opts.cg.link_args { |
841 | cmd.args(args); | |
842 | } | |
843 | cmd.args(&used_link_args); | |
1a4d82fc JJ |
844 | } |
845 | ||
846 | // # Native library linking | |
847 | // | |
848 | // User-supplied library search paths (-L on the command line). These are | |
849 | // the same paths used to find Rust crates, so some of them may have been | |
850 | // added already by the previous crate linking code. This only allows them | |
851 | // to be found at compile time so it is still entirely up to outside | |
852 | // forces to make sure that library can be found at runtime. | |
853 | // | |
854 | // Also note that the native libraries linked here are only the ones located | |
855 | // in the current crate. Upstream crates with native library dependencies | |
856 | // may have their native library pulled in above. | |
62682a34 | 857 | fn add_local_native_libraries(cmd: &mut Linker, sess: &Session) { |
85aaf69f SL |
858 | sess.target_filesearch(PathKind::All).for_each_lib_search_path(|path, k| { |
859 | match k { | |
62682a34 SL |
860 | PathKind::Framework => { cmd.framework_path(path); } |
861 | _ => { cmd.include_path(&fix_windows_verbatim_for_gcc(path)); } | |
85aaf69f | 862 | } |
1a4d82fc JJ |
863 | }); |
864 | ||
92a42be0 | 865 | let libs = sess.cstore.used_libraries(); |
1a4d82fc | 866 | |
85aaf69f | 867 | let staticlibs = libs.iter().filter_map(|&(ref l, kind)| { |
92a42be0 | 868 | if kind == NativeLibraryKind::NativeStatic {Some(l)} else {None} |
1a4d82fc | 869 | }); |
85aaf69f | 870 | let others = libs.iter().filter(|&&(_, kind)| { |
92a42be0 | 871 | kind != NativeLibraryKind::NativeStatic |
1a4d82fc JJ |
872 | }); |
873 | ||
62682a34 SL |
874 | // Some platforms take hints about whether a library is static or dynamic. |
875 | // For those that support this, we ensure we pass the option if the library | |
876 | // was flagged "static" (most defaults are dynamic) to ensure that if | |
877 | // libfoo.a and libfoo.so both exist that the right one is chosen. | |
878 | cmd.hint_static(); | |
879 | ||
1a4d82fc JJ |
880 | let search_path = archive_search_paths(sess); |
881 | for l in staticlibs { | |
62682a34 SL |
882 | // Here we explicitly ask that the entire archive is included into the |
883 | // result artifact. For more details see #15460, but the gist is that | |
884 | // the linker will strip away any unused objects in the archive if we | |
885 | // don't otherwise explicitly reference them. This can occur for | |
886 | // libraries which are just providing bindings, libraries with generic | |
887 | // functions, etc. | |
888 | cmd.link_whole_staticlib(l, &search_path); | |
1a4d82fc JJ |
889 | } |
890 | ||
62682a34 SL |
891 | cmd.hint_dynamic(); |
892 | ||
1a4d82fc JJ |
893 | for &(ref l, kind) in others { |
894 | match kind { | |
92a42be0 SL |
895 | NativeLibraryKind::NativeUnknown => cmd.link_dylib(l), |
896 | NativeLibraryKind::NativeFramework => cmd.link_framework(l), | |
54a0048b | 897 | NativeLibraryKind::NativeStatic => bug!(), |
1a4d82fc JJ |
898 | } |
899 | } | |
900 | } | |
901 | ||
902 | // # Rust Crate linking | |
903 | // | |
904 | // Rust crates are not considered at all when creating an rlib output. All | |
905 | // dependencies will be linked when producing the final output (instead of | |
906 | // the intermediate rlib version) | |
62682a34 | 907 | fn add_upstream_rust_crates(cmd: &mut Linker, sess: &Session, |
e9174d1e | 908 | dylib: bool, tmpdir: &Path) { |
1a4d82fc JJ |
909 | // All of the heavy lifting has previously been accomplished by the |
910 | // dependency_format module of the compiler. This is just crawling the | |
911 | // output of that module, adding crates as necessary. | |
912 | // | |
913 | // Linking to a rlib involves just passing it to the linker (the linker | |
914 | // will slurp up the object files inside), and linking to a dynamic library | |
915 | // involves just passing the right -l flag. | |
916 | ||
e9174d1e | 917 | let formats = sess.dependency_formats.borrow(); |
1a4d82fc | 918 | let data = if dylib { |
e9174d1e | 919 | formats.get(&config::CrateTypeDylib).unwrap() |
1a4d82fc | 920 | } else { |
e9174d1e | 921 | formats.get(&config::CrateTypeExecutable).unwrap() |
1a4d82fc JJ |
922 | }; |
923 | ||
924 | // Invoke get_used_crates to ensure that we get a topological sorting of | |
925 | // crates. | |
92a42be0 | 926 | let deps = sess.cstore.used_crates(LinkagePreference::RequireDynamic); |
1a4d82fc | 927 | |
85aaf69f | 928 | for &(cnum, _) in &deps { |
1a4d82fc JJ |
929 | // We may not pass all crates through to the linker. Some crates may |
930 | // appear statically in an existing dylib, meaning we'll pick up all the | |
931 | // symbols from the dylib. | |
92a42be0 | 932 | let src = sess.cstore.used_crate_source(cnum); |
e9174d1e SL |
933 | match data[cnum as usize - 1] { |
934 | Linkage::NotLinked | | |
935 | Linkage::IncludedFromDylib => {} | |
936 | Linkage::Static => { | |
c1a9b12d | 937 | add_static_crate(cmd, sess, tmpdir, dylib, &src.rlib.unwrap().0) |
1a4d82fc | 938 | } |
e9174d1e SL |
939 | Linkage::Dynamic => { |
940 | add_dynamic_crate(cmd, sess, &src.dylib.unwrap().0) | |
941 | } | |
1a4d82fc | 942 | } |
1a4d82fc JJ |
943 | } |
944 | ||
945 | // Converts a library file-stem into a cc -l argument | |
c34b1796 AL |
946 | fn unlib<'a>(config: &config::Config, stem: &'a str) -> &'a str { |
947 | if stem.starts_with("lib") && !config.target.options.is_like_windows { | |
1a4d82fc JJ |
948 | &stem[3..] |
949 | } else { | |
950 | stem | |
951 | } | |
952 | } | |
953 | ||
954 | // Adds the static "rlib" versions of all crates to the command line. | |
c1a9b12d SL |
955 | // There's a bit of magic which happens here specifically related to LTO and |
956 | // dynamic libraries. Specifically: | |
957 | // | |
958 | // * For LTO, we remove upstream object files. | |
959 | // * For dylibs we remove metadata and bytecode from upstream rlibs | |
960 | // | |
961 | // When performing LTO, all of the bytecode from the upstream libraries has | |
962 | // already been included in our object file output. As a result we need to | |
963 | // remove the object files in the upstream libraries so the linker doesn't | |
964 | // try to include them twice (or whine about duplicate symbols). We must | |
965 | // continue to include the rest of the rlib, however, as it may contain | |
966 | // static native libraries which must be linked in. | |
967 | // | |
968 | // When making a dynamic library, linkers by default don't include any | |
969 | // object files in an archive if they're not necessary to resolve the link. | |
970 | // We basically want to convert the archive (rlib) to a dylib, though, so we | |
971 | // *do* want everything included in the output, regardless of whether the | |
972 | // linker thinks it's needed or not. As a result we must use the | |
973 | // --whole-archive option (or the platform equivalent). When using this | |
974 | // option the linker will fail if there are non-objects in the archive (such | |
975 | // as our own metadata and/or bytecode). All in all, for rlibs to be | |
976 | // entirely included in dylibs, we need to remove all non-object files. | |
977 | // | |
978 | // Note, however, that if we're not doing LTO or we're not producing a dylib | |
979 | // (aka we're making an executable), we can just pass the rlib blindly to | |
980 | // the linker (fast) because it's fine if it's not actually included as | |
981 | // we're at the end of the dependency chain. | |
62682a34 | 982 | fn add_static_crate(cmd: &mut Linker, sess: &Session, tmpdir: &Path, |
c1a9b12d SL |
983 | dylib: bool, cratepath: &Path) { |
984 | if !sess.lto() && !dylib { | |
985 | cmd.link_rlib(&fix_windows_verbatim_for_gcc(cratepath)); | |
986 | return | |
987 | } | |
988 | ||
989 | let dst = tmpdir.join(cratepath.file_name().unwrap()); | |
990 | let name = cratepath.file_name().unwrap().to_str().unwrap(); | |
991 | let name = &name[3..name.len() - 5]; // chop off lib/.rlib | |
992 | ||
e9174d1e | 993 | time(sess.time_passes(), &format!("altering {}.rlib", name), || { |
c1a9b12d SL |
994 | let cfg = archive_config(sess, &dst, Some(cratepath)); |
995 | let mut archive = ArchiveBuilder::new(cfg); | |
92a42be0 | 996 | archive.remove_file(sess.cstore.metadata_filename()); |
c1a9b12d SL |
997 | archive.update_symbols(); |
998 | ||
999 | let mut any_objects = false; | |
1000 | for f in archive.src_files() { | |
1001 | if f.ends_with("bytecode.deflate") { | |
1002 | archive.remove_file(&f); | |
1003 | continue | |
1a4d82fc | 1004 | } |
c1a9b12d SL |
1005 | let canonical = f.replace("-", "_"); |
1006 | let canonical_name = name.replace("-", "_"); | |
1007 | if sess.lto() && canonical.starts_with(&canonical_name) && | |
1008 | canonical.ends_with(".o") { | |
1009 | let num = &f[name.len()..f.len() - 2]; | |
1010 | if num.len() > 0 && num[1..].parse::<u32>().is_ok() { | |
1011 | archive.remove_file(&f); | |
1012 | continue | |
1a4d82fc JJ |
1013 | } |
1014 | } | |
c1a9b12d SL |
1015 | any_objects = true; |
1016 | } | |
1017 | ||
1018 | if any_objects { | |
1019 | archive.build(); | |
7453a54e SL |
1020 | if dylib { |
1021 | cmd.link_whole_rlib(&fix_windows_verbatim_for_gcc(&dst)); | |
1022 | } else { | |
1023 | cmd.link_rlib(&fix_windows_verbatim_for_gcc(&dst)); | |
1024 | } | |
c1a9b12d SL |
1025 | } |
1026 | }); | |
1a4d82fc JJ |
1027 | } |
1028 | ||
1029 | // Same thing as above, but for dynamic crates instead of static crates. | |
62682a34 | 1030 | fn add_dynamic_crate(cmd: &mut Linker, sess: &Session, cratepath: &Path) { |
1a4d82fc JJ |
1031 | // If we're performing LTO, then it should have been previously required |
1032 | // that all upstream rust dependencies were available in an rlib format. | |
1033 | assert!(!sess.lto()); | |
1034 | ||
1035 | // Just need to tell the linker about where the library lives and | |
1036 | // what its name is | |
c1a9b12d SL |
1037 | let parent = cratepath.parent(); |
1038 | if let Some(dir) = parent { | |
62682a34 | 1039 | cmd.include_path(&fix_windows_verbatim_for_gcc(dir)); |
c34b1796 AL |
1040 | } |
1041 | let filestem = cratepath.file_stem().unwrap().to_str().unwrap(); | |
c1a9b12d SL |
1042 | cmd.link_rust_dylib(&unlib(&sess.target, filestem), |
1043 | parent.unwrap_or(Path::new(""))); | |
1a4d82fc JJ |
1044 | } |
1045 | } | |
1046 | ||
1047 | // Link in all of our upstream crates' native dependencies. Remember that | |
1048 | // all of these upstream native dependencies are all non-static | |
1049 | // dependencies. We've got two cases then: | |
1050 | // | |
1051 | // 1. The upstream crate is an rlib. In this case we *must* link in the | |
1052 | // native dependency because the rlib is just an archive. | |
1053 | // | |
1054 | // 2. The upstream crate is a dylib. In order to use the dylib, we have to | |
1055 | // have the dependency present on the system somewhere. Thus, we don't | |
1056 | // gain a whole lot from not linking in the dynamic dependency to this | |
1057 | // crate as well. | |
1058 | // | |
1059 | // The use case for this is a little subtle. In theory the native | |
1060 | // dependencies of a crate are purely an implementation detail of the crate | |
1061 | // itself, but the problem arises with generic and inlined functions. If a | |
1062 | // generic function calls a native function, then the generic function must | |
1063 | // be instantiated in the target crate, meaning that the native symbol must | |
1064 | // also be resolved in the target crate. | |
62682a34 | 1065 | fn add_upstream_native_libraries(cmd: &mut Linker, sess: &Session) { |
1a4d82fc JJ |
1066 | // Be sure to use a topological sorting of crates because there may be |
1067 | // interdependencies between native libraries. When passing -nodefaultlibs, | |
1068 | // for example, almost all native libraries depend on libc, so we have to | |
1069 | // make sure that's all the way at the right (liblibc is near the base of | |
1070 | // the dependency chain). | |
1071 | // | |
1072 | // This passes RequireStatic, but the actual requirement doesn't matter, | |
1073 | // we're just getting an ordering of crate numbers, we're not worried about | |
1074 | // the paths. | |
92a42be0 | 1075 | let crates = sess.cstore.used_crates(LinkagePreference::RequireStatic); |
85aaf69f | 1076 | for (cnum, _) in crates { |
92a42be0 | 1077 | let libs = sess.cstore.native_libraries(cnum); |
85aaf69f | 1078 | for &(kind, ref lib) in &libs { |
1a4d82fc | 1079 | match kind { |
92a42be0 SL |
1080 | NativeLibraryKind::NativeUnknown => cmd.link_dylib(lib), |
1081 | NativeLibraryKind::NativeFramework => cmd.link_framework(lib), | |
1082 | NativeLibraryKind::NativeStatic => { | |
54a0048b | 1083 | bug!("statics shouldn't be propagated"); |
1a4d82fc JJ |
1084 | } |
1085 | } | |
1086 | } | |
1087 | } | |
1088 | } |