Skip to content

Commit 19778e4

Browse files
committed
---
yaml --- r: 218322 b: refs/heads/tmp c: 9bc8e6d h: refs/heads/master v: v3
1 parent 15dfc99 commit 19778e4

File tree

17 files changed

+230
-130
lines changed

17 files changed

+230
-130
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ refs/tags/0.11.0: e1247cb1d0d681be034adb4b558b5a0c0d5720f9
2525
refs/tags/0.12.0: f0c419429ef30723ceaf6b42f9b5a2aeb5d2e2d1
2626
refs/heads/beta: ebf0c83cb9c6508e9564cb58337df2ad52b56430
2727
refs/tags/1.0.0-alpha: e42bd6d93a1d3433c486200587f8f9e12590a4d7
28-
refs/heads/tmp: d23239b48e2066d3f38eb03e2429427bffade822
28+
refs/heads/tmp: 9bc8e6d1472a57441afe3592078838d2bc767996
2929
refs/tags/1.0.0-alpha.2: 4c705f6bc559886632d3871b04f58aab093bfa2f
3030
refs/tags/homu-tmp: d0fdfbfb0d34f196f52b9d15215723c4785c4afa
3131
refs/tags/1.0.0-beta: 8cbb92b53468ee2b0c2d3eeb8567005953d40828

