diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index 511f2c9e80ec7..b2b6f7e9156d6 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -20,6 +20,7 @@ use std::env; use std::fs::{self, File}; +use std::ffi::OsString; use std::io::{Read, Write}; use std::path::{PathBuf, Path}; use std::process::{Command, Stdio}; @@ -53,6 +54,98 @@ fn rust_installer(build: &Build) -> Command { build.tool_cmd(&Compiler::new(0, &build.config.build), "rust-installer") } +// 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 +fn make_win_dist(rust_root: &PathBuf, plat_root: &PathBuf, target_triple: &str) { + let paths = env::var_os("PATH").expect("env var PATH missing"); + let mut bin_path = env::split_paths(&paths) + .map(|path| path.into_os_string() ).collect::>(); + let mut lib_path = vec![]; + + let gcc_out = Command::new("gcc.exe") + .arg("-print-search-dirs") + .output() + .expect("failed to execute gcc.exe"); + for line in String::from_utf8_lossy(&gcc_out.stdout).lines() { + let key_val = line.splitn(2, ':').collect::>(); + let key = key_val.get(0).expect("key not found"); + let val = key_val.get(1).expect("val not found").trim_left_matches(" ="); + let values = env::split_paths(&val) + .map(|path| path.into_os_string() ).collect::>(); + + match *key { + "programs" => bin_path.extend_from_slice(&values), + "libraries" => lib_path.extend_from_slice(&values), + _ => {} + } + } + + let mut rustc_dlls = vec!["libstdc++-6.dll", "libwinpthread-1.dll"]; + rustc_dlls.push(if target_triple.starts_with("i686-") { + "libgcc_s_dw2-1.dll" + } else { + "libgcc_s_seh-1.dll" + }); + + let target_tools = vec![ + "gcc.exe", "ld.exe", "ar.exe", + "dlltool.exe", "libwinpthread-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", + ]; + + 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); + + // Copy runtime dlls next to rustc.exe + let dist_bin_dir = rust_root.join("bin"); + copy_files(&rustc_dlls, &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"); + copy_files(&target_tools, &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"); + copy_files(&target_libs, &target_lib_dir); + + fn copy_files(files: &Vec, dest: &PathBuf) { + if !dest.is_dir() { + t!(fs::create_dir_all(&dest)); + } + for src in files { + copy(src.as_path(), dest.as_path()); + } + } + + fn find_files(files: &Vec<&str>, path: &Vec) -> Vec { + files.iter().map(|fname| { + let fpath = path.iter() + .find(|dir| PathBuf::from(&dir).join(fname).is_file() ) + .expect(&format!("couldn't find {} in {:?}", fname, path)); + + PathBuf::from(&fpath).join(fname) + }).collect() + } +} + /// Builds the `rust-docs` installer component. /// /// Slurps up documentation from the `stage`'s `host`. @@ -113,14 +206,7 @@ pub fn mingw(build: &Build, host: &str) { // 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); let mut cmd = rust_installer(build); cmd.arg("generate") @@ -172,15 +258,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(&tmpdir(build), &image, host); 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])