Skip to content

Package mingw dependencies #16957

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

Merged
merged 4 commits into from
Sep 12, 2014
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
2 changes: 1 addition & 1 deletion mk/dist.mk
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ PKG_EXE = dist/$(PKG_NAME)-$(CFG_BUILD).exe
$(PKG_EXE): rust.iss modpath.iss upgrade.iss LICENSE.txt rust-logo.ico \
$(CSREQ3_T_$(CFG_BUILD)_H_$(CFG_BUILD)) \
dist-prepare-win
$(CFG_PYTHON) $(S)src/etc/copy-runtime-deps.py tmp/dist/win/bin $(CFG_BUILD)
$(CFG_PYTHON) $(S)src/etc/make-win-dist.py tmp/dist/win $(CFG_BUILD)
@$(call E, ISCC: $@)
$(Q)"$(CFG_ISCC)" $<

Expand Down
24 changes: 0 additions & 24 deletions src/etc/copy-runtime-deps.py

This file was deleted.

82 changes: 82 additions & 0 deletions src/etc/make-win-dist.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
# Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
# file at the top-level directory of this distribution and at
# http://rust-lang.org/COPYRIGHT.
#
# Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
# http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
# <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
# option. This file may not be copied, modified, or distributed
# except according to those terms.

import sys, os, shutil, subprocess

def find_files(files, path):
found = []
for fname in files:
for dir in path:
filepath = os.path.normpath(os.path.join(dir, fname))
if os.path.isfile(filepath):
found.append(filepath)
break
else:
raise Exception("Could not find '%s' in %s" % (fname, path))
return found

def make_win_dist(dist_root, target_triple):
# Ask gcc where it keeps its' stuff
gcc_out = subprocess.check_output(["gcc.exe", "-print-search-dirs"])
bin_path = os.environ["PATH"].split(os.pathsep)
lib_path = []
for line in gcc_out.splitlines():
key, val = line.split(':', 1)
if key == "programs":
bin_path.extend(val.lstrip(' =').split(';'))
elif key == "libraries":
lib_path.extend(val.lstrip(' =').split(';'))

target_tools = ["gcc.exe", "ld.exe", "ar.exe", "dlltool.exe", "windres.exe"]
Copy link
Member

Choose a reason for hiding this comment

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

Oh wow, I would have thought that some dlls were needed to run these!

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Nope, they are all self-contained.


rustc_dlls = ["libstdc++-6.dll"]
if target_triple.startswith("i686-"):
rustc_dlls.append("libgcc_s_dw2-1.dll")
else:
rustc_dlls.append("libgcc_s_seh-1.dll")

target_libs = ["crtbegin.o", "crtend.o", "crt2.o", "dllcrt2.o",
"libadvapi32.a", "libcrypt32.a", "libgcc.a", "libgcc_eh.a", "libgcc_s.a",
"libimagehlp.a", "libiphlpapi.a", "libkernel32.a", "libm.a", "libmingw32.a",
"libmingwex.a", "libmsvcrt.a", "libpsapi.a", "libshell32.a", "libstdc++.a",
"libuser32.a", "libws2_32.a", "libiconv.a", "libmoldname.a"]

# Find mingw artifacts we want to bundle
target_tools = find_files(target_tools, bin_path)
rustc_dlls = find_files(rustc_dlls, bin_path)
target_libs = find_files(target_libs, lib_path)

# Copy runtime dlls next to rustc.exe
dist_bin_dir = os.path.join(dist_root, "bin")
for src in rustc_dlls:
shutil.copy(src, dist_bin_dir)

# Copy platform tools (and another copy of runtime dlls) to platform-spcific bin directory
target_bin_dir = os.path.join(dist_root, "bin", "rustlib", target_triple, "bin")
if not os.path.exists(target_bin_dir):
os.makedirs(target_bin_dir)
for src in target_tools:
shutil.copy(src, target_bin_dir)

# Copy platform libs to platform-spcific lib directory
target_lib_dir = os.path.join(dist_root, "bin", "rustlib", target_triple, "lib")
if not os.path.exists(target_lib_dir):
os.makedirs(target_lib_dir)
for src in target_libs:
shutil.copy(src, target_lib_dir)

# Copy license files
lic_dir = os.path.join(dist_root, "bin", "third-party")
if os.path.exists(lic_dir):
shutil.rmtree(lic_dir) # copytree() won't overwrite existing files
shutil.copytree(os.path.join(os.path.dirname(__file__), "third-party"), lic_dir)

if __name__=="__main__":
make_win_dist(sys.argv[1], sys.argv[2])
6 changes: 3 additions & 3 deletions src/etc/snapshot.py
Original file line number Diff line number Diff line change
Expand Up @@ -157,9 +157,9 @@ def get_winnt_runtime_deps(platform):
path_dirs = os.environ["PATH"].split(os.pathsep)
for name in deps:
for dir in path_dirs:
matches = glob.glob(os.path.join(dir, name))
if matches:
runtime_deps.append(matches[0])
filepath = os.path.join(dir, name)
if os.path.isfile(filepath):
runtime_deps.append(filepath)
break
else:
raise Exception("Could not find runtime dependency: %s" % name)
Expand Down
11 changes: 4 additions & 7 deletions src/etc/third-party/README.txt
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
Certain files in this distribution are covered by a different license than the rest of the Rust Project.
Specifically:
Certain binaries in this distribution do not originate from the Rust project, but are distributed with it in its binary form. These binaries, including gcc and other parts of the GNU compiler toolchain, are licensed either under the terms of the GNU General Public License, or the GNU General Public License with the GCC Runtime Library Exception, as published by the Free Software Foundation, either version 3, or (at your option) any later version. See the files COPYING3 and COPYING.RUNTIME respectively.

