From 6dff251e35736fa74eaab6ddbc8b6ecec08ecf48 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Tue, 9 Jan 2018 22:53:26 +0100 Subject: [PATCH 01/10] Revert "Use rustdoc --document-private-item instead of deprecated flags" This reverts commit d96f0ff6a77e309682898cc7e1905a7bd0feb3cf. --- etc/rustdoc-with-private | 4 ++++ python/servo/command_base.py | 7 +++++-- python/servo/testing_commands.py | 5 +---- 3 files changed, 10 insertions(+), 6 deletions(-) create mode 100755 etc/rustdoc-with-private diff --git a/etc/rustdoc-with-private b/etc/rustdoc-with-private new file mode 100755 index 000000000000..097c237c5623 --- /dev/null +++ b/etc/rustdoc-with-private @@ -0,0 +1,4 @@ +#!/bin/sh +# Skip the strip-private and strip-hidden rustdoc passes +# https://github.com/rust-lang/rust/issues/15347 +rustdoc --no-defaults --passes collapse-docs --passes unindent-comments --passes strip-priv-imports "$@" diff --git a/python/servo/command_base.py b/python/servo/command_base.py index 4b29b25daf6f..3ff2a6eea3b9 100644 --- a/python/servo/command_base.py +++ b/python/servo/command_base.py @@ -388,7 +388,7 @@ def get_binary_path(self, release, dev, android=False): " --release" if release else "")) sys.exit() - def build_env(self, hosts_file_path=None, target=None, is_build=False, geckolib=False): + def build_env(self, hosts_file_path=None, target=None, is_build=False, geckolib=False, test_unit=False): """Return an extended environment dictionary.""" env = os.environ.copy() if sys.platform == "win32" and type(env['PATH']) == unicode: @@ -486,7 +486,10 @@ def package_dir(package): if hosts_file_path: env['HOST_FILE'] = hosts_file_path - env['RUSTDOCFLAGS'] = "--document-private-items" + if not test_unit: + # This wrapper script is in bash and doesn't work on Windows + # where we want to run doctests as part of `./mach test-unit` + env['RUSTDOC'] = path.join(self.context.topdir, 'etc', 'rustdoc-with-private') if self.config["build"]["rustflags"]: env['RUSTFLAGS'] = env.get('RUSTFLAGS', "") + " " + self.config["build"]["rustflags"] diff --git a/python/servo/testing_commands.py b/python/servo/testing_commands.py index de77c85c2854..8a8c41597b93 100644 --- a/python/servo/testing_commands.py +++ b/python/servo/testing_commands.py @@ -255,12 +255,9 @@ def test_unit(self, test_name=None, package=None, bench=False, nocapture=False): packages.discard('stylo') - env = self.build_env() + env = self.build_env(test_unit=True) env["RUST_BACKTRACE"] = "1" - # Work around https://github.com/rust-lang/cargo/issues/4790 - del env["RUSTDOCFLAGS"] - if "msvc" in host_triple(): # on MSVC, we need some DLLs in the path. They were copied # in to the servo.exe build dir, so just point PATH to that. From 365a139716436bed8e6a178f4539e4a3d31099c4 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Mon, 27 Nov 2017 18:02:53 +0100 Subject: [PATCH 02/10] Use rustup.rs instead of custom bootstrap Fixes #11361, closes #18874 --- .travis.yml | 2 + appveyor.yml | 7 + ...-stable-version => geckolib-rust-toolchain | 0 python/servo/bootstrap_commands.py | 222 ++---------------- python/servo/build_commands.py | 20 +- python/servo/command_base.py | 131 ++++------- python/servo/devenv_commands.py | 39 +-- python/servo/post_build_commands.py | 20 +- python/servo/testing_commands.py | 18 +- python/servo/util.py | 7 +- servobuild.example | 21 +- 11 files changed, 125 insertions(+), 362 deletions(-) rename rust-stable-version => geckolib-rust-toolchain (100%) diff --git a/.travis.yml b/.travis.yml index 1354e724483e..7e13c36e8bb6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -19,6 +19,8 @@ matrix: - sudo apt-get install clang-3.9 llvm-3.9 llvm-3.9-runtime -y - export LLVM_CONFIG=/usr/lib/llvm-3.9/bin/llvm-config - export CC=gcc-5 CXX=g++-5 + - curl https://sh.rustup.rs -sSf | sh -s -- --default-toolchain none -y + - source ~/.profile script: - ./mach build -d --verbose - ./mach test-unit diff --git a/appveyor.yml b/appveyor.yml index 841213809578..2028871b170e 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -41,6 +41,13 @@ cache: - .cargo -> rust-toolchain - .ccache +install: + - appveyor-retry appveyor DownloadFile https://win.rustup.rs/ -FileName rustup-init.exe + - rustup-init.exe -y --default-host x86_64-pc-windows-msvc --default-toolchain none + - set PATH=%PATH%;C:\Users\appveyor\.cargo\bin + - mach rustc --version + - mach cargo --version + # Uncomment these lines to expose RDP access information to the build machine in the build log. #init: # - ps: iex ((new-object net.webclient).DownloadString('https://raw.githubusercontent.com/appveyor/ci/master/scripts/enable-rdp.ps1')) diff --git a/rust-stable-version b/geckolib-rust-toolchain similarity index 100% rename from rust-stable-version rename to geckolib-rust-toolchain diff --git a/python/servo/bootstrap_commands.py b/python/servo/bootstrap_commands.py index ba583735011d..ccc971e5b570 100644 --- a/python/servo/bootstrap_commands.py +++ b/python/servo/bootstrap_commands.py @@ -14,7 +14,6 @@ import os import os.path as path import re -import shutil import subprocess import sys import urllib2 @@ -27,9 +26,8 @@ ) import servo.bootstrap as bootstrap -from servo.command_base import CommandBase, BIN_SUFFIX, cd -from servo.util import delete, download_bytes, download_file, extract, host_triple -from servo.util import STATIC_RUST_LANG_ORG_DIST +from servo.command_base import CommandBase, cd, check_call +from servo.util import delete, download_bytes @CommandProvider @@ -39,6 +37,7 @@ class MachCommands(CommandBase): category='bootstrap') def env(self): env = self.build_env() + print("export RUSTFLAGS=%s" % env["RUSTFLAGS"]) print("export PATH=%s" % env["PATH"]) if sys.platform == "darwin": print("export DYLD_LIBRARY_PATH=%s" % env["DYLD_LIBRARY_PATH"]) @@ -54,161 +53,6 @@ def env(self): def bootstrap(self, force=False): return bootstrap.bootstrap(self.context, force=force) - @Command('bootstrap-rust', - description='Download the Rust compiler', - category='bootstrap') - @CommandArgument('--force', '-f', - action='store_true', - help='Force download even if a copy already exists') - @CommandArgument('--target', - action='append', - default=[], - help='Download rust stdlib for specified target') - @CommandArgument('--stable', - action='store_true', - help='Use stable rustc version') - def bootstrap_rustc(self, force=False, target=[], stable=False): - self.set_use_stable_rust(stable) - rust_dir = path.join(self.context.sharedir, "rust", self.rust_path()) - install_dir = path.join(self.context.sharedir, "rust", self.rust_install_dir()) - version = self.rust_stable_version() if stable else "nightly" - - nightly_dist = STATIC_RUST_LANG_ORG_DIST + "/" + self.rust_nightly_date() - - if not force and path.exists(path.join(rust_dir, "rustc", "bin", "rustc" + BIN_SUFFIX)): - print("Rust compiler already downloaded.", end=" ") - print("Use |bootstrap-rust --force| to download again.") - else: - if path.isdir(rust_dir): - shutil.rmtree(rust_dir) - os.makedirs(rust_dir) - - # The nightly Rust compiler is hosted on the nightly server under the date with a name - # rustc-nightly-HOST-TRIPLE.tar.gz, whereas the stable compiler is named - # rustc-VERSION-HOST-TRIPLE.tar.gz. We just need to pull down and extract it, - # giving a directory name that will be the same as the tarball name (rustc is - # in that directory). - if stable: - base_url = STATIC_RUST_LANG_ORG_DIST - else: - base_url = nightly_dist - - rustc_url = base_url + "/rustc-%s-%s.tar.gz" % (version, host_triple()) - tgz_file = rust_dir + '-rustc.tar.gz' - download_file("Rust compiler", rustc_url, tgz_file) - - print("Extracting Rust compiler...") - extract(tgz_file, install_dir) - print("Rust compiler ready.") - - # Each Rust stdlib has a name of the form `rust-std-nightly-TRIPLE.tar.gz` for the nightly - # releases, or rust-std-VERSION-TRIPLE.tar.gz for stable releases, with - # a directory of the name `rust-std-TRIPLE` inside and then a `lib` directory. - # This `lib` directory needs to be extracted and merged with the `rustc/lib` - # directory from the host compiler above. - lib_dir = path.join(install_dir, - "rustc-%s-%s" % (version, host_triple()), - "rustc", "lib", "rustlib") - - # ensure that the libs for the host's target is downloaded - host_target = host_triple() - if host_target not in target: - target.append(host_target) - - for target_triple in target: - target_lib_dir = path.join(lib_dir, target_triple) - if path.exists(target_lib_dir): - # No need to check for force. If --force the directory is already deleted - print("Rust lib for target {} already downloaded.".format(target_triple), end=" ") - print("Use |bootstrap-rust --force| to download again.") - continue - - tarball = "rust-std-%s-%s.tar.gz" % (version, target_triple) - tgz_file = path.join(install_dir, tarball) - if self.use_stable_rust(): - std_url = STATIC_RUST_LANG_ORG_DIST + "/" + tarball - else: - std_url = nightly_dist + "/" + tarball - - download_file("Host rust library for target %s" % target_triple, std_url, tgz_file) - print("Extracting Rust stdlib for target %s..." % target_triple) - extract(tgz_file, install_dir) - shutil.copytree(path.join(install_dir, - "rust-std-%s-%s" % (version, target_triple), - "rust-std-%s" % target_triple, - "lib", "rustlib", target_triple), - path.join(install_dir, - "rustc-%s-%s" % (version, host_triple()), - "rustc", - "lib", "rustlib", target_triple)) - shutil.rmtree(path.join(install_dir, "rust-std-%s-%s" % (version, target_triple))) - - print("Rust {} libs ready.".format(target_triple)) - - @Command('bootstrap-rust-docs', - description='Download the Rust documentation', - category='bootstrap') - @CommandArgument('--force', '-f', - action='store_true', - help='Force download even if docs already exist') - def bootstrap_rustc_docs(self, force=False): - self.ensure_bootstrapped() - rust_root = self.config["tools"]["rust-root"] - docs_dir = path.join(rust_root, "doc") - if not force and path.exists(docs_dir): - print("Rust docs already downloaded.", end=" ") - print("Use |bootstrap-rust-docs --force| to download again.") - return - - if path.isdir(docs_dir): - shutil.rmtree(docs_dir) - docs_name = self.rust_path().replace("rustc-", "rust-docs-") - docs_url = "%s/%s/rust-docs-nightly-%s.tar.gz" % ( - STATIC_RUST_LANG_ORG_DIST, self.rust_nightly_date(), host_triple() - ) - tgz_file = path.join(rust_root, 'doc.tar.gz') - - download_file("Rust docs", docs_url, tgz_file) - - print("Extracting Rust docs...") - temp_dir = path.join(rust_root, "temp_docs") - if path.isdir(temp_dir): - shutil.rmtree(temp_dir) - extract(tgz_file, temp_dir) - shutil.move(path.join(temp_dir, docs_name.split("/")[1], - "rust-docs", "share", "doc", "rust", "html"), - docs_dir) - shutil.rmtree(temp_dir) - print("Rust docs ready.") - - @Command('bootstrap-cargo', - description='Download the Cargo build tool', - category='bootstrap') - @CommandArgument('--force', '-f', - action='store_true', - help='Force download even if cargo already exists') - def bootstrap_cargo(self, force=False): - cargo_dir = path.join(self.context.sharedir, "cargo", self.rust_nightly_date()) - if not force and path.exists(path.join(cargo_dir, "cargo", "bin", "cargo" + BIN_SUFFIX)): - print("Cargo already downloaded.", end=" ") - print("Use |bootstrap-cargo --force| to download again.") - return - - if path.isdir(cargo_dir): - shutil.rmtree(cargo_dir) - os.makedirs(cargo_dir) - - tgz_file = "cargo-nightly-%s.tar.gz" % host_triple() - nightly_url = "%s/%s/%s" % (STATIC_RUST_LANG_ORG_DIST, self.rust_nightly_date(), tgz_file) - - download_file("Cargo nightly", nightly_url, tgz_file) - - print("Extracting Cargo nightly...") - nightly_dir = path.join(cargo_dir, - path.basename(tgz_file).replace(".tar.gz", "")) - extract(tgz_file, cargo_dir, movedir=nightly_dir) - print("Cargo ready.") - @Command('update-hsts-preload', description='Download the HSTS preload list', category='bootstrap') @@ -282,51 +126,31 @@ def bootstrap_pub_suffix(self, force=False): default='1', help='Keep up to this many most recent nightlies') def clean_nightlies(self, force=False, keep=None): - rust_current_nightly = self.rust_nightly_date() - rust_current_stable = self.rust_stable_version() - print("Current Rust nightly version: {}".format(rust_current_nightly)) - print("Current Rust stable version: {}".format(rust_current_stable)) - to_keep = set() - if int(keep) == 1: - # Optimize keep=1 case to not invoke git - to_keep.add(rust_current_nightly) - to_keep.add(rust_current_stable) - else: - for version_file in ['rust-toolchain', 'rust-stable-version']: - cmd = subprocess.Popen( - ['git', 'log', '--oneline', '--no-color', '-n', keep, '--patch', version_file], - stdout=subprocess.PIPE, - universal_newlines=True - ) - stdout, _ = cmd.communicate() - for line in stdout.splitlines(): - if line.startswith(b"+") and not line.startswith(b"+++"): - line = line[len(b"+"):] - if line.startswith(b"nightly-"): - line = line[len(b"nightly-"):] - to_keep.add(line) + default_toolchain = self.default_toolchain() + geckolib_toolchain = self.geckolib_toolchain() + print("Current Rust version for Servo: {}".format(default_toolchain)) + print("Current Rust version for geckolib: {}".format(geckolib_toolchain)) + old_toolchains = [] + keep = int(keep) + for toolchain_file in ['rust-toolchain', 'geckolib-rust-toolchain']: + stdout = subprocess.check_output(['git', 'log', '--format=%H', toolchain_file]) + for i, commit_hash in enumerate(stdout.split(), 1): + if i > keep: + toolchain = subprocess.check_output( + ['git', 'show', '%s:%s' % (commit_hash, toolchain_file)]) + old_toolchains.append(toolchain.strip()) removing_anything = False - for tool in ["rust", "cargo"]: - base = path.join(self.context.sharedir, tool) - if not path.isdir(base): - continue - for name in os.listdir(base): - full_path = path.join(base, name) - if name.startswith("rust-"): - name = name[len("rust-"):] - if name.endswith("-alt"): - name = name[:-len("-alt")] - if name not in to_keep: + stdout = subprocess.check_output(['rustup', 'toolchain', 'list']) + for toolchain_with_host in stdout.split(): + for old in old_toolchains: + if toolchain_with_host.startswith(old): removing_anything = True if force: - print("Removing {}".format(full_path)) - try: - delete(full_path) - except OSError as e: - print("Removal failed with error {}".format(e)) + print("Removing {}".format(toolchain_with_host)) + check_call(["rustup", "uninstall", toolchain_with_host]) else: - print("Would remove {}".format(full_path)) + print("Would remove {}".format(toolchain_with_host)) if not removing_anything: print("Nothing to remove.") elif not force: diff --git a/python/servo/build_commands.py b/python/servo/build_commands.py index 28451aac2cc7..22e716a29a1a 100644 --- a/python/servo/build_commands.py +++ b/python/servo/build_commands.py @@ -233,6 +233,13 @@ def build(self, target=None, release=False, dev=False, jobs=None, target = self.config["android"]["target"] if target: + if self.config["tools"]["use-rustup"]: + # 'rustup target add' fails if the toolchain is not installed at all. + self.call_rustup_run(["rustc", "--version"]) + + check_call(["rustup" + BIN_SUFFIX, "target", "add", + "--toolchain", self.toolchain(), target]) + opts += ["--target", target] if not android: android = self.handle_android_target(target) @@ -340,10 +347,7 @@ def build(self, target=None, release=False, dev=False, jobs=None, os.makedirs(aar_out_dir) env["AAR_OUT_DIR"] = aar_out_dir - cargo_binary = "cargo" + BIN_SUFFIX - - status = call( - [cargo_binary, "build"] + opts, env=env, verbose=verbose) + status = self.call_rustup_run(["cargo", "build"] + opts, env=env, verbose=verbose) elapsed = time() - build_start # Do some additional things if the build succeeded @@ -430,9 +434,9 @@ def build_cef(self, jobs=None, verbose=False, release=False, # Unlike RUSTFLAGS, these are only passed in the final rustc invocation # so that `./mach build` followed by `./mach build-cef` both build # common dependencies with the same flags. - opts += ["--", "-C", "link-args=-Xlinker -undefined -Xlinker dynamic_lookup"] + opts += ["--", "-Clink-args=-Xlinker -undefined -Xlinker dynamic_lookup"] - ret = call(["cargo", "rustc"] + opts, env=env, verbose=verbose) + ret = self.call_rustup_run(["cargo", "rustc"] + opts, env=env, verbose=verbose) elapsed = time() - build_start # Generate Desktop Notification if elapsed-time > some threshold value @@ -455,7 +459,7 @@ def build_cef(self, jobs=None, verbose=False, release=False, action='store_true', help='Build in release mode') def build_geckolib(self, jobs=None, verbose=False, release=False): - self.set_use_stable_rust() + self.set_use_geckolib_toolchain() self.ensure_bootstrapped() self.ensure_clobbered() @@ -475,7 +479,7 @@ def build_geckolib(self, jobs=None, verbose=False, release=False): opts += ["--features", ' '.join(features)] build_start = time() - ret = call(["cargo", "build"] + opts, env=env, verbose=verbose) + ret = self.call_rustup_run(["cargo", "build"] + opts, env=env, verbose=verbose) elapsed = time() - build_start # Generate Desktop Notification if elapsed-time > some threshold value diff --git a/python/servo/command_base.py b/python/servo/command_base.py index 3ff2a6eea3b9..c1cab4a682cc 100644 --- a/python/servo/command_base.py +++ b/python/servo/command_base.py @@ -138,6 +138,18 @@ def call(*args, **kwargs): return subprocess.call(*args, shell=sys.platform == 'win32', **kwargs) +def check_output(*args, **kwargs): + """Wrap `subprocess.call`, printing the command if verbose=True.""" + verbose = kwargs.pop('verbose', False) + if verbose: + print(' '.join(args[0])) + if 'env' in kwargs: + kwargs['env'] = normalize_env(kwargs['env']) + # we have to use shell=True in order to get PATH handling + # when looking for the binary on Windows + return subprocess.check_output(*args, shell=sys.platform == 'win32', **kwargs) + + def check_call(*args, **kwargs): """Wrap `subprocess.check_call`, printing the command if verbose=True. @@ -254,10 +266,7 @@ def resolverelative(category, key): context.sharedir = self.config["tools"]["cache-dir"] - self.config["tools"].setdefault("system-rust", False) - self.config["tools"].setdefault("system-cargo", False) - self.config["tools"].setdefault("rust-root", "") - self.config["tools"].setdefault("cargo-root", "") + self.config["tools"].setdefault("use-rustup", True) self.config["tools"].setdefault("rustc-with-gold", get_env_bool("SERVO_RUSTC_WITH_GOLD", True)) self.config.setdefault("build", {}) @@ -276,63 +285,46 @@ def resolverelative(category, key): # Set default android target self.handle_android_target("armv7-linux-androideabi") - self.set_cargo_root() - self.set_use_stable_rust(False) - - _use_stable_rust = False - _rust_stable_version = None - _rust_nightly_date = None + self.set_use_geckolib_toolchain(False) - def set_cargo_root(self): - if not self.config["tools"]["system-cargo"]: - self.config["tools"]["cargo-root"] = path.join( - self.context.sharedir, "cargo", self.rust_nightly_date()) + _use_geckolib_toolchain = False + _geckolib_toolchain = None + _default_toolchain = None - def set_use_stable_rust(self, use_stable_rust=True): - self._use_stable_rust = use_stable_rust - if not self.config["tools"]["system-rust"]: - self.config["tools"]["rust-root"] = path.join( - self.context.sharedir, "rust", self.rust_path()) - if use_stable_rust: + def set_use_geckolib_toolchain(self, use_geckolib_toolchain=True): + self._use_geckolib_toolchain = use_geckolib_toolchain + if use_geckolib_toolchain: # Cargo maintainer's position is that CARGO_INCREMENTAL is a nightly-only feature # and should not be used on the stable channel. # https://github.com/rust-lang/cargo/issues/3835 self.config["build"]["incremental"] = False - def use_stable_rust(self): - return self._use_stable_rust - - def rust_install_dir(self): - if self._use_stable_rust: - return self.rust_stable_version() + def toolchain(self): + if self._use_geckolib_toolchain: + return self.geckolib_toolchain() else: - return self.rust_nightly_date() + return self.default_toolchain() - def rust_path(self): - if self._use_stable_rust: - version = self.rust_stable_version() - else: - version = "nightly" - - subdir = "rustc-%s-%s" % (version, host_triple()) - return os.path.join(self.rust_install_dir(), subdir) - - def rust_stable_version(self): - if self._rust_stable_version is None: - filename = path.join("rust-stable-version") + def geckolib_toolchain(self): + if self._geckolib_toolchain is None: + filename = path.join(self.context.topdir, "geckolib-rust-toolchain") with open(filename) as f: - self._rust_stable_version = f.read().strip() - return self._rust_stable_version + self._geckolib_toolchain = f.read().strip() + return self._geckolib_toolchain - def rust_nightly_date(self): - if self._rust_nightly_date is None: + def default_toolchain(self): + if self._default_toolchain is None: filename = path.join(self.context.topdir, "rust-toolchain") with open(filename) as f: - toolchain = f.read().strip() - prefix = "nightly-" - assert toolchain.startswith(prefix) - self._rust_nightly_date = toolchain[len(prefix):] - return self._rust_nightly_date + self._default_toolchain = f.read().strip() + return self._default_toolchain + + def call_rustup_run(self, args, **kwargs): + if self.config["tools"]["use-rustup"]: + args = ["rustup" + BIN_SUFFIX, "run", "--install", self.toolchain()] + args + else: + args[0] += BIN_SUFFIX + return call(args, **kwargs) def get_top_dir(self): return self.context.topdir @@ -423,29 +415,9 @@ def package_dir(package): # Always build harfbuzz from source env["HARFBUZZ_SYS_NO_PKG_CONFIG"] = "true" - if not self.config["tools"]["system-rust"] \ - or self.config["tools"]["rust-root"]: - env["RUST_ROOT"] = self.config["tools"]["rust-root"] - # These paths are for when rust-root points to an unpacked installer - extra_path += [path.join(self.config["tools"]["rust-root"], "rustc", "bin")] - extra_lib += [path.join(self.config["tools"]["rust-root"], "rustc", "lib")] - # These paths are for when rust-root points to a rustc sysroot - extra_path += [path.join(self.config["tools"]["rust-root"], "bin")] - extra_lib += [path.join(self.config["tools"]["rust-root"], "lib")] - - if not self.config["tools"]["system-cargo"] \ - or self.config["tools"]["cargo-root"]: - # This path is for when rust-root points to an unpacked installer - extra_path += [ - path.join(self.config["tools"]["cargo-root"], "cargo", "bin")] - # This path is for when rust-root points to a rustc sysroot - extra_path += [ - path.join(self.config["tools"]["cargo-root"], "bin")] - if extra_path: env["PATH"] = "%s%s%s" % (os.pathsep.join(extra_path), os.pathsep, env["PATH"]) - env["CARGO_HOME"] = self.config["tools"]["cargo-home-dir"] if self.config["build"]["incremental"]: env["CARGO_INCREMENTAL"] = "1" @@ -591,33 +563,10 @@ def ensure_bootstrapped(self, target=None): target_platform = target or host_triple() - rust_root = self.config["tools"]["rust-root"] - rustc_path = path.join( - rust_root, "rustc", "bin", "rustc" + BIN_SUFFIX - ) - rustc_binary_exists = path.exists(rustc_path) - - base_target_path = path.join(rust_root, "rustc", "lib", "rustlib") - - target_path = path.join(base_target_path, target_platform) - target_exists = path.exists(target_path) - # Always check if all needed MSVC dependencies are installed if "msvc" in target_platform: Registrar.dispatch("bootstrap", context=self.context) - if not (self.config['tools']['system-rust'] or (rustc_binary_exists and target_exists)): - print("Looking for rustc at %s" % (rustc_path)) - Registrar.dispatch("bootstrap-rust", context=self.context, target=filter(None, [target]), - stable=self._use_stable_rust) - - cargo_path = path.join(self.config["tools"]["cargo-root"], "cargo", "bin", - "cargo" + BIN_SUFFIX) - cargo_binary_exists = path.exists(cargo_path) - - if not self.config["tools"]["system-cargo"] and not cargo_binary_exists: - Registrar.dispatch("bootstrap-cargo", context=self.context) - self.context.bootstrapped = True def ensure_clobbered(self, target_dir=None): diff --git a/python/servo/devenv_commands.py b/python/servo/devenv_commands.py index 1abf575ab5f6..dadf399479af 100644 --- a/python/servo/devenv_commands.py +++ b/python/servo/devenv_commands.py @@ -21,7 +21,7 @@ Command, ) -from servo.command_base import CommandBase, cd, call +from servo.command_base import CommandBase, cd, call, BIN_SUFFIX from servo.build_commands import notify_build_done from servo.util import STATIC_RUST_LANG_ORG_DIST, URLOPEN_KWARGS @@ -43,16 +43,16 @@ def run_cargo(self, params, geckolib=False, check=False): # for c in $(cargo --list | tail -$(($(cargo --list | wc -l) - 1))); do # (cargo help $c 2>&1 | grep "\\--package" >/dev/null 2>&1) && echo $c # done - if params[0] and params[0] in [ + if params and params[0] in [ 'bench', 'build', 'check', 'clean', 'doc', 'fmt', 'pkgid', 'run', 'rustc', 'rustdoc', 'test', 'update', ]: params[1:1] = ['--package', 'geckoservo'] - self.set_use_stable_rust() + self.set_use_geckolib_toolchain() build_start = time() - status = call(['cargo'] + params, env=env) + status = self.call_rustup_run(["cargo"] + params, env=env) elapsed = time() - build_start notify_build_done(self.config, elapsed, status == 0) @@ -197,8 +197,7 @@ def update_cargo(self, params=None, package=None, all_packages=None, dry_run=Non self.ensure_bootstrapped() with cd(self.context.topdir): - call(["cargo", "update"] + params, - env=self.build_env()) + self.call_rustup_run(["cargo", "update"] + params, env=self.build_env()) @Command('rustc', description='Run the Rust compiler', @@ -211,8 +210,7 @@ def rustc(self, params): params = [] self.ensure_bootstrapped() - - return call(["rustc"] + params, env=self.build_env()) + return self.call_rustup_run(["rustc"] + params, env=self.build_env()) @Command('rustc-geckolib', description='Run the Rust compiler with the same compiler version and root crate as build-geckolib', @@ -224,17 +222,11 @@ def rustc_geckolib(self, params): if params is None: params = [] - self.set_use_stable_rust() + self.set_use_geckolib_toolchain() self.ensure_bootstrapped() env = self.build_env(geckolib=True) - return call(["rustc"] + params, env=env) - - @Command('rust-root', - description='Print the path to the root of the Rust compiler', - category='devenv') - def rust_root(self): - print(self.config["tools"]["rust-root"]) + return self.call_rustup_run(["rustc"] + params, env=env) @Command('grep', description='`git grep` for selected directories.', @@ -267,24 +259,17 @@ def grep(self, params): def rustup(self): url = STATIC_RUST_LANG_ORG_DIST + "/channel-rust-nightly-date.txt" nightly_date = urllib2.urlopen(url, **URLOPEN_KWARGS).read() + toolchain = "nightly-" + nightly_date filename = path.join(self.context.topdir, "rust-toolchain") with open(filename, "w") as f: - f.write("nightly-%s\n" % nightly_date) - - # Reset self.config["tools"]["rust-root"] and self.config["tools"]["cargo-root"] - self._rust_nightly_date = None - self.set_use_stable_rust(False) - self.set_cargo_root() - - self.fetch() + f.write(toolchain + "\n") + return call(["rustup" + BIN_SUFFIX, "install", toolchain]) @Command('fetch', description='Fetch Rust, Cargo and Cargo dependencies', category='devenv') def fetch(self): - # Fetch Rust and Cargo self.ensure_bootstrapped() - # Fetch Cargo dependencies with cd(self.context.topdir): - call(["cargo", "fetch"], env=self.build_env()) + return self.call_rustup_run(["cargo", "fetch"], env=self.build_env()) diff --git a/python/servo/post_build_commands.py b/python/servo/post_build_commands.py index 0f3c9e9b7dff..eab7eaf05185 100644 --- a/python/servo/post_build_commands.py +++ b/python/servo/post_build_commands.py @@ -14,8 +14,6 @@ import subprocess from shutil import copytree, rmtree, copy2 -from mach.registrar import Registrar - from mach.decorators import ( CommandArgument, CommandProvider, @@ -24,7 +22,7 @@ from servo.command_base import ( CommandBase, - call, check_call, + check_call, check_output, BIN_SUFFIX, is_linux, is_windows, is_macosx, set_osmesa_env, get_browserhtml_path, ) @@ -211,10 +209,14 @@ def rr_replay(self): 'params', nargs='...', help="Command-line arguments to be passed through to cargo doc") def doc(self, params): + env = os.environ.copy() + env["RUSTUP_TOOLCHAIN"] = self.toolchain() + rustc_path = check_output(["rustup" + BIN_SUFFIX, "which", "rustc"], env=env) + assert path.basename(path.dirname(rustc_path)) == "bin" + toolchain_path = path.dirname(path.dirname(rustc_path)) + rust_docs = path.join(toolchain_path, "share", "doc", "rust", "html") + self.ensure_bootstrapped() - if not path.exists(path.join(self.config["tools"]["rust-root"], "doc")): - Registrar.dispatch("bootstrap-rust-docs", context=self.context) - rust_docs = path.join(self.config["tools"]["rust-root"], "doc") docs = path.join(self.get_target_dir(), "doc") if not path.exists(docs): os.makedirs(docs) @@ -234,8 +236,10 @@ def doc(self, params): else: copy2(full_name, destination) - return call(["cargo", "doc"] + params, - env=self.build_env(), cwd=self.servo_crate()) + return self.call_rustup_run( + ["cargo", "doc", "--manifest-path", self.servo_manifest()] + params, + env=self.build_env() + ) @Command('browse-doc', description='Generate documentation and open it in a web browser', diff --git a/python/servo/testing_commands.py b/python/servo/testing_commands.py index 8a8c41597b93..03d567786f61 100644 --- a/python/servo/testing_commands.py +++ b/python/servo/testing_commands.py @@ -34,7 +34,7 @@ from servo.command_base import ( BuildNotFound, CommandBase, - call, cd, check_call, set_osmesa_env, + call, check_call, set_osmesa_env, ) from servo.util import host_triple @@ -265,7 +265,7 @@ def test_unit(self, test_name=None, package=None, bench=False, nocapture=False): features = self.servo_features() if len(packages) > 0: - args = ["cargo", "bench" if bench else "test"] + args = ["cargo", "bench" if bench else "test", "--manifest-path", self.servo_manifest()] for crate in packages: args += ["-p", "%s_tests" % crate] for crate in in_crate_packages: @@ -278,7 +278,7 @@ def test_unit(self, test_name=None, package=None, bench=False, nocapture=False): if nocapture: args += ["--", "--nocapture"] - err = call(args, env=env, cwd=self.servo_crate()) + err = self.call_rustup_run(args, env=env) if err is not 0: return err @@ -290,17 +290,19 @@ def test_unit(self, test_name=None, package=None, bench=False, nocapture=False): @CommandArgument('--release', default=False, action="store_true", help="Run with a release build of servo") def test_stylo(self, release=False, test_name=None): - self.set_use_stable_rust() + self.set_use_geckolib_toolchain() self.ensure_bootstrapped() env = self.build_env() env["RUST_BACKTRACE"] = "1" env["CARGO_TARGET_DIR"] = path.join(self.context.topdir, "target", "geckolib").encode("UTF-8") - args = (["cargo", "test", "-p", "stylo_tests"] + - (["--release"] if release else []) + (test_name or [])) - with cd(path.join("ports", "geckolib")): - return call(args, env=env) + args = ( + ["cargo", "test", "--manifest-path", self.geckolib_manifest(), "-p", "stylo_tests"] + + (["--release"] if release else []) + + (test_name or []) + ) + return self.call_rustup_run(args, env=env) @Command('test-content', description='Run the content tests', diff --git a/python/servo/util.py b/python/servo/util.py index 78158b840da9..66f2f11527c3 100644 --- a/python/servo/util.py +++ b/python/servo/util.py @@ -16,7 +16,6 @@ from socket import error as socket_error import StringIO import sys -import tarfile import zipfile import urllib2 import certifi @@ -148,10 +147,8 @@ def download_file(desc, src, dst): def extract(src, dst, movedir=None): - if src.endswith(".zip"): - zipfile.ZipFile(src).extractall(dst) - else: - tarfile.open(src).extractall(dst) + assert src.endswith(".zip") + zipfile.ZipFile(src).extractall(dst) if movedir: for f in os.listdir(movedir): diff --git a/servobuild.example b/servobuild.example index b7cdcc7ba7d9..98dd8edaf9ce 100644 --- a/servobuild.example +++ b/servobuild.example @@ -6,22 +6,11 @@ # Tool options [tools] -# Where Rust compiler and other downloads will be stored. Can be -# shared by multiple Servo repositories. Defaults to /.servo -cache-dir = "./.servo" - -# Where Cargo stores all of its clones Defaults to /.cargo -cargo-home-dir = "./.cargo" - -# If system-rust is true, will use rustc/rustdoc from the path, or if -# rust-root is specified, will make sure that rust-root is in the path -# when building. Similarly for Cargo. This takes care of PATH as well as -# [DY]LD_LIBRARY_PATH. -# rust-root and cargo-root default to / -system-rust = false -#rust-root = "/path/to/rust" -system-cargo = false -#cargo-root = "/path/to/cargo" +# If use-rustup is set to false, mach will run for example "cargo build" +# instead of "rustup run --install cargo build" +# It is then the user’s responsibility to ensure that cargo and especially rustc +# in $PATH are versions compatible with Servo. +use-rustup = true # If rustc-with-gold is true, will try to find and use gold linker with rustc. # Defaults to true From f2c398fd5c11362ae2918da7ee12a24e29e3cb6f Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Mon, 27 Nov 2017 18:41:07 +0100 Subject: [PATCH 03/10] Add rustup.rs instructions in README --- README.md | 34 +++++++++++++++++++++++++++++----- 1 file changed, 29 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 0fafbac6ed4e..3c8e16e3a846 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,32 @@ Visit the [Servo Project page](https://servo.org/) for news and guides. ## Setting up your environment +### Rustup.rs + +Building servo requires [rustup](https://rustup.rs/), version 1.8.0 or more recent. +If you have an older version, run `rustup self update`. + +To install on Windows, download and run [`rustup-init.exe`](https://win.rustup.rs/) +then follow the onscreen instructions. + +To install on other systems, run: + +```sh +curl https://sh.rustup.rs -sSf | sh +``` + +This will also download the current stable version of Rust, which Servo won’t use. +To skip that step, run instead: + +``` +curl https://sh.rustup.rs -sSf | sh -s -- --default-toolchain none +``` + +See also [Other installation methods]( +https://github.com/rust-lang-nursery/rustup.rs/#other-installation-methods) + +### Other dependencies + Please select your operating system: * [OS X](#os-x) * [Debian-based Linuxes](#on-debian-based-linuxes) @@ -152,11 +178,9 @@ Pre-installed Android tools are needed. See wiki for ## The Rust compiler -Servo's build system automatically downloads a Rust compiler to build itself. -This is normally a specific revision of Rust upstream, but sometimes has a -backported patch or two. -If you'd like to know which nightly build of Rust we use, see -[`rust-toolchain`](https://github.com/servo/servo/blob/master/rust-toolchain). +Servo's build system uses rustup.rs to automatically download a Rust compiler. +This is a specific version of Rust Nightly determined by the +[`rust-toolchain`](https://github.com/servo/servo/blob/master/rust-toolchain) file. ## Building From 2f941d8450494895426aa614a15f65e3147d4095 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Mon, 27 Nov 2017 18:51:56 +0100 Subject: [PATCH 04/10] Print a link to instructions if rustup is not found. --- python/servo/command_base.py | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/python/servo/command_base.py b/python/servo/command_base.py index c1cab4a682cc..c6f0aa0601cb 100644 --- a/python/servo/command_base.py +++ b/python/servo/command_base.py @@ -7,6 +7,7 @@ # option. This file may not be copied, modified, or distributed # except according to those terms. +from errno import ENOENT as NO_SUCH_FILE_OR_DIRECTORY from glob import glob import gzip import itertools @@ -322,9 +323,18 @@ def default_toolchain(self): def call_rustup_run(self, args, **kwargs): if self.config["tools"]["use-rustup"]: args = ["rustup" + BIN_SUFFIX, "run", "--install", self.toolchain()] + args + try: + return call(args, **kwargs) + except OSError as e: + if e.errno == NO_SUCH_FILE_OR_DIRECTORY: + print "It looks like rustup is not installed. See instructions at " \ + "https://github.com/servo/servo/#setting-up-your-environment" + print + return 1 + raise else: args[0] += BIN_SUFFIX - return call(args, **kwargs) + return call(args, **kwargs) def get_top_dir(self): return self.context.topdir From a3339f97c3313cfd57f5e673b88dd165215c0450 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Mon, 27 Nov 2017 23:18:54 +0100 Subject: [PATCH 05/10] Print a better error message when rustup is too old --- python/servo/command_base.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/python/servo/command_base.py b/python/servo/command_base.py index c6f0aa0601cb..29968e766ad4 100644 --- a/python/servo/command_base.py +++ b/python/servo/command_base.py @@ -14,6 +14,7 @@ import locale import os from os import path +import re import contextlib import subprocess from subprocess import PIPE @@ -322,6 +323,12 @@ def default_toolchain(self): def call_rustup_run(self, args, **kwargs): if self.config["tools"]["use-rustup"]: + version_line = subprocess.check_output(["rustup" + BIN_SUFFIX, "--version"]) + version = tuple(map(int, re.match("rustup (\d+)\.(\d+)\.(\d+)", version_line).groups())) + if version < (1, 8, 0): + print "rustup is at version %s.%s.%s, Servo requires 1.8.0 or more recent." % version + print "Try running 'rustup self update'." + return 1 args = ["rustup" + BIN_SUFFIX, "run", "--install", self.toolchain()] + args try: return call(args, **kwargs) From d0b3525474fe55a2d0449ee136e7fc6cf2c2856d Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Tue, 28 Nov 2017 17:31:54 +0100 Subject: [PATCH 06/10] Cache rustup toolchains on AppVeyor and Travis-CI --- .travis.yml | 3 ++- appveyor.yml | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 7e13c36e8bb6..0ada8a1408a0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -30,8 +30,9 @@ matrix: - bash etc/ci/lockfile_changed.sh cache: directories: - - .cargo - .servo + - $HOME/.cargo + - $HOME/.rustup - $HOME/.ccache before_cache: - ./mach clean-nightlies --keep 2 --force diff --git a/appveyor.yml b/appveyor.yml index 2028871b170e..b04d49d0af33 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -37,8 +37,9 @@ branches: - master cache: + - C:\Users\appveyor\.rustup -> rust-toolchain + - C:\Users\appveyor\.cargo -> rust-toolchain - .servo -> rust-toolchain - - .cargo -> rust-toolchain - .ccache install: From e0f8f09c0561be31cfb02c008f31fefe6fab48dc Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Tue, 28 Nov 2017 17:38:36 +0100 Subject: [PATCH 07/10] Fix "rustup is not installed" message --- python/servo/command_base.py | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/python/servo/command_base.py b/python/servo/command_base.py index 29968e766ad4..c7d6f51d1f9d 100644 --- a/python/servo/command_base.py +++ b/python/servo/command_base.py @@ -323,15 +323,8 @@ def default_toolchain(self): def call_rustup_run(self, args, **kwargs): if self.config["tools"]["use-rustup"]: - version_line = subprocess.check_output(["rustup" + BIN_SUFFIX, "--version"]) - version = tuple(map(int, re.match("rustup (\d+)\.(\d+)\.(\d+)", version_line).groups())) - if version < (1, 8, 0): - print "rustup is at version %s.%s.%s, Servo requires 1.8.0 or more recent." % version - print "Try running 'rustup self update'." - return 1 - args = ["rustup" + BIN_SUFFIX, "run", "--install", self.toolchain()] + args try: - return call(args, **kwargs) + version_line = subprocess.check_output(["rustup" + BIN_SUFFIX, "--version"]) except OSError as e: if e.errno == NO_SUCH_FILE_OR_DIRECTORY: print "It looks like rustup is not installed. See instructions at " \ @@ -339,9 +332,15 @@ def call_rustup_run(self, args, **kwargs): print return 1 raise + version = tuple(map(int, re.match("rustup (\d+)\.(\d+)\.(\d+)", version_line).groups())) + if version < (1, 8, 0): + print "rustup is at version %s.%s.%s, Servo requires 1.8.0 or more recent." % version + print "Try running 'rustup self update'." + return 1 + args = ["rustup" + BIN_SUFFIX, "run", "--install", self.toolchain()] + args else: args[0] += BIN_SUFFIX - return call(args, **kwargs) + return call(args, **kwargs) def get_top_dir(self): return self.context.topdir From 2618e4ed9d15d75efb21802dfbd0788127b63e11 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Tue, 12 Dec 2017 22:19:59 +0100 Subject: [PATCH 08/10] Use rustup "proxies" instead of `rustup run` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit To make sure we’re indeed running rustup’s proxy rather than some other `cargo` for example, run the `rustup` executable with a different `argv[0]`. --- appveyor.yml | 1 + python/servo/command_base.py | 25 ++++++++++++------------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index b04d49d0af33..184e347a16e8 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -46,6 +46,7 @@ install: - appveyor-retry appveyor DownloadFile https://win.rustup.rs/ -FileName rustup-init.exe - rustup-init.exe -y --default-host x86_64-pc-windows-msvc --default-toolchain none - set PATH=%PATH%;C:\Users\appveyor\.cargo\bin + - rustup -V - mach rustc --version - mach cargo --version diff --git a/python/servo/command_base.py b/python/servo/command_base.py index c7d6f51d1f9d..dd1f6fdc8859 100644 --- a/python/servo/command_base.py +++ b/python/servo/command_base.py @@ -14,7 +14,6 @@ import locale import os from os import path -import re import contextlib import subprocess from subprocess import PIPE @@ -137,7 +136,8 @@ def call(*args, **kwargs): kwargs['env'] = normalize_env(kwargs['env']) # we have to use shell=True in order to get PATH handling # when looking for the binary on Windows - return subprocess.call(*args, shell=sys.platform == 'win32', **kwargs) + kwargs.setdefault("shell", sys.platform == "win32") + return subprocess.call(*args, **kwargs) def check_output(*args, **kwargs): @@ -149,7 +149,8 @@ def check_output(*args, **kwargs): kwargs['env'] = normalize_env(kwargs['env']) # we have to use shell=True in order to get PATH handling # when looking for the binary on Windows - return subprocess.check_output(*args, shell=sys.platform == 'win32', **kwargs) + kwargs.setdefault("shell", sys.platform == "win32") + return subprocess.check_output(*args, **kwargs) def check_call(*args, **kwargs): @@ -165,7 +166,8 @@ def check_call(*args, **kwargs): print(' '.join(args[0])) # we have to use shell=True in order to get PATH handling # when looking for the binary on Windows - proc = subprocess.Popen(*args, shell=sys.platform == 'win32', **kwargs) + kwargs.setdefault("shell", sys.platform == "win32") + proc = subprocess.Popen(*args, **kwargs) status = None # Leave it to the subprocess to handle Ctrl+C. If it terminates as # a result of Ctrl+C, proc.wait() will return a status code, and, @@ -322,25 +324,22 @@ def default_toolchain(self): return self._default_toolchain def call_rustup_run(self, args, **kwargs): + args[0] += BIN_SUFFIX if self.config["tools"]["use-rustup"]: try: - version_line = subprocess.check_output(["rustup" + BIN_SUFFIX, "--version"]) + kwargs.setdefault("env", {})["RUSTUP_TOOLCHAIN"] = self.toolchain() + return call(args, executable="rustup" + BIN_SUFFIX, shell=False, **kwargs) except OSError as e: if e.errno == NO_SUCH_FILE_OR_DIRECTORY: + print repr(e) + print print "It looks like rustup is not installed. See instructions at " \ "https://github.com/servo/servo/#setting-up-your-environment" print return 1 raise - version = tuple(map(int, re.match("rustup (\d+)\.(\d+)\.(\d+)", version_line).groups())) - if version < (1, 8, 0): - print "rustup is at version %s.%s.%s, Servo requires 1.8.0 or more recent." % version - print "Try running 'rustup self update'." - return 1 - args = ["rustup" + BIN_SUFFIX, "run", "--install", self.toolchain()] + args else: - args[0] += BIN_SUFFIX - return call(args, **kwargs) + return call(args, **kwargs) def get_top_dir(self): return self.context.topdir From ded0bc93653dabd23c9fd4f2db17caa1074af841 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Tue, 19 Dec 2017 17:44:22 +0100 Subject: [PATCH 09/10] Revert "Use rustup "proxies" instead of `rustup run`" This reverts commit ad22368646290510149d33a0a41fc436ac4a0e96. --- python/servo/command_base.py | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/python/servo/command_base.py b/python/servo/command_base.py index dd1f6fdc8859..c7d6f51d1f9d 100644 --- a/python/servo/command_base.py +++ b/python/servo/command_base.py @@ -14,6 +14,7 @@ import locale import os from os import path +import re import contextlib import subprocess from subprocess import PIPE @@ -136,8 +137,7 @@ def call(*args, **kwargs): kwargs['env'] = normalize_env(kwargs['env']) # we have to use shell=True in order to get PATH handling # when looking for the binary on Windows - kwargs.setdefault("shell", sys.platform == "win32") - return subprocess.call(*args, **kwargs) + return subprocess.call(*args, shell=sys.platform == 'win32', **kwargs) def check_output(*args, **kwargs): @@ -149,8 +149,7 @@ def check_output(*args, **kwargs): kwargs['env'] = normalize_env(kwargs['env']) # we have to use shell=True in order to get PATH handling # when looking for the binary on Windows - kwargs.setdefault("shell", sys.platform == "win32") - return subprocess.check_output(*args, **kwargs) + return subprocess.check_output(*args, shell=sys.platform == 'win32', **kwargs) def check_call(*args, **kwargs): @@ -166,8 +165,7 @@ def check_call(*args, **kwargs): print(' '.join(args[0])) # we have to use shell=True in order to get PATH handling # when looking for the binary on Windows - kwargs.setdefault("shell", sys.platform == "win32") - proc = subprocess.Popen(*args, **kwargs) + proc = subprocess.Popen(*args, shell=sys.platform == 'win32', **kwargs) status = None # Leave it to the subprocess to handle Ctrl+C. If it terminates as # a result of Ctrl+C, proc.wait() will return a status code, and, @@ -324,22 +322,25 @@ def default_toolchain(self): return self._default_toolchain def call_rustup_run(self, args, **kwargs): - args[0] += BIN_SUFFIX if self.config["tools"]["use-rustup"]: try: - kwargs.setdefault("env", {})["RUSTUP_TOOLCHAIN"] = self.toolchain() - return call(args, executable="rustup" + BIN_SUFFIX, shell=False, **kwargs) + version_line = subprocess.check_output(["rustup" + BIN_SUFFIX, "--version"]) except OSError as e: if e.errno == NO_SUCH_FILE_OR_DIRECTORY: - print repr(e) - print print "It looks like rustup is not installed. See instructions at " \ "https://github.com/servo/servo/#setting-up-your-environment" print return 1 raise + version = tuple(map(int, re.match("rustup (\d+)\.(\d+)\.(\d+)", version_line).groups())) + if version < (1, 8, 0): + print "rustup is at version %s.%s.%s, Servo requires 1.8.0 or more recent." % version + print "Try running 'rustup self update'." + return 1 + args = ["rustup" + BIN_SUFFIX, "run", "--install", self.toolchain()] + args else: - return call(args, **kwargs) + args[0] += BIN_SUFFIX + return call(args, **kwargs) def get_top_dir(self): return self.context.topdir From 0681e682e999ed7ec7c7067ac1b788290544ceab Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Tue, 19 Dec 2017 18:05:10 +0100 Subject: [PATCH 10/10] rustup.rs: Use MSVC rather than GNU toolchains on Windows --- python/servo/command_base.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/python/servo/command_base.py b/python/servo/command_base.py index c7d6f51d1f9d..1f3d784ebc3a 100644 --- a/python/servo/command_base.py +++ b/python/servo/command_base.py @@ -14,6 +14,7 @@ import locale import os from os import path +import platform import re import contextlib import subprocess @@ -337,7 +338,10 @@ def call_rustup_run(self, args, **kwargs): print "rustup is at version %s.%s.%s, Servo requires 1.8.0 or more recent." % version print "Try running 'rustup self update'." return 1 - args = ["rustup" + BIN_SUFFIX, "run", "--install", self.toolchain()] + args + toolchain = self.toolchain() + if platform.system() == "Windows": + toolchain += "-x86_64-pc-windows-msvc" + args = ["rustup" + BIN_SUFFIX, "run", "--install", toolchain] + args else: args[0] += BIN_SUFFIX return call(args, **kwargs)