diff options
author | bors-servo <lbergstrom+bors@mozilla.com> | 2018-01-10 12:00:59 -0600 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-01-10 12:00:59 -0600 |
commit | 2be49ac80659f58f2a39910dd79a3f3b5da98945 (patch) | |
tree | 9757c361969297f3a5f796e664fe1bbe410c49d9 | |
parent | 2065fa6da23c304093b0fdbbf7c068e0b0c67366 (diff) | |
parent | 0681e682e999ed7ec7c7067ac1b788290544ceab (diff) | |
download | servo-2be49ac80659f58f2a39910dd79a3f3b5da98945.tar.gz servo-2be49ac80659f58f2a39910dd79a3f3b5da98945.zip |
Auto merge of #19395 - servo:rustup.rs, r=jdm
Use rustup.rs instead of custom bootstrap
Fixes #11361, closes #18874, fixes #19365.
<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/19395)
<!-- Reviewable:end -->
-rw-r--r-- | .travis.yml | 5 | ||||
-rw-r--r-- | README.md | 34 | ||||
-rw-r--r-- | appveyor.yml | 11 | ||||
-rwxr-xr-x | etc/rustdoc-with-private | 4 | ||||
-rw-r--r-- | geckolib-rust-toolchain (renamed from rust-stable-version) | 0 | ||||
-rw-r--r-- | python/servo/bootstrap_commands.py | 222 | ||||
-rw-r--r-- | python/servo/build_commands.py | 20 | ||||
-rw-r--r-- | python/servo/command_base.py | 158 | ||||
-rw-r--r-- | python/servo/devenv_commands.py | 39 | ||||
-rw-r--r-- | python/servo/post_build_commands.py | 20 | ||||
-rw-r--r-- | python/servo/testing_commands.py | 23 | ||||
-rw-r--r-- | python/servo/util.py | 7 | ||||
-rw-r--r-- | servobuild.example | 21 |
13 files changed, 189 insertions, 375 deletions
diff --git a/.travis.yml b/.travis.yml index 1354e724483..0ada8a1408a 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 @@ -28,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/README.md b/README.md index 0fafbac6ed4..3c8e16e3a84 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 diff --git a/appveyor.yml b/appveyor.yml index 84121380957..184e347a16e 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -37,10 +37,19 @@ branches: - master cache: + - C:\Users\appveyor\.rustup -> rust-toolchain + - C:\Users\appveyor\.cargo -> rust-toolchain - .servo -> rust-toolchain - - .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 + - rustup -V + - 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/etc/rustdoc-with-private b/etc/rustdoc-with-private new file mode 100755 index 00000000000..097c237c562 --- /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/rust-stable-version b/geckolib-rust-toolchain index 6245beecd39..6245beecd39 100644 --- a/rust-stable-version +++ b/geckolib-rust-toolchain diff --git a/python/servo/bootstrap_commands.py b/python/servo/bootstrap_commands.py index ba583735011..ccc971e5b57 100644 --- a/python/servo/bootstrap_commands.py +++ b/python/servo/bootstrap_commands.py @@ -14,7 +14,6 @@ import json import os import os.path as path import re -import shutil import subprocess import sys import urllib2 @@ -27,9 +26,8 @@ from mach.decorators import ( ) 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 @@ class MachCommands(CommandBase): 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 @@ class MachCommands(CommandBase): 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 28451aac2cc..22e716a29a1 100644 --- a/python/servo/build_commands.py +++ b/python/servo/build_commands.py @@ -233,6 +233,13 @@ class MachCommands(CommandBase): 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 @@ class MachCommands(CommandBase): 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 @@ class MachCommands(CommandBase): # 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 @@ class MachCommands(CommandBase): 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 @@ class MachCommands(CommandBase): 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 4b29b25daf6..1f3d784ebc3 100644 --- a/python/servo/command_base.py +++ b/python/servo/command_base.py @@ -7,12 +7,15 @@ # 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 import locale import os from os import path +import platform +import re import contextlib import subprocess from subprocess import PIPE @@ -138,6 +141,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 +269,7 @@ class CommandBase(object): 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 +288,63 @@ class CommandBase(object): # 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"]: + try: + 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 " \ + "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 + 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) def get_top_dir(self): return self.context.topdir @@ -388,7 +400,7 @@ class CommandBase(object): " --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: @@ -423,29 +435,9 @@ class CommandBase(object): # 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" @@ -486,7 +478,10 @@ class CommandBase(object): 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"] @@ -588,33 +583,10 @@ class CommandBase(object): 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 1abf575ab5f..dadf399479a 100644 --- a/python/servo/devenv_commands.py +++ b/python/servo/devenv_commands.py @@ -21,7 +21,7 @@ from mach.decorators import ( 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 @@ class MachCommands(CommandBase): # 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 @@ class MachCommands(CommandBase): 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 @@ class MachCommands(CommandBase): 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 @@ class MachCommands(CommandBase): 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 @@ class MachCommands(CommandBase): 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 0f3c9e9b7df..eab7eaf0518 100644 --- a/python/servo/post_build_commands.py +++ b/python/servo/post_build_commands.py @@ -14,8 +14,6 @@ import os.path as path import subprocess from shutil import copytree, rmtree, copy2 -from mach.registrar import Registrar - from mach.decorators import ( CommandArgument, CommandProvider, @@ -24,7 +22,7 @@ from mach.decorators import ( 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 @@ class PostBuildCommands(CommandBase): '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 @@ class PostBuildCommands(CommandBase): 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 de77c85c285..03d567786f6 100644 --- a/python/servo/testing_commands.py +++ b/python/servo/testing_commands.py @@ -34,7 +34,7 @@ from mach.decorators import ( 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 @@ -255,12 +255,9 @@ class MachCommands(CommandBase): 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. @@ -268,7 +265,7 @@ class MachCommands(CommandBase): 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: @@ -281,7 +278,7 @@ class MachCommands(CommandBase): 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 @@ -293,17 +290,19 @@ class MachCommands(CommandBase): @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 78158b840da..66f2f11527c 100644 --- a/python/servo/util.py +++ b/python/servo/util.py @@ -16,7 +16,6 @@ import shutil 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 b7cdcc7ba7d..98dd8edaf9c 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-repo>/.servo -cache-dir = "./.servo" - -# Where Cargo stores all of its clones Defaults to <servo-repo>/.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 <servo-repo>/ -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 <toolchain> 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 |