diff --git a/README.md b/README.md index f387b4be6008f..dbb5bf9ce38d6 100644 --- a/README.md +++ b/README.md @@ -35,7 +35,7 @@ Read ["Installing Rust"] from [The Book]. 3. Build and install: ```sh - $ ./x.py build && sudo ./x.py dist --install + $ ./x.py build && sudo ./x.py install ``` > ***Note:*** Install locations can be adjusted by copying the config file @@ -43,7 +43,7 @@ Read ["Installing Rust"] from [The Book]. > adjusting the `prefix` option under `[install]`. Various other options are > also supported, and are documented in the config file. - When complete, `sudo ./x.py dist --install` will place several programs into + When complete, `sudo ./x.py install` will place several programs into `/usr/local/bin`: `rustc`, the Rust compiler, and `rustdoc`, the API-documentation tool. This install does not include [Cargo], Rust's package manager, which you may also want to build. @@ -96,7 +96,7 @@ build. 4. Navigate to Rust's source code (or clone it), then build it: ```sh - $ ./x.py build && ./x.py dist --install + $ ./x.py build && ./x.py install ``` #### MSVC diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py index bfba1a0dede24..40f9ac489b91a 100644 --- a/src/bootstrap/bootstrap.py +++ b/src/bootstrap/bootstrap.py @@ -40,7 +40,8 @@ def get(url, path, verbose=False): return else: if verbose: - print("ignoring already-download file " + path + " due to failed verification") + print("ignoring already-download file " + + path + " due to failed verification") os.unlink(path) download(temp_path, url, True, verbose) if not verify(temp_path, sha_path, verbose): @@ -100,8 +101,8 @@ def verify(path, sha_path, verbose): verified = found == expected if not verified: print("invalid checksum:\n" - " found: {}\n" - " expected: {}".format(found, expected)) + " found: {}\n" + " expected: {}".format(found, expected)) return verified @@ -127,13 +128,14 @@ def unpack(tarball, dst, verbose=False, match=None): shutil.move(tp, fp) shutil.rmtree(os.path.join(dst, fname)) -def run(args, verbose=False, exception=False, cwd=None): + +def run(args, verbose=False, exception=False): if verbose: print("running: " + ' '.join(args)) sys.stdout.flush() # Use Popen here instead of call() as it apparently allows powershell on # Windows to not lock up waiting for input presumably. - ret = subprocess.Popen(args, cwd=cwd) + ret = subprocess.Popen(args) code = ret.wait() if code != 0: err = "failed to run: " + ' '.join(args) @@ -141,6 +143,7 @@ def run(args, verbose=False, exception=False, cwd=None): raise RuntimeError(err) sys.exit(err) + def stage0_data(rust_root): nightlies = os.path.join(rust_root, "src/stage0.txt") data = {} @@ -153,11 +156,13 @@ def stage0_data(rust_root): data[a] = b return data + def format_build_time(duration): return str(datetime.timedelta(seconds=int(duration))) class RustBuild(object): + def download_stage0(self): cache_dst = os.path.join(self.build_dir, "cache") rustc_cache = os.path.join(cache_dst, self.stage0_date()) @@ -172,11 +177,13 @@ def download_stage0(self): self.print_what_it_means_to_bootstrap() if os.path.exists(self.bin_root()): shutil.rmtree(self.bin_root()) - filename = "rust-std-{}-{}.tar.gz".format(rustc_channel, self.build) + filename = "rust-std-{}-{}.tar.gz".format( + rustc_channel, self.build) url = self._download_url + "/dist/" + self.stage0_date() tarball = os.path.join(rustc_cache, filename) if not os.path.exists(tarball): - get("{}/{}".format(url, filename), tarball, verbose=self.verbose) + get("{}/{}".format(url, filename), + tarball, verbose=self.verbose) unpack(tarball, self.bin_root(), match="rust-std-" + self.build, verbose=self.verbose) @@ -185,20 +192,25 @@ def download_stage0(self): url = self._download_url + "/dist/" + self.stage0_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="rustc", verbose=self.verbose) + get("{}/{}".format(url, filename), + tarball, verbose=self.verbose) + unpack(tarball, self.bin_root(), + match="rustc", verbose=self.verbose) self.fix_executable(self.bin_root() + "/bin/rustc") self.fix_executable(self.bin_root() + "/bin/rustdoc") with open(self.rustc_stamp(), 'w') as f: f.write(self.stage0_date()) if "pc-windows-gnu" in self.build: - filename = "rust-mingw-{}-{}.tar.gz".format(rustc_channel, self.build) + filename = "rust-mingw-{}-{}.tar.gz".format( + rustc_channel, self.build) url = self._download_url + "/dist/" + self.stage0_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) + 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()): @@ -207,8 +219,10 @@ def download_stage0(self): url = self._download_url + "/dist/" + self.stage0_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="cargo", verbose=self.verbose) + get("{}/{}".format(url, filename), + tarball, verbose=self.verbose) + unpack(tarball, self.bin_root(), + match="cargo", verbose=self.verbose) self.fix_executable(self.bin_root() + "/bin/cargo") with open(self.cargo_stamp(), 'w') as f: f.write(self.stage0_date()) @@ -218,7 +232,8 @@ def fix_executable(self, fname): default_encoding = sys.getdefaultencoding() try: - ostype = subprocess.check_output(['uname', '-s']).strip().decode(default_encoding) + ostype = subprocess.check_output( + ['uname', '-s']).strip().decode(default_encoding) except (subprocess.CalledProcessError, WindowsError): return @@ -234,7 +249,8 @@ def fix_executable(self, fname): print("info: you seem to be running NixOS. Attempting to patch " + fname) try: - interpreter = subprocess.check_output(["patchelf", "--print-interpreter", fname]) + interpreter = subprocess.check_output( + ["patchelf", "--print-interpreter", fname]) interpreter = interpreter.strip().decode(default_encoding) except subprocess.CalledProcessError as e: print("warning: failed to call patchelf: %s" % e) @@ -243,7 +259,8 @@ def fix_executable(self, fname): loader = interpreter.split("/")[-1] try: - ldd_output = subprocess.check_output(['ldd', '/run/current-system/sw/bin/sh']) + ldd_output = subprocess.check_output( + ['ldd', '/run/current-system/sw/bin/sh']) ldd_output = ldd_output.strip().decode(default_encoding) except subprocess.CalledProcessError as e: print("warning: unable to call ldd: %s" % e) @@ -261,7 +278,8 @@ def fix_executable(self, fname): correct_interpreter = loader_path + loader try: - subprocess.check_output(["patchelf", "--set-interpreter", correct_interpreter, fname]) + subprocess.check_output( + ["patchelf", "--set-interpreter", correct_interpreter, fname]) except subprocess.CalledProcessError as e: print("warning: failed to call patchelf: %s" % e) return @@ -371,16 +389,16 @@ def build_bootstrap(self): env["CARGO_TARGET_DIR"] = build_dir env["RUSTC"] = self.rustc() env["LD_LIBRARY_PATH"] = os.path.join(self.bin_root(), "lib") + \ - (os.pathsep + env["LD_LIBRARY_PATH"]) \ - if "LD_LIBRARY_PATH" in env else "" + (os.pathsep + env["LD_LIBRARY_PATH"]) \ + if "LD_LIBRARY_PATH" in env else "" env["DYLD_LIBRARY_PATH"] = os.path.join(self.bin_root(), "lib") + \ - (os.pathsep + env["DYLD_LIBRARY_PATH"]) \ - if "DYLD_LIBRARY_PATH" in env else "" + (os.pathsep + env["DYLD_LIBRARY_PATH"]) \ + if "DYLD_LIBRARY_PATH" in env else "" env["LIBRARY_PATH"] = os.path.join(self.bin_root(), "lib") + \ - (os.pathsep + env["LIBRARY_PATH"]) \ - if "LIBRARY_PATH" in env else "" + (os.pathsep + env["LIBRARY_PATH"]) \ + if "LIBRARY_PATH" in env else "" env["PATH"] = os.path.join(self.bin_root(), "bin") + \ - os.pathsep + env["PATH"] + os.pathsep + env["PATH"] if not os.path.isfile(self.cargo()): raise Exception("no cargo executable found at `%s`" % self.cargo()) args = [self.cargo(), "build", "--manifest-path", @@ -389,23 +407,13 @@ def build_bootstrap(self): args.append("--locked") if self.use_vendored_sources: args.append("--frozen") - self.run(args, env) - - def run(self, args, env=None, cwd=None): - proc = subprocess.Popen(args, env=env, cwd=cwd) - ret = proc.wait() - if ret != 0: - sys.exit(ret) + self.run(args, env=env) - def output(self, args, env=None, cwd=None): - default_encoding = sys.getdefaultencoding() - proc = subprocess.Popen(args, stdout=subprocess.PIPE, env=env, cwd=cwd) - (out, err) = proc.communicate() + def run(self, args, **kwargs): + proc = subprocess.Popen(args, **kwargs) ret = proc.wait() if ret != 0: - print(out) sys.exit(ret) - return out.decode(default_encoding) def build_triple(self): default_encoding = sys.getdefaultencoding() @@ -416,8 +424,10 @@ def build_triple(self): if config: return config try: - ostype = subprocess.check_output(['uname', '-s']).strip().decode(default_encoding) - cputype = subprocess.check_output(['uname', '-m']).strip().decode(default_encoding) + ostype = subprocess.check_output( + ['uname', '-s']).strip().decode(default_encoding) + cputype = subprocess.check_output( + ['uname', '-m']).strip().decode(default_encoding) except (subprocess.CalledProcessError, OSError): if sys.platform == 'win32': return 'x86_64-pc-windows-msvc' @@ -429,7 +439,8 @@ def build_triple(self): # The goal here is to come up with the same triple as LLVM would, # at least for the subset of platforms we're willing to target. if ostype == 'Linux': - os_from_sp = subprocess.check_output(['uname', '-o']).strip().decode(default_encoding) + os_from_sp = subprocess.check_output( + ['uname', '-o']).strip().decode(default_encoding) if os_from_sp == 'Android': ostype = 'linux-android' else: @@ -453,7 +464,7 @@ def build_triple(self): # must be used instead. try: cputype = subprocess.check_output(['isainfo', - '-k']).strip().decode(default_encoding) + '-k']).strip().decode(default_encoding) except (subprocess.CalledProcessError, OSError): err = "isainfo not found" if self.verbose: @@ -546,51 +557,29 @@ def build_triple(self): def update_submodules(self): if (not os.path.exists(os.path.join(self.rust_root, ".git"))) or \ - self.get_toml('submodules') == "false" or \ - self.get_mk('CFG_DISABLE_MANAGE_SUBMODULES') == "1": + self.get_toml('submodules') == "false" or \ + self.get_mk('CFG_DISABLE_MANAGE_SUBMODULES') == "1": return - print('Updating submodules') - output = self.output(["git", "submodule", "status"], cwd=self.rust_root) - submodules = [] - for line in output.splitlines(): - # NOTE `git submodule status` output looks like this: - # - # -5066b7dcab7e700844b0e2ba71b8af9dc627a59b src/liblibc - # +b37ef24aa82d2be3a3cc0fe89bf82292f4ca181c src/compiler-rt (remotes/origin/..) - # e058ca661692a8d01f8cf9d35939dfe3105ce968 src/jemalloc (3.6.0-533-ge058ca6) - # - # The first character can be '-', '+' or ' ' and denotes the - # `State` of the submodule Right next to this character is the - # SHA-1 of the submodule HEAD And after that comes the path to the - # submodule - path = line[1:].split(' ')[1] - submodules.append([path, line[0]]) - - self.run(["git", "submodule", "sync"], cwd=self.rust_root) - - for submod in submodules: - path, status = submod - if path.endswith('llvm') and \ - (self.get_toml('llvm-config') or self.get_mk('CFG_LLVM_ROOT')): - continue - if path.endswith('jemalloc') and \ - (self.get_toml('jemalloc') or self.get_mk('CFG_JEMALLOC_ROOT')): - continue - submod_path = os.path.join(self.rust_root, path) - - if status == ' ': - self.run(["git", "reset", "--hard"], cwd=submod_path) - self.run(["git", "clean", "-fdx"], cwd=submod_path) - elif status == '+': - self.run(["git", "submodule", "update", path], cwd=self.rust_root) - self.run(["git", "reset", "--hard"], cwd=submod_path) - self.run(["git", "clean", "-fdx"], cwd=submod_path) - elif status == '-': - self.run(["git", "submodule", "init", path], cwd=self.rust_root) - self.run(["git", "submodule", "update", path], cwd=self.rust_root) - else: - raise ValueError('unknown submodule status: ' + status) + default_encoding = sys.getdefaultencoding() + self.run(["git", "submodule", "-q", "sync"], cwd=self.rust_root) + submodules = [s.split(' ', 1)[1] for s in subprocess.check_output( + ["git", "config", "--file", os.path.join(self.rust_root, ".gitmodules"), + "--get-regexp", "path"] + ).decode(default_encoding).splitlines()] + submodules = [module for module in submodules + if not ((module.endswith("llvm") and + (self.get_toml('llvm-config') or self.get_mk('CFG_LLVM_ROOT'))) or + (module.endswith("jemalloc") and + (self.get_toml('jemalloc') or self.get_mk('CFG_JEMALLOC_ROOT')))) + ] + self.run(["git", "submodule", "update", + "--init"] + submodules, cwd=self.rust_root) + self.run(["git", "submodule", "-q", "foreach", "git", + "reset", "-q", "--hard"], cwd=self.rust_root) + self.run(["git", "submodule", "-q", "foreach", "git", + "clean", "-qdfx"], cwd=self.rust_root) + def bootstrap(): parser = argparse.ArgumentParser(description='Build rust') @@ -638,7 +627,7 @@ def bootstrap(): if rb.use_vendored_sources: if not os.path.exists('.cargo'): os.makedirs('.cargo') - with open('.cargo/config','w') as f: + with open('.cargo/config', 'w') as f: f.write(""" [source.crates-io] replace-with = 'vendored-sources' @@ -676,15 +665,18 @@ def bootstrap(): env["BUILD"] = rb.build env["SRC"] = rb.rust_root env["BOOTSTRAP_PARENT_ID"] = str(os.getpid()) - rb.run(args, env) + rb.run(args, env=env) + def main(): start_time = time() - help_triggered = ('-h' in sys.argv) or ('--help' in sys.argv) or (len(sys.argv) == 1) + help_triggered = ( + '-h' in sys.argv) or ('--help' in sys.argv) or (len(sys.argv) == 1) try: bootstrap() if not help_triggered: - print("Build completed successfully in %s" % format_build_time(time() - start_time)) + print("Build completed successfully in %s" % + format_build_time(time() - start_time)) except (SystemExit, KeyboardInterrupt) as e: if hasattr(e, 'code') and isinstance(e.code, int): exit_code = e.code @@ -692,7 +684,8 @@ def main(): exit_code = 1 print(e) if not help_triggered: - print("Build completed unsuccessfully in %s" % format_build_time(time() - start_time)) + print("Build completed unsuccessfully in %s" % + format_build_time(time() - start_time)) sys.exit(exit_code) if __name__ == '__main__': diff --git a/src/bootstrap/config.toml.example b/src/bootstrap/config.toml.example index 95cca96f7fcc0..0eb6c4c82c4dd 100644 --- a/src/bootstrap/config.toml.example +++ b/src/bootstrap/config.toml.example @@ -314,3 +314,9 @@ # Note that this address should not contain a trailing slash as file names will # be appended to it. #upload-addr = "https://example.com/folder" + +# Whether to build a plain source tarball to upload +# We disable that on Windows not to override the one already uploaded on S3 +# as the one built on Windows will contain backslashes in paths causing problems +# on linux +#src-tarball = true diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs index 511f2c9e80ec7..94189d7eb92fd 100644 --- a/src/bootstrap/dist.rs +++ b/src/bootstrap/dist.rs @@ -30,11 +30,11 @@ use {Build, Compiler, Mode}; use channel; use util::{cp_r, libdir, is_dylib, cp_filtered, copy, exe}; -fn pkgname(build: &Build, component: &str) -> String { +pub fn pkgname(build: &Build, component: &str) -> String { if component == "cargo" { format!("{}-{}", component, build.cargo_package_vers()) } else if component == "rls" { - format!("{}-{}", component, build.package_vers(&build.release_num("rls"))) + format!("{}-{}", component, build.rls_package_vers()) } else { assert!(component.starts_with("rust")); format!("{}-{}", component, build.rust_package_vers()) @@ -369,38 +369,7 @@ pub fn analysis(build: &Build, compiler: &Compiler, target: &str) { t!(fs::remove_dir_all(&image)); } -const CARGO_VENDOR_VERSION: &'static str = "0.1.4"; - -/// Creates the `rust-src` installer component and the plain source tarball -pub fn rust_src(build: &Build) { - if !build.config.rust_dist_src { - return - } - - println!("Dist src"); - - // Make sure that the root folder of tarball has the correct name - let plain_name = format!("rustc-{}-src", build.rust_package_vers()); - let plain_dst_src = tmpdir(build).join(&plain_name); - let _ = fs::remove_dir_all(&plain_dst_src); - t!(fs::create_dir_all(&plain_dst_src)); - - // This is the set of root paths which will become part of the source package - let src_files = [ - "COPYRIGHT", - "LICENSE-APACHE", - "LICENSE-MIT", - "CONTRIBUTING.md", - "README.md", - "RELEASES.md", - "configure", - "x.py", - ]; - let src_dirs = [ - "man", - "src", - ]; - +fn copy_src_dirs(build: &Build, src_dirs: &[&str], dst_dir: &Path) { let filter_fn = move |path: &Path| { let spath = match path.to_str() { Some(path) => path, @@ -429,60 +398,16 @@ pub fn rust_src(build: &Build) { }; // Copy the directories using our filter - for item in &src_dirs { - let dst = &plain_dst_src.join(item); - t!(fs::create_dir(dst)); + for item in src_dirs { + let dst = &dst_dir.join(item); + t!(fs::create_dir_all(dst)); cp_filtered(&build.src.join(item), dst, &filter_fn); } - // Copy the files normally - for item in &src_files { - copy(&build.src.join(item), &plain_dst_src.join(item)); - } - - // If we're building from git sources, we need to vendor a complete distribution. - if build.src_is_git { - // Get cargo-vendor installed, if it isn't already. - let mut has_cargo_vendor = false; - let mut cmd = Command::new(&build.cargo); - for line in output(cmd.arg("install").arg("--list")).lines() { - has_cargo_vendor |= line.starts_with("cargo-vendor "); - } - if !has_cargo_vendor { - let mut cmd = Command::new(&build.cargo); - cmd.arg("install") - .arg("--force") - .arg("--debug") - .arg("--vers").arg(CARGO_VENDOR_VERSION) - .arg("cargo-vendor") - .env("RUSTC", &build.rustc); - build.run(&mut cmd); - } - - // Vendor all Cargo dependencies - let mut cmd = Command::new(&build.cargo); - cmd.arg("vendor") - .current_dir(&plain_dst_src.join("src")); - build.run(&mut cmd); - } - - // Create the version file - write_file(&plain_dst_src.join("version"), build.rust_version().as_bytes()); - - // Create plain source tarball - let mut tarball = rust_src_location(build); - tarball.set_extension(""); // strip .gz - tarball.set_extension(""); // strip .tar - if let Some(dir) = tarball.parent() { - t!(fs::create_dir_all(dir)); - } - let mut cmd = rust_installer(build); - cmd.arg("tarball") - .arg("--input").arg(&plain_name) - .arg("--output").arg(&tarball) - .arg("--work-dir=.") - .current_dir(tmpdir(build)); - build.run(&mut cmd); +} +/// Creates the `rust-src` installer component +pub fn rust_src(build: &Build) { + println!("Dist src"); let name = pkgname(build, "rust-src"); let image = tmpdir(build).join(format!("{}-image", name)); @@ -516,11 +441,7 @@ pub fn rust_src(build: &Build) { "src/rustc/libc_shim", ]; - for item in &std_src_dirs { - let dst = &dst_src.join(item); - t!(fs::create_dir_all(dst)); - cp_r(&plain_dst_src.join(item), dst); - } + copy_src_dirs(build, &std_src_dirs[..], &dst_src); // Create source tarball in rust-installer format let mut cmd = rust_installer(build); @@ -537,7 +458,86 @@ pub fn rust_src(build: &Build) { build.run(&mut cmd); t!(fs::remove_dir_all(&image)); - t!(fs::remove_dir_all(&plain_dst_src)); +} + +const CARGO_VENDOR_VERSION: &'static str = "0.1.4"; + +/// Creates the plain source tarball +pub fn plain_source_tarball(build: &Build) { + println!("Create plain source tarball"); + + // Make sure that the root folder of tarball has the correct name + let plain_name = format!("{}-src", pkgname(build, "rustc")); + let plain_dst_src = tmpdir(build).join(&plain_name); + let _ = fs::remove_dir_all(&plain_dst_src); + t!(fs::create_dir_all(&plain_dst_src)); + + // This is the set of root paths which will become part of the source package + let src_files = [ + "COPYRIGHT", + "LICENSE-APACHE", + "LICENSE-MIT", + "CONTRIBUTING.md", + "README.md", + "RELEASES.md", + "configure", + "x.py", + ]; + let src_dirs = [ + "man", + "src", + ]; + + copy_src_dirs(build, &src_dirs[..], &plain_dst_src); + + // Copy the files normally + for item in &src_files { + copy(&build.src.join(item), &plain_dst_src.join(item)); + } + + // Create the version file + write_file(&plain_dst_src.join("version"), build.rust_version().as_bytes()); + + // If we're building from git sources, we need to vendor a complete distribution. + if build.src_is_git { + // Get cargo-vendor installed, if it isn't already. + let mut has_cargo_vendor = false; + let mut cmd = Command::new(&build.cargo); + for line in output(cmd.arg("install").arg("--list")).lines() { + has_cargo_vendor |= line.starts_with("cargo-vendor "); + } + if !has_cargo_vendor { + let mut cmd = Command::new(&build.cargo); + cmd.arg("install") + .arg("--force") + .arg("--debug") + .arg("--vers").arg(CARGO_VENDOR_VERSION) + .arg("cargo-vendor") + .env("RUSTC", &build.rustc); + build.run(&mut cmd); + } + + // Vendor all Cargo dependencies + let mut cmd = Command::new(&build.cargo); + cmd.arg("vendor") + .current_dir(&plain_dst_src.join("src")); + build.run(&mut cmd); + } + + // Create plain source tarball + let mut tarball = rust_src_location(build); + tarball.set_extension(""); // strip .gz + tarball.set_extension(""); // strip .tar + if let Some(dir) = tarball.parent() { + t!(fs::create_dir_all(dir)); + } + let mut cmd = rust_installer(build); + cmd.arg("tarball") + .arg("--input").arg(&plain_name) + .arg("--output").arg(&tarball) + .arg("--work-dir=.") + .current_dir(tmpdir(build)); + build.run(&mut cmd); } fn install(src: &Path, dstdir: &Path, perms: u32) { diff --git a/src/bootstrap/flags.rs b/src/bootstrap/flags.rs index a1466d68a135a..fe4e18ab622cd 100644 --- a/src/bootstrap/flags.rs +++ b/src/bootstrap/flags.rs @@ -69,7 +69,9 @@ pub enum Subcommand { Clean, Dist { paths: Vec, - install: bool, + }, + Install { + paths: Vec, }, } @@ -85,7 +87,8 @@ Subcommands: bench Build and run some benchmarks doc Build documentation clean Clean out build directories - dist Build and/or install distribution artifacts + dist Build distribution artifacts + install Install distribution artifacts To learn more about a subcommand, run `./x.py -h`"); @@ -125,7 +128,8 @@ To learn more about a subcommand, run `./x.py -h`"); || (s == "bench") || (s == "doc") || (s == "clean") - || (s == "dist")); + || (s == "dist") + || (s == "install")); let subcommand = match possible_subcommands.first() { Some(s) => s, None => { @@ -139,7 +143,6 @@ To learn more about a subcommand, run `./x.py -h`"); match subcommand.as_str() { "test" => { opts.optmulti("", "test-args", "extra arguments", "ARGS"); }, "bench" => { opts.optmulti("", "test-args", "extra arguments", "ARGS"); }, - "dist" => { opts.optflag("", "install", "run installer as well"); }, _ => { }, }; @@ -281,7 +284,11 @@ Arguments: "dist" => { Subcommand::Dist { paths: paths, - install: matches.opt_present("install"), + } + } + "install" => { + Subcommand::Install { + paths: paths, } } _ => { diff --git a/src/bootstrap/install.rs b/src/bootstrap/install.rs index dce0b1670e181..21e21628dc947 100644 --- a/src/bootstrap/install.rs +++ b/src/bootstrap/install.rs @@ -19,7 +19,7 @@ use std::path::{Path, PathBuf, Component}; use std::process::Command; use Build; -use dist::{sanitize_sh, tmpdir}; +use dist::{pkgname, sanitize_sh, tmpdir}; pub struct Installer<'a> { build: &'a Build, @@ -29,6 +29,13 @@ pub struct Installer<'a> { bindir: PathBuf, libdir: PathBuf, mandir: PathBuf, + empty_dir: PathBuf, +} + +impl<'a> Drop for Installer<'a> { + fn drop(&mut self) { + t!(fs::remove_dir_all(&self.empty_dir)); + } } impl<'a> Installer<'a> { @@ -61,6 +68,10 @@ impl<'a> Installer<'a> { let libdir = add_destdir(&libdir, &destdir); let mandir = add_destdir(&mandir, &destdir); + let empty_dir = build.out.join("tmp/empty_dir"); + + t!(fs::create_dir_all(&empty_dir)); + Installer { build, prefix, @@ -69,52 +80,49 @@ impl<'a> Installer<'a> { bindir, libdir, mandir, + empty_dir, } } - /// Installs everything. - pub fn install(&self, stage: u32, host: &str) { - let empty_dir = self.build.out.join("tmp/empty_dir"); - t!(fs::create_dir_all(&empty_dir)); - - if self.build.config.docs { - self.install_sh("docs", "rust-docs", &self.build.rust_package_vers(), - stage, Some(host), &empty_dir); - } + pub fn install_docs(&self, stage: u32, host: &str) { + self.install_sh("docs", "rust-docs", stage, Some(host)); + } + pub fn install_std(&self, stage: u32) { for target in self.build.config.target.iter() { - self.install_sh("std", "rust-std", &self.build.rust_package_vers(), - stage, Some(target), &empty_dir); + self.install_sh("std", "rust-std", stage, Some(target)); } + } - if self.build.config.extended { - self.install_sh("cargo", "cargo", &self.build.cargo_package_vers(), - stage, Some(host), &empty_dir); - self.install_sh("rls", "rls", &self.build.rls_package_vers(), - stage, Some(host), &empty_dir); - self.install_sh("analysis", "rust-analysis", &self.build.rust_package_vers(), - stage, Some(host), &empty_dir); - self.install_sh("src", "rust-src", &self.build.rust_package_vers(), - stage, None, &empty_dir); - } + pub fn install_cargo(&self, stage: u32, host: &str) { + self.install_sh("cargo", "cargo", stage, Some(host)); + } - self.install_sh("rustc", "rustc", &self.build.rust_package_vers(), - stage, Some(host), &empty_dir); + pub fn install_rls(&self, stage: u32, host: &str) { + self.install_sh("rls", "rls", stage, Some(host)); + } + + pub fn install_analysis(&self, stage: u32, host: &str) { + self.install_sh("analysis", "rust-analysis", stage, Some(host)); + } - t!(fs::remove_dir_all(&empty_dir)); + pub fn install_src(&self, stage: u32) { + self.install_sh("src", "rust-src", stage, None); + } + pub fn install_rustc(&self, stage: u32, host: &str) { + self.install_sh("rustc", "rustc", stage, Some(host)); } - fn install_sh(&self, package: &str, name: &str, version: &str, - stage: u32, host: Option<&str>, empty_dir: &Path) { + fn install_sh(&self, package: &str, name: &str, stage: u32, host: Option<&str>) { println!("Install {} stage{} ({:?})", package, stage, host); let package_name = if let Some(host) = host { - format!("{}-{}-{}", name, version, host) + format!("{}-{}", pkgname(self.build, name), host) } else { - format!("{}-{}", name, version) + pkgname(self.build, name) }; let mut cmd = Command::new("sh"); - cmd.current_dir(empty_dir) + cmd.current_dir(&self.empty_dir) .arg(sanitize_sh(&tmpdir(self.build).join(&package_name).join("install.sh"))) .arg(format!("--prefix={}", sanitize_sh(&self.prefix))) .arg(format!("--sysconfdir={}", sanitize_sh(&self.sysconfdir))) diff --git a/src/bootstrap/mk/Makefile.in b/src/bootstrap/mk/Makefile.in index a5df741e2bfc8..47c792a510b1b 100644 --- a/src/bootstrap/mk/Makefile.in +++ b/src/bootstrap/mk/Makefile.in @@ -69,7 +69,7 @@ distcheck: $(Q)$(BOOTSTRAP) dist $(BOOTSTRAP_ARGS) $(Q)$(BOOTSTRAP) test distcheck $(BOOTSTRAP_ARGS) install: - $(Q)$(BOOTSTRAP) dist --install $(BOOTSTRAP_ARGS) + $(Q)$(BOOTSTRAP) install $(BOOTSTRAP_ARGS) tidy: $(Q)$(BOOTSTRAP) test src/tools/tidy $(BOOTSTRAP_ARGS) prepare: diff --git a/src/bootstrap/step.rs b/src/bootstrap/step.rs index 57915446e1d1a..8e65fbd40b460 100644 --- a/src/bootstrap/step.rs +++ b/src/bootstrap/step.rs @@ -492,7 +492,7 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules { .host(true) .run(move |s| check::docs(build, &s.compiler())); rules.test("check-distcheck", "distcheck") - .dep(|s| s.name("dist-src")) + .dep(|s| s.name("dist-plain-source-tarball")) .run(move |_| check::distcheck(build)); rules.build("test-helpers", "src/rt/rust_test_helpers.c") @@ -734,6 +734,13 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules { dist::mingw(build, s.target) } }); + rules.dist("dist-plain-source-tarball", "src") + .default(build.config.rust_dist_src) + .host(true) + .only_build(true) + .only_host_build(true) + .dep(move |s| tool_rust_installer(build, s)) + .run(move |_| dist::plain_source_tarball(build)); rules.dist("dist-src", "src") .default(true) .host(true) @@ -759,9 +766,6 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules { .dep(|s| s.name("tool-rls")) .dep(move |s| tool_rust_installer(build, s)) .run(move |s| dist::rls(build, s.stage, s.target)); - rules.dist("install", "path/to/nowhere") - .dep(|s| s.name("default:dist")) - .run(move |s| install::Installer::new(build).install(s.stage, s.target)); rules.dist("dist-cargo", "cargo") .host(true) .only_host_build(true) @@ -789,6 +793,47 @@ pub fn build_rules<'a>(build: &'a Build) -> Rules { .dep(move |s| s.name("tool-build-manifest").target(&build.config.build).stage(0)) .run(move |_| dist::hash_and_sign(build)); + rules.install("install-docs", "src/doc") + .default(build.config.docs) + .only_host_build(true) + .dep(|s| s.name("dist-docs")) + .run(move |s| install::Installer::new(build).install_docs(s.stage, s.target)); + rules.install("install-std", "src/libstd") + .default(true) + .only_host_build(true) + .dep(|s| s.name("dist-std")) + .run(move |s| install::Installer::new(build).install_std(s.stage)); + rules.install("install-cargo", "cargo") + .default(build.config.extended) + .host(true) + .only_host_build(true) + .dep(|s| s.name("dist-cargo")) + .run(move |s| install::Installer::new(build).install_cargo(s.stage, s.target)); + rules.install("install-rls", "rls") + .default(build.config.extended) + .host(true) + .only_host_build(true) + .dep(|s| s.name("dist-rls")) + .run(move |s| install::Installer::new(build).install_rls(s.stage, s.target)); + rules.install("install-analysis", "analysis") + .default(build.config.extended) + .only_host_build(true) + .dep(|s| s.name("dist-analysis")) + .run(move |s| install::Installer::new(build).install_analysis(s.stage, s.target)); + rules.install("install-src", "src") + .default(build.config.extended) + .host(true) + .only_build(true) + .only_host_build(true) + .dep(|s| s.name("dist-src")) + .run(move |s| install::Installer::new(build).install_src(s.stage)); + rules.install("install-rustc", "src/librustc") + .default(true) + .host(true) + .only_host_build(true) + .dep(|s| s.name("dist-rustc")) + .run(move |s| install::Installer::new(build).install_rustc(s.stage, s.target)); + rules.verify(); return rules; @@ -902,6 +947,7 @@ enum Kind { Bench, Dist, Doc, + Install, } impl<'a> Rule<'a> { @@ -1033,6 +1079,12 @@ impl<'a> Rules<'a> { self.rule(name, path, Kind::Dist) } + /// Same as `build`, but for `Kind::Install`. + fn install<'b>(&'b mut self, name: &'a str, path: &'a str) + -> RuleBuilder<'a, 'b> { + self.rule(name, path, Kind::Install) + } + fn rule<'b>(&'b mut self, name: &'a str, path: &'a str, @@ -1073,6 +1125,7 @@ invalid rule dependency graph detected, was a rule added and maybe typo'd? "test" => Kind::Test, "bench" => Kind::Bench, "dist" => Kind::Dist, + "install" => Kind::Install, _ => return None, }; let rules = self.rules.values().filter(|r| r.kind == kind); @@ -1122,13 +1175,8 @@ invalid rule dependency graph detected, was a rule added and maybe typo'd? Subcommand::Doc { ref paths } => (Kind::Doc, &paths[..]), Subcommand::Test { ref paths, test_args: _ } => (Kind::Test, &paths[..]), Subcommand::Bench { ref paths, test_args: _ } => (Kind::Bench, &paths[..]), - Subcommand::Dist { ref paths, install } => { - if install { - return vec![self.sbuild.name("install")] - } else { - (Kind::Dist, &paths[..]) - } - } + Subcommand::Dist { ref paths } => (Kind::Dist, &paths[..]), + Subcommand::Install { ref paths } => (Kind::Install, &paths[..]), Subcommand::Clean => panic!(), }; @@ -1347,10 +1395,6 @@ mod tests { use config::Config; use flags::Flags; - macro_rules! a { - ($($a:expr),*) => (vec![$($a.to_string()),*]) - } - fn build(args: &[&str], extra_host: &[&str], extra_target: &[&str]) -> Build { diff --git a/src/doc/unstable-book/src/library-features/step-trait.md b/src/doc/unstable-book/src/library-features/step-trait.md index e53ca13f7b6f5..56050c20c6915 100644 --- a/src/doc/unstable-book/src/library-features/step-trait.md +++ b/src/doc/unstable-book/src/library-features/step-trait.md @@ -1,7 +1,7 @@ # `step_trait` -The tracking issue for this feature is: [#27741] +The tracking issue for this feature is: [#42168] -[#27741]: https://github.com/rust-lang/rust/issues/27741 +[#42168]: https://github.com/rust-lang/rust/issues/42168 ------------------------ diff --git a/src/libcore/iter/mod.rs b/src/libcore/iter/mod.rs index f9b818f5bff35..54919a414786d 100644 --- a/src/libcore/iter/mod.rs +++ b/src/libcore/iter/mod.rs @@ -309,7 +309,7 @@ pub use self::iterator::Iterator; #[unstable(feature = "step_trait", reason = "likely to be replaced by finer-grained traits", - issue = "27741")] + issue = "42168")] pub use self::range::Step; #[unstable(feature = "step_by", reason = "recent addition", issue = "27741")] diff --git a/src/libcore/iter/range.rs b/src/libcore/iter/range.rs index bd831d638c0c4..8d370f9675f3e 100644 --- a/src/libcore/iter/range.rs +++ b/src/libcore/iter/range.rs @@ -20,7 +20,7 @@ use super::{FusedIterator, TrustedLen}; /// two `Step` objects. #[unstable(feature = "step_trait", reason = "likely to be replaced by finer-grained traits", - issue = "27741")] + issue = "42168")] pub trait Step: PartialOrd + Sized { /// Steps `self` if possible. fn step(&self, by: &Self) -> Option; @@ -55,7 +55,7 @@ macro_rules! step_impl_unsigned { ($($t:ty)*) => ($( #[unstable(feature = "step_trait", reason = "likely to be replaced by finer-grained traits", - issue = "27741")] + issue = "42168")] impl Step for $t { #[inline] fn step(&self, by: &$t) -> Option<$t> { @@ -115,7 +115,7 @@ macro_rules! step_impl_signed { ($($t:ty)*) => ($( #[unstable(feature = "step_trait", reason = "likely to be replaced by finer-grained traits", - issue = "27741")] + issue = "42168")] impl Step for $t { #[inline] fn step(&self, by: &$t) -> Option<$t> { @@ -187,7 +187,7 @@ macro_rules! step_impl_no_between { ($($t:ty)*) => ($( #[unstable(feature = "step_trait", reason = "likely to be replaced by finer-grained traits", - issue = "27741")] + issue = "42168")] impl Step for $t { #[inline] fn step(&self, by: &$t) -> Option<$t> { diff --git a/src/libcore/ops.rs b/src/libcore/ops.rs index fc3af096b1838..4fb1f1757bbf7 100644 --- a/src/libcore/ops.rs +++ b/src/libcore/ops.rs @@ -153,6 +153,13 @@ use marker::Unsize; /// The `Drop` trait is used to run some code when a value goes out of scope. /// This is sometimes called a 'destructor'. /// +/// When a value goes out of scope, if it implements this trait, it will have +/// its `drop` method called. Then any fields the value contains will also +/// be dropped recursively. +/// +/// Because of the recursive dropping, you do not need to implement this trait +/// unless your type needs its own destructor logic. +/// /// # Examples /// /// A trivial implementation of `Drop`. The `drop` method is called when `_x` @@ -171,6 +178,43 @@ use marker::Unsize; /// let _x = HasDrop; /// } /// ``` +/// +/// Showing the recursive nature of `Drop`. When `outer` goes out of scope, the +/// `drop` method will be called first for `Outer`, then for `Inner`. Therefore +/// `main` prints `Dropping Outer!` and then `Dropping Inner!`. +/// +/// ``` +/// struct Inner; +/// struct Outer(Inner); +/// +/// impl Drop for Inner { +/// fn drop(&mut self) { +/// println!("Dropping Inner!"); +/// } +/// } +/// +/// impl Drop for Outer { +/// fn drop(&mut self) { +/// println!("Dropping Outer!"); +/// } +/// } +/// +/// fn main() { +/// let _x = Outer(Inner); +/// } +/// ``` +/// +/// Because variables are dropped in the reverse order they are declared, +/// `main` will print `Declared second!` and then `Declared first!`. +/// +/// ``` +/// struct PrintOnDrop(&'static str); +/// +/// fn main() { +/// let _first = PrintOnDrop("Declared first!"); +/// let _second = PrintOnDrop("Declared second!"); +/// } +/// ``` #[lang = "drop"] #[stable(feature = "rust1", since = "1.0.0")] pub trait Drop { diff --git a/src/libstd/rt.rs b/src/libstd/rt.rs index acff7faf8a7d0..06fd838ea06d9 100644 --- a/src/libstd/rt.rs +++ b/src/libstd/rt.rs @@ -35,6 +35,8 @@ fn lang_start(main: fn(), argc: isize, argv: *const *const u8) -> isize { use sys_common; use sys_common::thread_info; use thread::Thread; + #[cfg(not(feature = "backtrace"))] + use mem; sys::init(); @@ -53,9 +55,12 @@ fn lang_start(main: fn(), argc: isize, argv: *const *const u8) -> isize { sys::args::init(argc, argv); // Let's run some code! + #[cfg(feature = "backtrace")] let res = panic::catch_unwind(|| { ::sys_common::backtrace::__rust_begin_short_backtrace(main) }); + #[cfg(not(feature = "backtrace"))] + let res = panic::catch_unwind(mem::transmute::<_, fn()>(main)); sys_common::cleanup(); res.is_err() }; diff --git a/src/libstd/sys/redox/thread_local.rs b/src/libstd/sys/redox/thread_local.rs index abdd9ace795f4..cacd84e21025f 100644 --- a/src/libstd/sys/redox/thread_local.rs +++ b/src/libstd/sys/redox/thread_local.rs @@ -64,3 +64,8 @@ pub unsafe fn set(key: Key, value: *mut u8) { pub unsafe fn destroy(key: Key) { keys().remove(&key); } + +#[inline] +pub fn requires_synchronized_create() -> bool { + false +} diff --git a/src/libstd/thread/mod.rs b/src/libstd/thread/mod.rs index 154406a1d8bd7..75717abb4ad28 100644 --- a/src/libstd/thread/mod.rs +++ b/src/libstd/thread/mod.rs @@ -359,9 +359,12 @@ impl Builder { } unsafe { thread_info::set(imp::guard::current(), their_thread); + #[cfg(feature = "backtrace")] let try_result = panic::catch_unwind(panic::AssertUnwindSafe(|| { ::sys_common::backtrace::__rust_begin_short_backtrace(f) })); + #[cfg(not(feature = "backtrace"))] + let try_result = panic::catch_unwind(panic::AssertUnwindSafe(f)); *their_packet.get() = Some(try_result); } }; diff --git a/src/libsyntax/parse/lexer/unicode_chars.rs b/src/libsyntax/parse/lexer/unicode_chars.rs index 4df23da3c9ce3..83a164bdb9693 100644 --- a/src/libsyntax/parse/lexer/unicode_chars.rs +++ b/src/libsyntax/parse/lexer/unicode_chars.rs @@ -238,7 +238,7 @@ pub fn check_for_substitution<'a>(reader: &StringReader<'a>, match ASCII_ARRAY.iter().find(|&&(c, _)| c == ascii_char) { Some(&(ascii_char, ascii_name)) => { let msg = - format!("unicode character '{}' ({}) looks much like '{}' ({}), but it's not", + format!("unicode character '{}' ({}) looks like '{}' ({}), but it's not", ch, u_name, ascii_char, ascii_name); err.span_help(span, &msg); }, diff --git a/src/test/compile-fail-fulldeps/proc-macro/feature-gate-proc_macro.rs b/src/test/compile-fail-fulldeps/proc-macro/feature-gate-proc_macro.rs index 7e32800e0f9b8..eeede4b8aa13c 100644 --- a/src/test/compile-fail-fulldeps/proc-macro/feature-gate-proc_macro.rs +++ b/src/test/compile-fail-fulldeps/proc-macro/feature-gate-proc_macro.rs @@ -9,7 +9,6 @@ // except according to those terms. // aux-build:attr_proc_macro.rs -// gate-test-proc_macro #![feature(use_extern_macros)] extern crate attr_proc_macro; @@ -21,4 +20,4 @@ struct Foo; fn main() { let _ = Foo; -} \ No newline at end of file +} diff --git a/src/test/compile-fail/feature-gate-global_asm.rs b/src/test/compile-fail/feature-gate-global_asm.rs index 0560abb6af498..77f61ba47b005 100644 --- a/src/test/compile-fail/feature-gate-global_asm.rs +++ b/src/test/compile-fail/feature-gate-global_asm.rs @@ -8,8 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -// gate-test-global_asm - global_asm!(""); //~ ERROR `global_asm!` is not stable fn main() {} diff --git a/src/test/parse-fail/unicode-chars.rs b/src/test/parse-fail/unicode-chars.rs index adfaf62b5d3cc..1bdeb121a55d5 100644 --- a/src/test/parse-fail/unicode-chars.rs +++ b/src/test/parse-fail/unicode-chars.rs @@ -9,10 +9,9 @@ // except according to those terms. // compile-flags: -Z parse-only -// ignore-tidy-linelength fn main() { let y = 0; //~^ ERROR unknown start of token: \u{37e} - //~^^ HELP unicode character ';' (Greek Question Mark) looks much like ';' (Semicolon), but it's not + //~^^ HELP unicode character ';' (Greek Question Mark) looks like ';' (Semicolon), but it's not } diff --git a/src/tools/tidy/src/features.rs b/src/tools/tidy/src/features.rs index ad0d2fa0b3635..791b8d77e0b90 100644 --- a/src/tools/tidy/src/features.rs +++ b/src/tools/tidy/src/features.rs @@ -70,7 +70,7 @@ pub fn check(path: &Path, bad: &mut bool) { } let filen_underscore = filename.replace("-","_").replace(".rs",""); - test_filen_gate(&filen_underscore, &mut features); + let filename_is_gate_test = test_filen_gate(&filen_underscore, &mut features); contents.truncate(0); t!(t!(File::open(&file), &file).read_to_string(&mut contents)); @@ -92,17 +92,20 @@ pub fn check(path: &Path, bad: &mut bool) { }, None => continue, }; - let found_feature = features.get_mut(feature_name) - .map(|v| { v.has_gate_test = true; () }) - .is_some(); - - let found_lib_feature = features.get_mut(feature_name) - .map(|v| { v.has_gate_test = true; () }) - .is_some(); - - if !(found_feature || found_lib_feature) { - err(&format!("gate-test test found referencing a nonexistent feature '{}'", - feature_name)); + match features.get_mut(feature_name) { + Some(f) => { + if filename_is_gate_test { + err(&format!("The file is already marked as gate test \ + through its name, no need for a \ + 'gate-test-{}' comment", + feature_name)); + } + f.has_gate_test = true; + } + None => { + err(&format!("gate-test test found referencing a nonexistent feature '{}'", + feature_name)); + } } } }); @@ -265,4 +268,4 @@ pub fn collect_lib_features(base_src_path: &Path, } }); lib_features -} \ No newline at end of file +}