Skip to content

Commit 1a9b382

Browse files
committed
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
2 parents 6cd15a0 + ad3f6e0 commit 1a9b382

File tree

8 files changed

+89
-100
lines changed

8 files changed

+89
-100
lines changed

src/bootstrap/bootstrap.py

+10-1
Original file line numberDiff line numberDiff line change
@@ -163,12 +163,13 @@ def download_stage0(self):
163163
if not os.path.exists(rustc_cache):
164164
os.makedirs(rustc_cache)
165165

166+
channel = self.stage0_rustc_channel()
167+
166168
if self.rustc().startswith(self.bin_root()) and \
167169
(not os.path.exists(self.rustc()) or self.rustc_out_of_date()):
168170
self.print_what_it_means_to_bootstrap()
169171
if os.path.exists(self.bin_root()):
170172
shutil.rmtree(self.bin_root())
171-
channel = self.stage0_rustc_channel()
172173
filename = "rust-std-{}-{}.tar.gz".format(channel, self.build)
173174
url = "https://static.rust-lang.org/dist/" + self.stage0_rustc_date()
174175
tarball = os.path.join(rustc_cache, filename)
@@ -189,6 +190,14 @@ def download_stage0(self):
189190
with open(self.rustc_stamp(), 'w') as f:
190191
f.write(self.stage0_rustc_date())
191192

193+
if "pc-windows-gnu" in self.build:
194+
filename = "rust-mingw-{}-{}.tar.gz".format(channel, self.build)
195+
url = "https://static.rust-lang.org/dist/" + self.stage0_rustc_date()
196+
tarball = os.path.join(rustc_cache, filename)
197+
if not os.path.exists(tarball):
198+
get("{}/{}".format(url, filename), tarball, verbose=self.verbose)
199+
unpack(tarball, self.bin_root(), match="rust-mingw", verbose=self.verbose)
200+
192201
if self.cargo().startswith(self.bin_root()) and \
193202
(not os.path.exists(self.cargo()) or self.cargo_out_of_date()):
194203
self.print_what_it_means_to_bootstrap()

src/etc/make-win-dist.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ def make_win_dist(rust_root, plat_root, target_triple):
5151

5252
target_tools = ["gcc.exe", "ld.exe", "ar.exe", "dlltool.exe"]
5353

54-
rustc_dlls = ["libstdc++-6.dll"]
54+
rustc_dlls = ["libstdc++-6.dll", "libwinpthread-1.dll"]
5555
if target_triple.startswith("i686-"):
5656
rustc_dlls.append("libgcc_s_dw2-1.dll")
5757
else:
@@ -67,6 +67,7 @@ def make_win_dist(rust_root, plat_root, target_triple):
6767
"libstdc++.a",
6868
"libiconv.a",
6969
"libmoldname.a",
70+
"libpthread.a",
7071
# Windows import libs
7172
"libadvapi32.a",
7273
"libbcrypt.a",

src/librustc_llvm/build.rs

+6
Original file line numberDiff line numberDiff line change
@@ -259,4 +259,10 @@ fn main() {
259259
println!("cargo:rustc-link-lib={}", stdcppname);
260260
}
261261
}
262+
263+
// LLVM requires symbols from this library, but apparently they're not printeds
264+
// during llvm-config?
265+
if target.contains("windows") {
266+
println!("cargo:rustc-link-lib=ole32");
267+
}
262268
}

src/librustc_llvm/ffi.rs

-7
Original file line numberDiff line numberDiff line change
@@ -1662,10 +1662,3 @@ extern "C" {
16621662
pub fn LLVMRustUnsetComdat(V: ValueRef);
16631663
pub fn LLVMRustSetModulePIELevel(M: ModuleRef);
16641664
}
1665-
1666-
1667-
// LLVM requires symbols from this library, but apparently they're not printed
1668-
// during llvm-config?
1669-
#[cfg(windows)]
1670-
#[link(name = "ole32")]
1671-
extern "C" {}

src/librustc_trans/back/link.rs

+6-25
Original file line numberDiff line numberDiff line change
@@ -734,9 +734,10 @@ fn link_natively(sess: &Session,
734734
}
735735

