diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index d5bc6127a1e7f..9f9d3471640ff 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -163,12 +163,13 @@ def download_stage0(self): if not os.path.exists(rustc_cache): os.makedirs(rustc_cache) + channel = self.stage0_rustc_channel() + if self.rustc().startswith(self.bin_root()) and \ (not os.path.exists(self.rustc()) or self.rustc_out_of_date()): self.print_what_it_means_to_bootstrap() if os.path.exists(self.bin_root()): shutil.rmtree(self.bin_root()) - channel = self.stage0_rustc_channel() filename = "rust-std-{}-{}.tar.gz".format(channel, self.build) url = "https://static.rust-lang.org/dist/" + self.stage0_rustc_date() tarball = os.path.join(rustc_cache, filename) @@ -189,6 +190,14 @@ def download_stage0(self): with open(self.rustc_stamp(), 'w') as f: f.write(self.stage0_rustc_date()) + if "pc-windows-gnu" in self.build: + filename = "rust-mingw-{}-{}.tar.gz".format(channel, self.build) + url = "https://static.rust-lang.org/dist/" + self.stage0_rustc_date() + tarball = os.path.join(rustc_cache, filename) + if not os.path.exists(tarball): + get("{}/{}".format(url, filename), tarball, verbose=self.verbose) + unpack(tarball, self.bin_root(), match="rust-mingw", verbose=self.verbose) + if self.cargo().startswith(self.bin_root()) and \ (not os.path.exists(self.cargo()) or self.cargo_out_of_date()): self.print_what_it_means_to_bootstrap() diff --git a/src/etc/make-win-dist.py b/src/etc/make-win-dist.py index eda5f85408574..394ff97d84533 100644 --- a/src/etc/make-win-dist.py +++ b/src/etc/make-win-dist.py @@ -51,7 +51,7 @@ def make_win_dist(rust_root, plat_root, target_triple): target_tools = ["gcc.exe", "ld.exe", "ar.exe", "dlltool.exe"] - rustc_dlls = ["libstdc++-6.dll"] + rustc_dlls = ["libstdc++-6.dll", "libwinpthread-1.dll"] if target_triple.startswith("i686-"): rustc_dlls.append("libgcc_s_dw2-1.dll") else: @@ -67,6 +67,7 @@ def make_win_dist(rust_root, plat_root, target_triple): "libstdc++.a", "libiconv.a", "libmoldname.a", + "libpthread.a", # Windows import libs "libadvapi32.a", "libbcrypt.a", diff --git a/src/librustc_llvm/build.rs b/src/librustc_llvm/build.rs index 2b945e0a3afaf..7d5887e699fd7 100644 --- a/src/librustc_llvm/build.rs +++ b/src/librustc_llvm/build.rs @@ -259,4 +259,10 @@ fn main() { println!("cargo:rustc-link-lib={}", stdcppname); } } + + // LLVM requires symbols from this library, but apparently they're not printeds + // during llvm-config? + if target.contains("windows") { + println!("cargo:rustc-link-lib=ole32"); + } } diff --git a/src/librustc_llvm/ffi.rs b/src/librustc_llvm/ffi.rs index 26c7a9166e68e..32c9183ece999 100644 --- a/src/librustc_llvm/ffi.rs +++ b/src/librustc_llvm/ffi.rs @@ -1662,10 +1662,3 @@ extern "C" { pub fn LLVMRustUnsetComdat(V: ValueRef); pub fn LLVMRustSetModulePIELevel(M: ModuleRef); } - - -// LLVM requires symbols from this library, but apparently they're not printed -// during llvm-config? -#[cfg(windows)] -#[link(name = "ole32")] -extern "C" {} diff --git a/src/librustc_trans/back/link.rs b/src/librustc_trans/back/link.rs index 6d17b2f0eeda3..12a1ffa276725 100644 --- a/src/librustc_trans/back/link.rs +++ b/src/librustc_trans/back/link.rs @@ -734,9 +734,10 @@ fn link_natively(sess: &Session, } { - let mut linker = trans.linker_info.to_linker(&mut cmd, &sess); + let mut linker = trans.linker_info.to_linker(cmd, &sess); link_args(&mut *linker, sess, crate_type, tmpdir, objects, out_filename, outputs, trans); + cmd = linker.finalize(); } cmd.args(&sess.target.target.options.late_link_args); for obj in &sess.target.target.options.post_link_objects { @@ -1021,38 +1022,18 @@ fn add_local_native_libraries(cmd: &mut Linker, sess: &Session) { } }); - let pair = sess.cstore.used_libraries().into_iter().filter(|l| { + let relevant_libs = sess.cstore.used_libraries().into_iter().filter(|l| { relevant_lib(sess, l) - }).partition(|lib| { - lib.kind == NativeLibraryKind::NativeStatic }); - let (staticlibs, others): (Vec<_>, Vec<_>) = pair; - - // Some platforms take hints about whether a library is static or dynamic. - // For those that support this, we ensure we pass the option if the library - // was flagged "static" (most defaults are dynamic) to ensure that if - // libfoo.a and libfoo.so both exist that the right one is chosen. - cmd.hint_static(); let search_path = archive_search_paths(sess); - for l in staticlibs { - // Here we explicitly ask that the entire archive is included into the - // result artifact. For more details see #15460, but the gist is that - // the linker will strip away any unused objects in the archive if we - // don't otherwise explicitly reference them. This can occur for - // libraries which are just providing bindings, libraries with generic - // functions, etc. - cmd.link_whole_staticlib(&l.name.as_str(), &search_path); - } - - cmd.hint_dynamic(); - - for lib in others { + for lib in relevant_libs { match lib.kind { NativeLibraryKind::NativeUnknown => cmd.link_dylib(&lib.name.as_str()), NativeLibraryKind::NativeFramework => cmd.link_framework(&lib.name.as_str()), NativeLibraryKind::NativeStaticNobundle => cmd.link_staticlib(&lib.name.as_str()), - NativeLibraryKind::NativeStatic => bug!(), + NativeLibraryKind::NativeStatic => cmd.link_whole_staticlib(&lib.name.as_str(), + &search_path) } } } diff --git a/src/librustc_trans/back/linker.rs b/src/librustc_trans/back/linker.rs index 80801e8161cd0..a178d17a7c2d3 100644 --- a/src/librustc_trans/back/linker.rs +++ b/src/librustc_trans/back/linker.rs @@ -43,7 +43,7 @@ impl<'a, 'tcx> LinkerInfo { } pub fn to_linker(&'a self, - cmd: &'a mut Command, + cmd: Command, sess: &'a Session) -> Box { if sess.target.target.options.is_like_msvc { Box::new(MsvcLinker { @@ -61,7 +61,8 @@ impl<'a, 'tcx> LinkerInfo { Box::new(GnuLinker { cmd: cmd, sess: sess, - info: self + info: self, + hinted_static: false, }) as Box } } @@ -93,30 +94,49 @@ pub trait Linker { fn no_default_libraries(&mut self); fn build_dylib(&mut self, out_filename: &Path); fn args(&mut self, args: &[String]); - fn hint_static(&mut self); - fn hint_dynamic(&mut self); - fn whole_archives(&mut self); - fn no_whole_archives(&mut self); fn export_symbols(&mut self, tmpdir: &Path, crate_type: CrateType); fn subsystem(&mut self, subsystem: &str); + // Should have been finalize(self), but we don't support self-by-value on trait objects (yet?). + fn finalize(&mut self) -> Command; } pub struct GnuLinker<'a> { - cmd: &'a mut Command, + cmd: Command, sess: &'a Session, - info: &'a LinkerInfo + info: &'a LinkerInfo, + hinted_static: bool, // Keeps track of the current hinting mode. } impl<'a> GnuLinker<'a> { fn takes_hints(&self) -> bool { !self.sess.target.target.options.is_like_osx } + + // Some platforms take hints about whether a library is static or dynamic. + // For those that support this, we ensure we pass the option if the library + // was flagged "static" (most defaults are dynamic) to ensure that if + // libfoo.a and libfoo.so both exist that the right one is chosen. + fn hint_static(&mut self) { + if !self.takes_hints() { return } + if !self.hinted_static { + self.cmd.arg("-Wl,-Bstatic"); + self.hinted_static = true; + } + } + + fn hint_dynamic(&mut self) { + if !self.takes_hints() { return } + if self.hinted_static { + self.cmd.arg("-Wl,-Bdynamic"); + self.hinted_static = false; + } + } } impl<'a> Linker for GnuLinker<'a> { - fn link_dylib(&mut self, lib: &str) { self.cmd.arg("-l").arg(lib); } - fn link_staticlib(&mut self, lib: &str) { self.cmd.arg("-l").arg(lib); } - fn link_rlib(&mut self, lib: &Path) { self.cmd.arg(lib); } + fn link_dylib(&mut self, lib: &str) { self.hint_dynamic(); self.cmd.arg("-l").arg(lib); } + fn link_staticlib(&mut self, lib: &str) { self.hint_static(); self.cmd.arg("-l").arg(lib); } + fn link_rlib(&mut self, lib: &Path) { self.hint_static(); self.cmd.arg(lib); } fn include_path(&mut self, path: &Path) { self.cmd.arg("-L").arg(path); } fn framework_path(&mut self, path: &Path) { self.cmd.arg("-F").arg(path); } fn output_filename(&mut self, path: &Path) { self.cmd.arg("-o").arg(path); } @@ -125,14 +145,23 @@ impl<'a> Linker for GnuLinker<'a> { fn args(&mut self, args: &[String]) { self.cmd.args(args); } fn link_rust_dylib(&mut self, lib: &str, _path: &Path) { + self.hint_dynamic(); self.cmd.arg("-l").arg(lib); } fn link_framework(&mut self, framework: &str) { + self.hint_dynamic(); self.cmd.arg("-framework").arg(framework); } + // Here we explicitly ask that the entire archive is included into the + // result artifact. For more details see #15460, but the gist is that + // the linker will strip away any unused objects in the archive if we + // don't otherwise explicitly reference them. This can occur for + // libraries which are just providing bindings, libraries with generic + // functions, etc. fn link_whole_staticlib(&mut self, lib: &str, search_path: &[PathBuf]) { + self.hint_static(); let target = &self.sess.target.target; if !target.options.is_like_osx { self.cmd.arg("-Wl,--whole-archive") @@ -148,6 +177,7 @@ impl<'a> Linker for GnuLinker<'a> { } fn link_whole_rlib(&mut self, lib: &Path) { + self.hint_static(); if self.sess.target.target.options.is_like_osx { let mut v = OsString::from("-Wl,-force_load,"); v.push(lib); @@ -228,26 +258,6 @@ impl<'a> Linker for GnuLinker<'a> { } } - fn whole_archives(&mut self) { - if !self.takes_hints() { return } - self.cmd.arg("-Wl,--whole-archive"); - } - - fn no_whole_archives(&mut self) { - if !self.takes_hints() { return } - self.cmd.arg("-Wl,--no-whole-archive"); - } - - fn hint_static(&mut self) { - if !self.takes_hints() { return } - self.cmd.arg("-Wl,-Bstatic"); - } - - fn hint_dynamic(&mut self) { - if !self.takes_hints() { return } - self.cmd.arg("-Wl,-Bdynamic"); - } - fn export_symbols(&mut self, tmpdir: &Path, crate_type: CrateType) { // If we're compiling a dylib, then we let symbol visibility in object // files to take care of whether they're exported or not. @@ -311,10 +321,17 @@ impl<'a> Linker for GnuLinker<'a> { fn subsystem(&mut self, subsystem: &str) { self.cmd.arg(&format!("-Wl,--subsystem,{}", subsystem)); } + + fn finalize(&mut self) -> Command { + self.hint_dynamic(); // Reset to default before returning the composed command line. + let mut cmd = Command::new(""); + ::std::mem::swap(&mut cmd, &mut self.cmd); + cmd + } } pub struct MsvcLinker<'a> { - cmd: &'a mut Command, + cmd: Command, sess: &'a Session, info: &'a LinkerInfo } @@ -416,22 +433,6 @@ impl<'a> Linker for MsvcLinker<'a> { self.cmd.arg("/DEBUG"); } - fn whole_archives(&mut self) { - // hints not supported? - } - fn no_whole_archives(&mut self) { - // hints not supported? - } - - // On windows static libraries are of the form `foo.lib` and dynamic - // libraries are not linked against directly, but rather through their - // import libraries also called `foo.lib`. As a result there's no - // possibility for a native library to appear both dynamically and - // statically in the same folder so we don't have to worry about hints like - // we do on Unix platforms. - fn hint_static(&mut self) {} - fn hint_dynamic(&mut self) {} - // Currently the compiler doesn't use `dllexport` (an LLVM attribute) to // export symbols from a dynamic library. When building a dynamic library, // however, we're going to want some symbols exported, so this function @@ -492,10 +493,16 @@ impl<'a> Linker for MsvcLinker<'a> { self.cmd.arg("/ENTRY:mainCRTStartup"); } } + + fn finalize(&mut self) -> Command { + let mut cmd = Command::new(""); + ::std::mem::swap(&mut cmd, &mut self.cmd); + cmd + } } pub struct EmLinker<'a> { - cmd: &'a mut Command, + cmd: Command, sess: &'a Session, info: &'a LinkerInfo } @@ -591,22 +598,6 @@ impl<'a> Linker for EmLinker<'a> { bug!("building dynamic library is unsupported on Emscripten") } - fn whole_archives(&mut self) { - // noop - } - - fn no_whole_archives(&mut self) { - // noop - } - - fn hint_static(&mut self) { - // noop - } - - fn hint_dynamic(&mut self) { - // noop - } - fn export_symbols(&mut self, _tmpdir: &Path, crate_type: CrateType) { let symbols = &self.info.exports[&crate_type]; @@ -640,6 +631,12 @@ impl<'a> Linker for EmLinker<'a> { fn subsystem(&mut self, _subsystem: &str) { // noop } + + fn finalize(&mut self) -> Command { + let mut cmd = Command::new(""); + ::std::mem::swap(&mut cmd, &mut self.cmd); + cmd + } } fn exported_symbols(scx: &SharedCrateContext, diff --git a/src/libunwind/build.rs b/src/libunwind/build.rs index ed3d5212bf256..9b8099d55a024 100644 --- a/src/libunwind/build.rs +++ b/src/libunwind/build.rs @@ -35,7 +35,8 @@ fn main() { } else if target.contains("dragonfly") { println!("cargo:rustc-link-lib=gcc_pic"); } else if target.contains("windows-gnu") { - println!("cargo:rustc-link-lib=gcc_eh"); + println!("cargo:rustc-link-lib=static-nobundle=gcc_eh"); + println!("cargo:rustc-link-lib=static-nobundle=pthread"); } else if target.contains("fuchsia") { println!("cargo:rustc-link-lib=unwind"); } diff --git a/src/libunwind/lib.rs b/src/libunwind/lib.rs index 7fa2ce650fd6c..d4d52322adab0 100644 --- a/src/libunwind/lib.rs +++ b/src/libunwind/lib.rs @@ -17,6 +17,7 @@ #![feature(cfg_target_vendor)] #![feature(staged_api)] #![feature(unwind_attributes)] +#![feature(static_nobundle)] #![cfg_attr(not(target_env = "msvc"), feature(libc))]