- libgcc_s_dw2-1.dll and libstdc++6.dll are distributed under the terms of the GNU General Public License
with the GCC Runtime Library Exception as published by the Free Software Foundation; either version 3,
or (at your option) any later version. See the files COPYING3 and COPYING.RUNTIME respectively.
You can obtain a copy of the source of these libraries either here: http://sourceforge.net/projects/mingw/files/MinGW/Base/gcc/Version4/gcc-4.5.2-1/,
or from the project website at http://gcc.gnu.org
You can obtain a copy of the source of these libraries from the MinGW-w64 project[1].

[1]: http://mingw-w64.sourceforge.net/
3 changes: 3 additions & 0 deletions src/librustc/back/link.rs
Original file line number Diff line number Diff line change
Expand Up @@ -929,6 +929,9 @@ fn link_args(cmd: &mut Command,
cmd.arg("-nodefaultlibs");
}

// Rust does its' own LTO
cmd.arg("-fno-lto").arg("-fno-use-linker-plugin");
Copy link
Member

Choose a reason for hiding this comment

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

Should we only run these on windows, or is this ok for all invocations of gcc?

Copy link
Contributor

Choose a reason for hiding this comment

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

LTO is off by default, so why does this need to be done?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@alexcrichton: I think this is ok for all platforms. That'll be one less gcc dependency to worry about if we ever switch to direct linker invocation.
@thestinger: gcc still tells linker to load its' lto plugin, I guess on the off chance that one of the libraries being linked was compiled with lto.

Copy link
Contributor

Choose a reason for hiding this comment

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

This breaks clang builds on OSX since clang doesn't know the argument: -fno-use-linker-plugin

Copy link
Contributor Author

Choose a reason for hiding this comment

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

You should be able to work around this with export ARCHFLAGS="-Wno-error=unused-command-line-argument-hard-error-in-future".

Not sure what to do about this in the long term.

Copy link
Contributor

Choose a reason for hiding this comment

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

Can clang vs gcc be detected before the option is passed? If it's known which one is being called, then this can be passed to gcc but not clang.


// If we're building a dylib, we don't use --gc-sections because LLVM has
// already done the best it can do, and we also don't want to eliminate the
// metadata. If we're building an executable, however, --gc-sections drops
Expand Down
22 changes: 19 additions & 3 deletions src/librustc/driver/driver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ use serialize::{json, Encodable};

use std::io;
use std::io::fs;
use std::os;
use arena::TypedArena;
use syntax::ast;
use syntax::attr;
Expand Down Expand Up @@ -258,18 +259,26 @@ pub fn phase_2_configure_and_expand(sess: &Session,
// dependent dlls. Note that this uses cfg!(windows) as opposed to
// targ_cfg because syntax extensions are always loaded for the host
// compiler, not for the target.
let mut _old_path = String::new();
if cfg!(windows) {
sess.host_filesearch().add_dylib_search_paths();
_old_path = os::getenv("PATH").unwrap_or(_old_path);
let mut new_path = sess.host_filesearch().get_dylib_search_paths();
new_path.push_all_move(os::split_paths(_old_path.as_slice()));
os::setenv("PATH", os::join_paths(new_path.as_slice()).unwrap());
}
let cfg = syntax::ext::expand::ExpansionConfig {
deriving_hash_type_parameter: sess.features.default_type_params.get(),
crate_name: crate_name.to_string(),
};
syntax::ext::expand::expand_crate(&sess.parse_sess,
let ret = syntax::ext::expand::expand_crate(&sess.parse_sess,
cfg,
macros,
syntax_exts,
krate)
krate);
if cfg!(windows) {
os::setenv("PATH", _old_path);
}
ret
}
);

Expand Down Expand Up @@ -509,11 +518,18 @@ pub fn phase_5_run_llvm_passes(sess: &Session,
pub fn phase_6_link_output(sess: &Session,
trans: &CrateTranslation,
outputs: &OutputFilenames) {
let old_path = os::getenv("PATH").unwrap_or_else(||String::new());
let mut new_path = os::split_paths(old_path.as_slice());
new_path.push_all_move(sess.host_filesearch().get_tools_search_paths());
os::setenv("PATH", os::join_paths(new_path.as_slice()).unwrap());

time(sess.time_passes(), "linking", (), |_|
link::link_binary(sess,
trans,
outputs,
trans.link.crate_name.as_slice()));

os::setenv("PATH", old_path);
}

pub fn stop_after_phase_3(sess: &Session) -> bool {
Expand Down
20 changes: 16 additions & 4 deletions src/librustc/metadata/filesearch.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@
use std::cell::RefCell;
use std::os;
use std::io::fs;
use std::dynamic_lib::DynamicLibrary;
use std::collections::HashSet;

use util::fs as myfs;
Expand Down Expand Up @@ -134,11 +133,24 @@ impl<'a> FileSearch<'a> {
}
}

pub fn add_dylib_search_paths(&self) {
// Returns a list of directories where target-specific dylibs might be located.
pub fn get_dylib_search_paths(&self) -> Vec<Path> {
let mut paths = Vec::new();
self.for_each_lib_search_path(|lib_search_path| {
DynamicLibrary::prepend_search_path(lib_search_path);
paths.push(lib_search_path.clone());
FileDoesntMatch
})
});
paths
}

// Returns a list of directories where target-specific tool binaries are located.
pub fn get_tools_search_paths(&self) -> Vec<Path> {
let mut p = Path::new(self.sysroot);
p.push(find_libdir(self.sysroot));
p.push(rustlibdir());
p.push(self.triple);
p.push("bin");
vec![p]
}
}

Expand Down