Skip to content

Commit

Permalink
Auto merge of #40805 - vadimcn:msys-mingw, r=alexcrichton
Browse files Browse the repository at this point in the history
[Windows] Enable building rustc with "pthreads" flavor of mingw.

Tested on mingw-w64 packaged with msys2.

r? @alexcrichton

cc #40123
  • Loading branch information
bors committed Apr 6, 2017
2 parents 6cd15a0 + ad3f6e0 commit 1a9b382
Show file tree
Hide file tree
Showing 8 changed files with 89 additions and 100 deletions.
11 changes: 10 additions & 1 deletion src/bootstrap/bootstrap.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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()
Expand Down
3 changes: 2 additions & 1 deletion src/etc/make-win-dist.py
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand All @@ -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",
Expand Down
6 changes: 6 additions & 0 deletions src/librustc_llvm/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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");
}
}
7 changes: 0 additions & 7 deletions src/librustc_llvm/ffi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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" {}
31 changes: 6 additions & 25 deletions src/librustc_trans/back/link.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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)
}
}
}
Expand Down
127 changes: 62 additions & 65 deletions src/librustc_trans/back/linker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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>
}
}
Expand Down Expand Up @@ -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); }
Expand All @@ -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")
Expand All @@ -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);
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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
}
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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
}
Expand Down Expand Up @@ -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];

Expand Down Expand Up @@ -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,
Expand Down
3 changes: 2 additions & 1 deletion src/libunwind/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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");
}
Expand Down
1 change: 1 addition & 0 deletions src/libunwind/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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))]

Expand Down

0 comments on commit 1a9b382

Please sign in to comment.