branches/tmp/src/liballoc/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,4 +148,5 @@ pub fn oom() -> ! {
148148
// optimize it out).
149149
#[doc(hidden)]
150150
#[unstable(feature = "issue_14344_fixme")]
151+
#[cfg(stage0)]
151152
pub fn fixme_14344_be_sure_to_link_to_collections() {}

branches/tmp/src/libcollections/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,6 +138,7 @@ pub mod btree_set {
138138
// FIXME(#14344) this shouldn't be necessary
139139
#[doc(hidden)]
140140
#[unstable(feature = "issue_14344_fixme")]
141+
#[cfg(stage0)]
141142
pub fn fixme_14344_be_sure_to_link_to_collections() {}
142143

143144
#[cfg(not(test))]

branches/tmp/src/liblibc/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6431,6 +6431,7 @@ pub mod funcs {
64316431
}
64326432

64336433
#[doc(hidden)]
6434+
#[cfg(stage0)]
64346435
pub fn issue_14344_workaround() {} // FIXME #14344 force linkage to happen correctly
64356436

64366437
#[test] fn work_on_windows() { } // FIXME #10872 needed for a happy windows

branches/tmp/src/librustc/metadata/encoder.rs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2136,11 +2136,7 @@ fn encode_metadata_inner(wr: &mut Cursor<Vec<u8>>,
21362136
let mut rbml_w = Encoder::new(wr);
21372137

21382138
encode_crate_name(&mut rbml_w, &ecx.link_meta.crate_name);
2139-
encode_crate_triple(&mut rbml_w,
2140-
&tcx.sess
2141-
.opts
2142-
.target_triple
2143-
);
2139+
encode_crate_triple(&mut rbml_w, &tcx.sess.opts.target_triple);
21442140
encode_hash(&mut rbml_w, &ecx.link_meta.crate_hash);
21452141
encode_dylib_dependency_formats(&mut rbml_w, &ecx);
21462142

branches/tmp/src/librustc_driver/driver.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -804,8 +804,8 @@ fn write_out_deps(sess: &Session,
804804
match *output_type {
805805
config::OutputTypeExe => {
806806
for output in sess.crate_types.borrow().iter() {
807-
let p = link::filename_for_input(sess, *output,
808-
id, &file);
807+
let p = link::filename_for_input(sess, *output, id,
808+
outputs);
809809
out_filenames.push(p);
810810
}
811811
}

branches/tmp/src/librustc_driver/lib.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -452,10 +452,8 @@ impl RustcDefaultCalls {
452452
let metadata = driver::collect_crate_metadata(sess, attrs);
453453
*sess.crate_metadata.borrow_mut() = metadata;
454454
for &style in &crate_types {
455-
let fname = link::filename_for_input(sess,
456-
style,
457-
&id,
458-
&t_outputs.with_extension(""));
455+
let fname = link::filename_for_input(sess, style, &id,
456+
&t_outputs);
459457
println!("{}", fname.file_name().unwrap()
460458
.to_string_lossy());
461459
}

branches/tmp/src/librustc_trans/back/link.rs

Lines changed: 94 additions & 86 deletions
Original file line numberDiff line numberDiff line change
@@ -464,26 +464,25 @@ fn is_writeable(p: &Path) -> bool {
464464

465465
pub fn filename_for_input(sess: &Session,
466466
crate_type: config::CrateType,
467-
name: &str,
468-
out_filename: &Path) -> PathBuf {
469-
let libname = format!("{}{}", name, sess.opts.cg.extra_filename);
467+
crate_name: &str,
468+
outputs: &OutputFilenames) -> PathBuf {
469+
let libname = format!("{}{}", crate_name, sess.opts.cg.extra_filename);
470470
match crate_type {
471471
config::CrateTypeRlib => {
472-
out_filename.with_file_name(&format!("lib{}.rlib", libname))
472+
outputs.out_directory.join(&format!("lib{}.rlib", libname))
473473
}
474474
config::CrateTypeDylib => {
475475
let (prefix, suffix) = (&sess.target.target.options.dll_prefix,
476476
&sess.target.target.options.dll_suffix);
477-
out_filename.with_file_name(&format!("{}{}{}",
478-
prefix,
479-
libname,
480-
suffix))
477+
outputs.out_directory.join(&format!("{}{}{}", prefix, libname,
478+
suffix))
481479
}
482480
config::CrateTypeStaticlib => {
483-
out_filename.with_file_name(&format!("lib{}.a", libname))
481+
outputs.out_directory.join(&format!("lib{}.a", libname))
484482
}
485483
config::CrateTypeExecutable => {
486484
let suffix = &sess.target.target.options.exe_suffix;
485+
let out_filename = outputs.path(OutputTypeExe);
487486
if suffix.is_empty() {
488487
out_filename.to_path_buf()
489488
} else {
@@ -501,10 +500,7 @@ fn link_binary_output(sess: &Session,
501500
let objects = object_filenames(sess, outputs);
502501
let out_filename = match outputs.single_output_file {
503502
Some(ref file) => file.clone(),
504-
None => {
505-
let out_filename = outputs.path(OutputTypeExe);
506-
filename_for_input(sess, crate_type, crate_name, &out_filename)
507-
}
503+
None => filename_for_input(sess, crate_type, crate_name, outputs),
508504
};
509505

510506
// Make sure files are writeable. Mac, FreeBSD, and Windows system linkers
@@ -551,6 +547,19 @@ fn archive_search_paths(sess: &Session) -> Vec<PathBuf> {
551547
return search;
552548
}
553549

550+
fn archive_config<'a>(sess: &'a Session,
551+
output: &Path) -> ArchiveConfig<'a> {
552+
ArchiveConfig {
553+
handler: &sess.diagnostic().handler,
554+
dst: output.to_path_buf(),
555+
lib_search_paths: archive_search_paths(sess),
556+
slib_prefix: sess.target.target.options.staticlib_prefix.clone(),
557+
slib_suffix: sess.target.target.options.staticlib_suffix.clone(),
558+
ar_prog: get_ar_prog(sess),
559+
command_path: command_path(sess),
560+
}
561+
}
562+
554563
// Create an 'rlib'
555564
//
556565
// An rlib in its current incarnation is essentially a renamed .a file. The
@@ -562,17 +571,7 @@ fn link_rlib<'a>(sess: &'a Session,
562571
objects: &[PathBuf],
563572
out_filename: &Path) -> ArchiveBuilder<'a> {
564573
info!("preparing rlib from {:?} to {:?}", objects, out_filename);
565-
let handler = &sess.diagnostic().handler;
566-
let config = ArchiveConfig {
567-
handler: handler,
568-
dst: out_filename.to_path_buf(),
569-
lib_search_paths: archive_search_paths(sess),
570-
slib_prefix: sess.target.target.options.staticlib_prefix.clone(),
571-
slib_suffix: sess.target.target.options.staticlib_suffix.clone(),
572-
ar_prog: get_ar_prog(sess),
573-
command_path: command_path(sess),
574-
};
575-
let mut ab = ArchiveBuilder::create(config);
574+
let mut ab = ArchiveBuilder::create(archive_config(sess, out_filename));
576575
for obj in objects {
577576
ab.add_file(obj).unwrap();
578577
}
@@ -1131,7 +1130,7 @@ fn add_upstream_rust_crates(cmd: &mut Linker, sess: &Session,
11311130
add_dynamic_crate(cmd, sess, &src.dylib.unwrap().0)
11321131
}
11331132
cstore::RequireStatic => {
1134-
add_static_crate(cmd, sess, tmpdir, &src.rlib.unwrap().0)
1133+
add_static_crate(cmd, sess, tmpdir, dylib, &src.rlib.unwrap().0)
11351134
}
11361135
}
11371136

@@ -1147,71 +1146,80 @@ fn add_upstream_rust_crates(cmd: &mut Linker, sess: &Session,
11471146
}
11481147

11491148
// Adds the static "rlib" versions of all crates to the command line.
1149+
// There's a bit of magic which happens here specifically related to LTO and
1150+
// dynamic libraries. Specifically:
1151+
//
1152+
// * For LTO, we remove upstream object files.
1153+
// * For dylibs we remove metadata and bytecode from upstream rlibs
1154+
//
1155+
// When performing LTO, all of the bytecode from the upstream libraries has
1156+
// already been included in our object file output. As a result we need to
1157+
// remove the object files in the upstream libraries so the linker doesn't
1158+
// try to include them twice (or whine about duplicate symbols). We must
1159+
// continue to include the rest of the rlib, however, as it may contain
1160+
// static native libraries which must be linked in.
1161+
//
1162+
// When making a dynamic library, linkers by default don't include any
1163+
// object files in an archive if they're not necessary to resolve the link.
1164+
// We basically want to convert the archive (rlib) to a dylib, though, so we
1165+
// *do* want everything included in the output, regardless of whether the
1166+
// linker thinks it's needed or not. As a result we must use the
1167+
// --whole-archive option (or the platform equivalent). When using this
1168+
// option the linker will fail if there are non-objects in the archive (such
1169+
// as our own metadata and/or bytecode). All in all, for rlibs to be
1170+
// entirely included in dylibs, we need to remove all non-object files.
1171+
//
1172+
// Note, however, that if we're not doing LTO or we're not producing a dylib
1173+
// (aka we're making an executable), we can just pass the rlib blindly to
1174+
// the linker (fast) because it's fine if it's not actually included as
1175+
// we're at the end of the dependency chain.
11501176
fn add_static_crate(cmd: &mut Linker, sess: &Session, tmpdir: &Path,
1151-
cratepath: &Path) {
1152-
// When performing LTO on an executable output, all of the
1153-
// bytecode from the upstream libraries has already been
1154-
// included in our object file output. We need to modify all of
1155-
// the upstream archives to remove their corresponding object
1156-
// file to make sure we don't pull the same code in twice.
1157-
//
1158-
// We must continue to link to the upstream archives to be sure
1159-
// to pull in native static dependencies. As the final caveat,
1160-
// on Linux it is apparently illegal to link to a blank archive,
1161-
// so if an archive no longer has any object files in it after
1162-
// we remove `lib.o`, then don't link against it at all.
1163-
//
1164-
// If we're not doing LTO, then our job is simply to just link
1165-
// against the archive.
1166-
if sess.lto() {
1167-
let name = cratepath.file_name().unwrap().to_str().unwrap();
1168-
let name = &name[3..name.len() - 5]; // chop off lib/.rlib
1169-
time(sess.time_passes(),
1170-
&format!("altering {}.rlib", name),
1171-
(), |()| {
1172-
let dst = tmpdir.join(cratepath.file_name().unwrap());
1173-
match fs::copy(&cratepath, &dst) {
1174-
Ok(..) => {}
1175-
Err(e) => {
1176-
sess.fatal(&format!("failed to copy {} to {}: {}",
1177-
cratepath.display(),
1178-
dst.display(), e));
1179-
}
1177+
dylib: bool, cratepath: &Path) {
1178+
if !sess.lto() && !dylib {
1179+
cmd.link_rlib(&fix_windows_verbatim_for_gcc(cratepath));
1180+
return
1181+
}
1182+
1183+
let dst = tmpdir.join(cratepath.file_name().unwrap());
1184+
let name = cratepath.file_name().unwrap().to_str().unwrap();
1185+
let name = &name[3..name.len() - 5]; // chop off lib/.rlib
1186+
1187+
time(sess.time_passes(), &format!("altering {}.rlib", name), (), |()| {
1188+
let err = (|| {
1189+
io::copy(&mut try!(fs::File::open(&cratepath)),
1190+
&mut try!(fs::File::create(&dst)))
1191+
})();
1192+
if let Err(e) = err {
1193+
sess.fatal(&format!("failed to copy {} to {}: {}",
1194+
cratepath.display(), dst.display(), e));
1195+
}
1196+
1197+
let mut archive = Archive::open(archive_config(sess, &dst));
1198+
archive.remove_file(METADATA_FILENAME);
1199+
1200+
let mut any_objects = false;
1201+
for f in archive.files() {
1202+
if f.ends_with("bytecode.deflate") {
1203+
archive.remove_file(&f);
1204+
continue
11801205
}
1181-
// Fix up permissions of the copy, as fs::copy() preserves
1182-
// permissions, but the original file may have been installed
1183-
// by a package manager and may be read-only.
1184-
match fs::metadata(&dst).and_then(|m| {
1185-
let mut perms = m.permissions();
1186-
perms.set_readonly(false);
1187-
fs::set_permissions(&dst, perms)
1188-
}) {
1189-
Ok(..) => {}
1190-
Err(e) => {
1191-
sess.fatal(&format!("failed to chmod {} when preparing \
1192-
for LTO: {}", dst.display(), e));
1206+
let canonical = f.replace("-", "_");
1207+
let canonical_name = name.replace("-", "_");
1208+
if sess.lto() && canonical.starts_with(&canonical_name) &&
1209+
canonical.ends_with(".o") {
1210+
let num = &f[name.len()..f.len() - 2];
1211+
if num.len() > 0 && num[1..].parse::<u32>().is_ok() {
1212+
archive.remove_file(&f);
1213+
continue
11931214
}
11941215
}
1195-
let handler = &sess.diagnostic().handler;
1196-
let config = ArchiveConfig {
1197-
handler: handler,
1198-
dst: dst.clone(),
1199-
lib_search_paths: archive_search_paths(sess),
1200-
slib_prefix: sess.target.target.options.staticlib_prefix.clone(),
1201-
slib_suffix: sess.target.target.options.staticlib_suffix.clone(),
1202-
ar_prog: get_ar_prog(sess),
1203-
command_path: command_path(sess),
1204-
};
1205-
let mut archive = Archive::open(config);
1206-
archive.remove_file(&format!("{}.o", name));
1207-
let files = archive.files();
1208-
if files.iter().any(|s| s.ends_with(".o")) {
1209-
cmd.link_rlib(&dst);
1210-
}
1211-
});
1212-
} else {
1213-
cmd.link_rlib(&fix_windows_verbatim_for_gcc(cratepath));
1214-
}
1216+
any_objects = true;
1217+
}
1218+
1219+
if any_objects {
1220+
cmd.link_whole_rlib(&fix_windows_verbatim_for_gcc(&dst));
1221+
}
1222+
});
12151223
}
12161224

12171225
// Same thing as above, but for dynamic crates instead of static crates.

branches/tmp/src/librustc_trans/back/linker.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ pub trait Linker {
3030
fn link_framework(&mut self, framework: &str);
3131
fn link_staticlib(&mut self, lib: &str);
3232
fn link_rlib(&mut self, lib: &Path);
33+
fn link_whole_rlib(&mut self, lib: &Path);
3334
fn link_whole_staticlib(&mut self, lib: &str, search_path: &[PathBuf]);
3435
fn include_path(&mut self, path: &Path);
3536
fn framework_path(&mut self, path: &Path);
@@ -96,6 +97,17 @@ impl<'a> Linker for GnuLinker<'a> {
9697
}
9798
}
9899

100+
fn link_whole_rlib(&mut self, lib: &Path) {
101+
if self.sess.target.target.options.is_like_osx {
102+
let mut v = OsString::from("-Wl,-force_load,");
103+
v.push(lib);
104+
self.cmd.arg(&v);
105+
} else {
106+
self.cmd.arg("-Wl,--whole-archive").arg(lib)
107+
.arg("-Wl,--no-whole-archive");
108+
}
109+
}
110+
99111
fn gc_sections(&mut self, is_dylib: bool) {
100112
// The dead_strip option to the linker specifies that functions and data
101113
// unreachable by the entry point will be removed. This is quite useful
@@ -250,6 +262,10 @@ impl<'a> Linker for MsvcLinker<'a> {
250262
// not supported?
251263
self.link_staticlib(lib);
252264
}
265+
fn link_whole_rlib(&mut self, path: &Path) {
266+
// not supported?
267+
self.link_rlib(path);
268+
}
253269
fn optimize(&mut self) {
254270
// Needs more investigation of `/OPT` arguments
255271
}

0 commit comments

Comments
 (0)