Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Windows] Enable building rustc with "pthreads" flavor of mingw. #40805

Merged
merged 5 commits into from
Apr 6, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

s/printeds/printed/

// 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