about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2017-04-06 03:42:31 +0000
committerbors <bors@rust-lang.org>2017-04-06 03:42:31 +0000
commit1a9b382168cbf405589fbba7215ace700c067879 (patch)
treeecaaf285c2c836cbfabfd40a82fcbd993f5c111f
parent6cd15a0e8fecce04fd99b77b25099bf374bb0f56 (diff)
parentad3f6e056cdae847c3784ece2ebd8b52baa130e2 (diff)
downloadrust-1a9b382168cbf405589fbba7215ace700c067879.tar.gz
rust-1a9b382168cbf405589fbba7215ace700c067879.zip
Auto merge of #40805 - vadimcn:msys-mingw, r=alexcrichton
[Windows] Enable building rustc with "pthreads" flavor of mingw.

Tested on mingw-w64 packaged with msys2.

r? @alexcrichton

cc #40123
-rw-r--r--src/bootstrap/bootstrap.py11
-rw-r--r--src/etc/make-win-dist.py3
-rw-r--r--src/librustc_llvm/build.rs6
-rw-r--r--src/librustc_llvm/ffi.rs7
-rw-r--r--src/librustc_trans/back/link.rs31
-rw-r--r--src/librustc_trans/back/linker.rs127
-rw-r--r--src/libunwind/build.rs3
-rw-r--r--src/libunwind/lib.rs1
8 files changed, 89 insertions, 100 deletions
diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py
index d5bc6127a1e..9f9d3471640 100644
--- a/src/bootstrap/bootstrap.py
+++ b/src/bootstrap/bootstrap.py
@@ -163,12 +163,13 @@ class RustBuild(object):
         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 @@ class RustBuild(object):
             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 eda5f854085..394ff97d845 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 2b945e0a3af..7d5887e699f 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 26c7a9166e6..32c9183ece9 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 6d17b2f0eed..12a1ffa2767 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 80801e8161c..a178d17a7c2 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<Linker+'a> {
         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<Linker>
         }
     }
@@ -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 ed3d5212bf2..9b8099d55a0 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 7fa2ce650fd..d4d52322ada 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))]