736736
{
737-
let mut linker = trans.linker_info.to_linker(&mut cmd, &sess);
737+
let mut linker = trans.linker_info.to_linker(cmd, &sess);
738738
link_args(&mut *linker, sess, crate_type, tmpdir,
739739
objects, out_filename, outputs, trans);
740+
cmd = linker.finalize();
740741
}
741742
cmd.args(&sess.target.target.options.late_link_args);
742743
for obj in &sess.target.target.options.post_link_objects {
@@ -1021,38 +1022,18 @@ fn add_local_native_libraries(cmd: &mut Linker, sess: &Session) {
10211022
}
10221023
});
10231024

1024-
let pair = sess.cstore.used_libraries().into_iter().filter(|l| {
1025+
let relevant_libs = sess.cstore.used_libraries().into_iter().filter(|l| {
10251026
relevant_lib(sess, l)
1026-
}).partition(|lib| {
1027-
lib.kind == NativeLibraryKind::NativeStatic
10281027
});
1029-
let (staticlibs, others): (Vec<_>, Vec<_>) = pair;
1030-
1031-
// Some platforms take hints about whether a library is static or dynamic.
1032-
// For those that support this, we ensure we pass the option if the library
1033-
// was flagged "static" (most defaults are dynamic) to ensure that if
1034-
// libfoo.a and libfoo.so both exist that the right one is chosen.
1035-
cmd.hint_static();
10361028

10371029
let search_path = archive_search_paths(sess);
1038-
for l in staticlibs {
1039-
// Here we explicitly ask that the entire archive is included into the
1040-
// result artifact. For more details see #15460, but the gist is that
1041-
// the linker will strip away any unused objects in the archive if we
1042-
// don't otherwise explicitly reference them. This can occur for
1043-
// libraries which are just providing bindings, libraries with generic
1044-
// functions, etc.
1045-
cmd.link_whole_staticlib(&l.name.as_str(), &search_path);
1046-
}
1047-
1048-
cmd.hint_dynamic();
1049-
1050-
for lib in others {
1030+
for lib in relevant_libs {
10511031
match lib.kind {
10521032
NativeLibraryKind::NativeUnknown => cmd.link_dylib(&lib.name.as_str()),
10531033
NativeLibraryKind::NativeFramework => cmd.link_framework(&lib.name.as_str()),
10541034
NativeLibraryKind::NativeStaticNobundle => cmd.link_staticlib(&lib.name.as_str()),
1055-
NativeLibraryKind::NativeStatic => bug!(),
1035+
NativeLibraryKind::NativeStatic => cmd.link_whole_staticlib(&lib.name.as_str(),
1036+
&search_path)
10561037
}
10571038
}
10581039
}

src/librustc_trans/back/linker.rs

+62-65
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ impl<'a, 'tcx> LinkerInfo {
4343
}
4444

4545
pub fn to_linker(&'a self,
46-
cmd: &'a mut Command,
46+
cmd: Command,
4747
sess: &'a Session) -> Box<Linker+'a> {
4848
if sess.target.target.options.is_like_msvc {
4949
Box::new(MsvcLinker {
@@ -61,7 +61,8 @@ impl<'a, 'tcx> LinkerInfo {
6161
Box::new(GnuLinker {
6262
cmd: cmd,
6363
sess: sess,
64-
info: self
64+
info: self,
65+
hinted_static: false,
6566
}) as Box<Linker>
6667
}
6768
}
@@ -93,30 +94,49 @@ pub trait Linker {
9394
fn no_default_libraries(&mut self);
9495
fn build_dylib(&mut self, out_filename: &Path);
9596
fn args(&mut self, args: &[String]);
96-
fn hint_static(&mut self);
97-
fn hint_dynamic(&mut self);
98-
fn whole_archives(&mut self);
99-
fn no_whole_archives(&mut self);
10097
fn export_symbols(&mut self, tmpdir: &Path, crate_type: CrateType);
10198
fn subsystem(&mut self, subsystem: &str);
99+
// Should have been finalize(self), but we don't support self-by-value on trait objects (yet?).
100+
fn finalize(&mut self) -> Command;
102101
}
103102

104103
pub struct GnuLinker<'a> {
105-
cmd: &'a mut Command,
104+
cmd: Command,
106105
sess: &'a Session,
107-
info: &'a LinkerInfo
106+
info: &'a LinkerInfo,
107+
hinted_static: bool, // Keeps track of the current hinting mode.
108108
}
109109

110110
impl<'a> GnuLinker<'a> {
111111
fn takes_hints(&self) -> bool {
112112
!self.sess.target.target.options.is_like_osx
113113
}
114+
115+
// Some platforms take hints about whether a library is static or dynamic.
116+
// For those that support this, we ensure we pass the option if the library
117+
// was flagged "static" (most defaults are dynamic) to ensure that if
118+
// libfoo.a and libfoo.so both exist that the right one is chosen.
119+
fn hint_static(&mut self) {
120+
if !self.takes_hints() { return }
121+
if !self.hinted_static {
122+
self.cmd.arg("-Wl,-Bstatic");
123+
self.hinted_static = true;
124+
}
125+
}
126+
127+
fn hint_dynamic(&mut self) {
128+
if !self.takes_hints() { return }
129+
if self.hinted_static {
130+
self.cmd.arg("-Wl,-Bdynamic");
131+
self.hinted_static = false;
132+
}
133+
}
114134
}
115135

116136
impl<'a> Linker for GnuLinker<'a> {
117-
fn link_dylib(&mut self, lib: &str) { self.cmd.arg("-l").arg(lib); }
118-
fn link_staticlib(&mut self, lib: &str) { self.cmd.arg("-l").arg(lib); }
119-
fn link_rlib(&mut self, lib: &Path) { self.cmd.arg(lib); }
137+
fn link_dylib(&mut self, lib: &str) { self.hint_dynamic(); self.cmd.arg("-l").arg(lib); }
138+
fn link_staticlib(&mut self, lib: &str) { self.hint_static(); self.cmd.arg("-l").arg(lib); }
139+
fn link_rlib(&mut self, lib: &Path) { self.hint_static(); self.cmd.arg(lib); }
120140
fn include_path(&mut self, path: &Path) { self.cmd.arg("-L").arg(path); }
121141
fn framework_path(&mut self, path: &Path) { self.cmd.arg("-F").arg(path); }
122142
fn output_filename(&mut self, path: &Path) { self.cmd.arg("-o").arg(path); }
@@ -125,14 +145,23 @@ impl<'a> Linker for GnuLinker<'a> {
125145
fn args(&mut self, args: &[String]) { self.cmd.args(args); }
126146

127147
fn link_rust_dylib(&mut self, lib: &str, _path: &Path) {
148+
self.hint_dynamic();
128149
self.cmd.arg("-l").arg(lib);
129150
}
130151

131152
fn link_framework(&mut self, framework: &str) {
153+
self.hint_dynamic();
132154
self.cmd.arg("-framework").arg(framework);
133155
}
134156

157+
// Here we explicitly ask that the entire archive is included into the
158+
// result artifact. For more details see #15460, but the gist is that
159+
// the linker will strip away any unused objects in the archive if we
160+
// don't otherwise explicitly reference them. This can occur for
161+
// libraries which are just providing bindings, libraries with generic
162+
// functions, etc.
135163
fn link_whole_staticlib(&mut self, lib: &str, search_path: &[PathBuf]) {
164+
self.hint_static();
136165
let target = &self.sess.target.target;
137166
if !target.options.is_like_osx {
138167
self.cmd.arg("-Wl,--whole-archive")
@@ -148,6 +177,7 @@ impl<'a> Linker for GnuLinker<'a> {
148177
}
149178

150179
fn link_whole_rlib(&mut self, lib: &Path) {
180+
self.hint_static();
151181
if self.sess.target.target.options.is_like_osx {
152182
let mut v = OsString::from("-Wl,-force_load,");
153183
v.push(lib);
@@ -228,26 +258,6 @@ impl<'a> Linker for GnuLinker<'a> {
228258
}
229259
}
230260

231-
fn whole_archives(&mut self) {
232-
if !self.takes_hints() { return }
233-
self.cmd.arg("-Wl,--whole-archive");
234-
}
235-
236-
fn no_whole_archives(&mut self) {
237-
if !self.takes_hints() { return }
238-
self.cmd.arg("-Wl,--no-whole-archive");
239-
}
240-
241-
fn hint_static(&mut self) {
242-
if !self.takes_hints() { return }
243-
self.cmd.arg("-Wl,-Bstatic");
244-
}
245-
246-
fn hint_dynamic(&mut self) {
247-
if !self.takes_hints() { return }
248-
self.cmd.arg("-Wl,-Bdynamic");
249-
}
250-
251261
fn export_symbols(&mut self, tmpdir: &Path, crate_type: CrateType) {
252262
// If we're compiling a dylib, then we let symbol visibility in object
253263
// files to take care of whether they're exported or not.
@@ -311,10 +321,17 @@ impl<'a> Linker for GnuLinker<'a> {
311321
fn subsystem(&mut self, subsystem: &str) {
312322
self.cmd.arg(&format!("-Wl,--subsystem,{}", subsystem));
313323
}
324+
325+
fn finalize(&mut self) -> Command {
326+
self.hint_dynamic(); // Reset to default before returning the composed command line.
327+
let mut cmd = Command::new("");
328+
::std::mem::swap(&mut cmd, &mut self.cmd);
329+
cmd
330+
}
314331
}
315332

316333
pub struct MsvcLinker<'a> {
317-
cmd: &'a mut Command,
334+
cmd: Command,
318335
sess: &'a Session,
319336
info: &'a LinkerInfo
320337
}
@@ -416,22 +433,6 @@ impl<'a> Linker for MsvcLinker<'a> {
416433
self.cmd.arg("/DEBUG");
417434
}
418435

419-
fn whole_archives(&mut self) {
420-
// hints not supported?
421-
}
422-
fn no_whole_archives(&mut self) {
423-
// hints not supported?
424-
}
425-
426-
// On windows static libraries are of the form `foo.lib` and dynamic
427-
// libraries are not linked against directly, but rather through their
428-
// import libraries also called `foo.lib`. As a result there's no
429-
// possibility for a native library to appear both dynamically and
430-
// statically in the same folder so we don't have to worry about hints like
431-
// we do on Unix platforms.
432-
fn hint_static(&mut self) {}
433-
fn hint_dynamic(&mut self) {}
434-
435436
// Currently the compiler doesn't use `dllexport` (an LLVM attribute) to
436437
// export symbols from a dynamic library. When building a dynamic library,
437438
// however, we're going to want some symbols exported, so this function
@@ -492,10 +493,16 @@ impl<'a> Linker for MsvcLinker<'a> {
492493
self.cmd.arg("/ENTRY:mainCRTStartup");
493494
}
494495
}
496+
497+
fn finalize(&mut self) -> Command {
498+
let mut cmd = Command::new("");
499+
::std::mem::swap(&mut cmd, &mut self.cmd);
500+
cmd
501+
}
495502
}
496503

497504
pub struct EmLinker<'a> {
498-
cmd: &'a mut Command,
505+
cmd: Command,
499506
sess: &'a Session,
500507
info: &'a LinkerInfo
501508
}
@@ -591,22 +598,6 @@ impl<'a> Linker for EmLinker<'a> {
591598
bug!("building dynamic library is unsupported on Emscripten")
592599
}
593600

594-
fn whole_archives(&mut self) {
595-
// noop
596-
}
597-
598-
fn no_whole_archives(&mut self) {
599-
// noop
600-
}
601-
602-
fn hint_static(&mut self) {
603-
// noop
604-
}
605-
606-
fn hint_dynamic(&mut self) {
607-
// noop
608-
}
609-
610601
fn export_symbols(&mut self, _tmpdir: &Path, crate_type: CrateType) {
611602
let symbols = &self.info.exports[&crate_type];
612603

@@ -640,6 +631,12 @@ impl<'a> Linker for EmLinker<'a> {
640631
fn subsystem(&mut self, _subsystem: &str) {
641632
// noop
642633
}
634+
635+
fn finalize(&mut self) -> Command {
636+
let mut cmd = Command::new("");
637+
::std::mem::swap(&mut cmd, &mut self.cmd);
638+
cmd
639+
}
643640
}
644641

645642
fn exported_symbols(scx: &SharedCrateContext,

src/libunwind/build.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,8 @@ fn main() {
3535
} else if target.contains("dragonfly") {
3636
println!("cargo:rustc-link-lib=gcc_pic");
3737
} else if target.contains("windows-gnu") {
38-
println!("cargo:rustc-link-lib=gcc_eh");
38+
println!("cargo:rustc-link-lib=static-nobundle=gcc_eh");
39+
println!("cargo:rustc-link-lib=static-nobundle=pthread");
3940
} else if target.contains("fuchsia") {
4041
println!("cargo:rustc-link-lib=unwind");
4142
}

src/libunwind/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#![feature(cfg_target_vendor)]
1818
#![feature(staged_api)]
1919
#![feature(unwind_attributes)]
20+
#![feature(static_nobundle)]
2021

2122
#![cfg_attr(not(target_env = "msvc"), feature(libc))]
2223

0 commit comments

Comments
 (0)