diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index 511f2c9e80ec7..14ddcc7cb3232 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -96,6 +96,140 @@ pub fn docs(build: &Build, stage: u32, host: &str) { } } +fn find_files(files: &[&str], path: &[PathBuf]) -> Vec { + let mut found = Vec::new(); + + for file in files { + let file_path = + path.iter() + .map(|dir| dir.join(file)) + .find(|p| p.exists()); + + if let Some(file_path) = file_path { + found.push(file_path); + } else { + panic!("Could not find '{}' in {:?}", file, path); + } + } + + found +} + +fn make_win_dist(rust_root: &Path, plat_root: &Path, target_triple: &str, build: &Build) { + //Ask gcc where it keeps its stuff + let mut cmd = Command::new(build.cc(target_triple)); + cmd.arg("-print-search-dirs"); + build.run_quiet(&mut cmd); + let gcc_out = + String::from_utf8( + cmd + .output() + .expect("failed to execute gcc") + .stdout).expect("gcc.exe output was not utf8"); + + let mut bin_path: Vec<_> = + env::split_paths(&env::var_os("PATH").unwrap_or_default()) + .collect(); + let mut lib_path = Vec::new(); + + for line in gcc_out.lines() { + let idx = line.find(':').unwrap(); + let key = &line[..idx]; + let trim_chars: &[_] = &[' ', '=']; + let value = + line[(idx + 1)..] + .trim_left_matches(trim_chars) + .split(';') + .map(|s| PathBuf::from(s)); + + if key == "programs" { + bin_path.extend(value); + } else if key == "libraries" { + lib_path.extend(value); + } + } + + let target_tools = vec!["gcc.exe", "ld.exe", "ar.exe", "dlltool.exe", "libwinpthread-1.dll"]; + let mut rustc_dlls = vec!["libstdc++-6.dll", "libwinpthread-1.dll"]; + if target_triple.starts_with("i686-") { + rustc_dlls.push("libgcc_s_dw2-1.dll"); + } else { + rustc_dlls.push("libgcc_s_seh-1.dll"); + } + + let target_libs = vec![ //MinGW libs + "libgcc.a", + "libgcc_eh.a", + "libgcc_s.a", + "libm.a", + "libmingw32.a", + "libmingwex.a", + "libstdc++.a", + "libiconv.a", + "libmoldname.a", + "libpthread.a", + //Windows import libs + "libadvapi32.a", + "libbcrypt.a", + "libcomctl32.a", + "libcomdlg32.a", + "libcrypt32.a", + "libgdi32.a", + "libimagehlp.a", + "libiphlpapi.a", + "libkernel32.a", + "libmsvcrt.a", + "libodbc32.a", + "libole32.a", + "liboleaut32.a", + "libopengl32.a", + "libpsapi.a", + "librpcrt4.a", + "libsetupapi.a", + "libshell32.a", + "libuser32.a", + "libuserenv.a", + "libuuid.a", + "libwinhttp.a", + "libwinmm.a", + "libwinspool.a", + "libws2_32.a", + "libwsock32.a", + ]; + + //Find mingw artifacts we want to bundle + let target_tools = find_files(&target_tools, &bin_path); + let rustc_dlls = find_files(&rustc_dlls, &bin_path); + let target_libs = find_files(&target_libs, &lib_path); + + fn copy_to_folder(src: &Path, dest_folder: &Path) { + let file_name = src.file_name().unwrap().to_os_string(); + let dest = dest_folder.join(file_name); + copy(src, &dest); + } + + //Copy runtime dlls next to rustc.exe + let dist_bin_dir = rust_root.join("bin/"); + fs::create_dir_all(&dist_bin_dir).expect("creating dist_bin_dir failed"); + for src in rustc_dlls { + copy_to_folder(&src, &dist_bin_dir); + } + + //Copy platform tools to platform-specific bin directory + let target_bin_dir = plat_root.join("lib").join("rustlib").join(target_triple).join("bin"); + fs::create_dir_all(&target_bin_dir).expect("creating target_bin_dir failed"); + for src in target_tools { + copy_to_folder(&src, &target_bin_dir); + } + + //Copy platform libs to platform-specific lib directory + let target_lib_dir = plat_root.join("lib").join("rustlib").join(target_triple).join("lib"); + fs::create_dir_all(&target_lib_dir).expect("creating target_lib_dir failed"); + for src in target_libs { + copy_to_folder(&src, &target_lib_dir); + } +} + /// Build the `rust-mingw` installer component. /// /// This contains all the bits and pieces to run the MinGW Windows targets @@ -109,18 +243,11 @@ pub fn mingw(build: &Build, host: &str) { let _ = fs::remove_dir_all(&image); t!(fs::create_dir_all(&image)); - // The first argument to the script is a "temporary directory" which is just + // The first argument is a "temporary directory" which is just // thrown away (this contains the runtime DLLs included in the rustc package // above) and the second argument is where to place all the MinGW components // (which is what we want). - // - // FIXME: this script should be rewritten into Rust - let mut cmd = Command::new(build.python()); - cmd.arg(build.src.join("src/etc/make-win-dist.py")) - .arg(tmpdir(build)) - .arg(&image) - .arg(host); - build.run(&mut cmd); + make_win_dist(&tmpdir(build), &image, host, &build); let mut cmd = rust_installer(build); cmd.arg("generate") @@ -172,15 +299,8 @@ pub fn rustc(build: &Build, stage: u32, host: &str) { // anything requiring us to distribute a license, but it's likely the // install will *also* include the rust-mingw package, which also needs // licenses, so to be safe we just include it here in all MinGW packages. - // - // FIXME: this script should be rewritten into Rust if host.contains("pc-windows-gnu") { - let mut cmd = Command::new(build.python()); - cmd.arg(build.src.join("src/etc/make-win-dist.py")) - .arg(&image) - .arg(tmpdir(build)) - .arg(host); - build.run(&mut cmd); + make_win_dist(&image, &tmpdir(build), host, build); let dst = image.join("share/doc"); t!(fs::create_dir_all(&dst)); diff --git a/src/etc/make-win-dist.py b/src/etc/make-win-dist.py deleted file mode 100644 index 4699fefbb20e3..0000000000000 --- a/src/etc/make-win-dist.py +++ /dev/null @@ -1,126 +0,0 @@ -# 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 or the MIT license -# , at your -# option. This file may not be copied, modified, or distributed -# except according to those terms. - -# Script parameters: -# argv[1] = rust component root, -# argv[2] = gcc component root, -# argv[3] = target triple -# The first two correspond to the two installable components defined in the setup script. - -import sys -import os -import shutil -import 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 - - -# rust_root - root directory of the host binaries image -# plat_root - root directory of the target platform tools and libs image -# (the two get overlayed on top of each other during installation) -# target_triple - triple of the target image being layed out -def make_win_dist(rust_root, plat_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", - "libwinpthread-1.dll"] - - rustc_dlls = ["libstdc++-6.dll", "libwinpthread-1.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 = [ # MinGW libs - "libgcc.a", - "libgcc_eh.a", - "libgcc_s.a", - "libm.a", - "libmingw32.a", - "libmingwex.a", - "libstdc++.a", - "libiconv.a", - "libmoldname.a", - "libpthread.a", - # Windows import libs - "libadvapi32.a", - "libbcrypt.a", - "libcomctl32.a", - "libcomdlg32.a", - "libcrypt32.a", - "libgdi32.a", - "libimagehlp.a", - "libiphlpapi.a", - "libkernel32.a", - "libmsvcrt.a", - "libodbc32.a", - "libole32.a", - "liboleaut32.a", - "libopengl32.a", - "libpsapi.a", - "librpcrt4.a", - "libsetupapi.a", - "libshell32.a", - "libuser32.a", - "libuserenv.a", - "libuuid.a", - "libwinhttp.a", - "libwinmm.a", - "libwinspool.a", - "libws2_32.a", - "libwsock32.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(rust_root, "bin") - for src in rustc_dlls: - shutil.copy(src, dist_bin_dir) - - # Copy platform tools to platform-specific bin directory - target_bin_dir = os.path.join(plat_root, "lib", "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-specific lib directory - target_lib_dir = os.path.join(plat_root, "lib", "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) - -if __name__ == "__main__": - make_win_dist(sys.argv[1], sys.argv[2], sys.argv[3])