Auto merge of #9385 - larsbergstrom:win32, r=frewsxcv,pcwalton,jdm,ecoal95

Win32 support

r? @frewsxcv for python stuff
r? @pcwalton for the "remove usage of Gaol" stuff for Win32
r? anybody else for misc cargo.lock updates, etc.

This replaces #7878.

This works best with https://github.com/servo/mozjs/pull/71, too, to enable static linking, but can be run without (via some PATH hackery).

The instructions are here, and will be added to a .md file in the repo once the mozjs changes also land:
https://hackpad.com/Servo-on-Windows-C1LPcI2bP25

I'd like to get these changes landed because I've been rebasing them for months, they're otherwise quite stable, and don't affect our other platforms and targets.

<!-- Reviewable:start -->
[<img src="https://reviewable.io/review_button.png" height=40 alt="Review on Reviewable"/>](https://reviewable.io/reviews/servo/servo/9385)
<!-- Reviewable:end -->
This commit is contained in:
bors-servo 2016-01-23 07:27:27 +05:30
commit 525e77f64f
25 changed files with 431 additions and 288 deletions

View file

@ -92,7 +92,9 @@ def _activate_virtualenv(topdir):
if python is None:
sys.exit("Python is not installed. Please install it prior to running mach.")
activate_path = os.path.join(virtualenv_path, "bin", "activate_this.py")
# Virtualenv calls its scripts folder "bin" on linux/OSX but "Scripts" on Windows, detect which one then use that
script_dir = "Scripts" if os.name == "nt" else "bin"
activate_path = os.path.join(virtualenv_path, script_dir, "activate_this.py")
if not (os.path.exists(virtualenv_path) and os.path.exists(activate_path)):
virtualenv = _get_exec(*VIRTUALENV_NAMES)
if virtualenv is None:

View file

@ -28,7 +28,7 @@ from mach.decorators import (
Command,
)
from servo.command_base import CommandBase, cd, host_triple
from servo.command_base import CommandBase, cd, host_triple, check_call, BIN_SUFFIX
def download(desc, src, writer):
@ -111,7 +111,7 @@ class MachCommands(CommandBase):
def bootstrap_rustc(self, force=False):
rust_dir = path.join(
self.context.sharedir, "rust", self.rust_path())
if not force and path.exists(path.join(rust_dir, "rustc", "bin", "rustc")):
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.")
return
@ -203,7 +203,7 @@ class MachCommands(CommandBase):
def bootstrap_cargo(self, force=False):
cargo_dir = path.join(self.context.sharedir, "cargo",
self.cargo_build_id())
if not force and path.exists(path.join(cargo_dir, "bin", "cargo")):
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
@ -289,9 +289,9 @@ class MachCommands(CommandBase):
% module_path)
print("\nClean the submodule and try again.")
return 1
subprocess.check_call(
check_call(
["git", "submodule", "--quiet", "sync", "--recursive"])
subprocess.check_call(
check_call(
["git", "submodule", "update", "--init", "--recursive"])
@Command('clean-nightlies',

View file

@ -11,7 +11,6 @@ from __future__ import print_function, unicode_literals
import os
import os.path as path
import subprocess
import sys
import shutil
@ -23,7 +22,7 @@ from mach.decorators import (
Command,
)
from servo.command_base import CommandBase, cd
from servo.command_base import CommandBase, cd, call
def is_headless_build():
@ -123,14 +122,6 @@ def notify(title, text):
print("[Warning] Could not generate notification! %s" % extra, file=sys.stderr)
def call(*args, **kwargs):
"""Wrap `subprocess.call`, printing the command if verbose=True."""
verbose = kwargs.pop('verbose', False)
if verbose:
print(' '.join(args[0]))
return subprocess.call(*args, **kwargs)
@CommandProvider
class MachCommands(CommandBase):
@Command('build',

View file

@ -16,6 +16,8 @@ import toml
from mach.registrar import Registrar
BIN_SUFFIX = ".exe" if sys.platform == "win32" else ""
@contextlib.contextmanager
def cd(new_path):
@ -36,6 +38,8 @@ def host_triple():
os_type = "apple-darwin"
elif os_type == "android":
os_type = "linux-androideabi"
elif os_type.startswith("mingw64_nt-"):
os_type = "pc-windows-gnu"
else:
os_type = "unknown"
@ -52,6 +56,31 @@ def host_triple():
return "%s-%s" % (cpu_type, os_type)
def use_nightly_rust():
envvar = os.environ.get("SERVO_USE_NIGHTLY_RUST", "0")
return envvar != "0"
def call(*args, **kwargs):
"""Wrap `subprocess.call`, printing the command if verbose=True."""
verbose = kwargs.pop('verbose', False)
if verbose:
print(' '.join(args[0]))
# 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)
def check_call(*args, **kwargs):
"""Wrap `subprocess.check_call`, printing the command if verbose=True."""
verbose = kwargs.pop('verbose', False)
if verbose:
print(' '.join(args[0]))
# we have to use shell=True in order to get PATH handling
# when looking for the binary on Windows
return subprocess.check_call(*args, shell=sys.platform == 'win32', **kwargs)
class CommandBase(object):
"""Base class for mach command providers.
@ -187,6 +216,14 @@ class CommandBase(object):
def build_env(self, gonk=False, hosts_file_path=None):
"""Return an extended environment dictionary."""
env = os.environ.copy()
if sys.platform == "win32" and type(env['PATH']) == unicode:
# On win32, the virtualenv's activate_this.py script sometimes ends up
# turning os.environ['PATH'] into a unicode string. This doesn't work
# for passing env vars in to a process, so we force it back to ascii.
# We don't use UTF8 since that won't be correct anyway; if you actually
# have unicode stuff in your path, all this PATH munging would have broken
# it in any case.
env['PATH'] = env['PATH'].encode('ascii', 'ignore')
extra_path = []
extra_lib = []
if not self.config["tools"]["system-rust"] \
@ -333,13 +370,13 @@ class CommandBase(object):
if not self.config["tools"]["system-rust"] and \
not path.exists(path.join(
self.config["tools"]["rust-root"], "rustc", "bin", "rustc")):
self.config["tools"]["rust-root"], "rustc", "bin", "rustc" + BIN_SUFFIX)):
print("looking for rustc at %s" % path.join(
self.config["tools"]["rust-root"], "rustc", "bin", "rustc"))
self.config["tools"]["rust-root"], "rustc", "bin", "rustc" + BIN_SUFFIX))
Registrar.dispatch("bootstrap-rust", context=self.context)
if not self.config["tools"]["system-cargo"] and \
not path.exists(path.join(
self.config["tools"]["cargo-root"], "cargo", "bin", "cargo")):
self.config["tools"]["cargo-root"], "cargo", "bin", "cargo" + BIN_SUFFIX)):
Registrar.dispatch("bootstrap-cargo", context=self.context)
self.context.bootstrapped = True

View file

@ -19,7 +19,7 @@ from mach.decorators import (
Command,
)
from servo.command_base import CommandBase, cd
from servo.command_base import CommandBase, cd, call
@CommandProvider
@ -36,10 +36,8 @@ class MachCommands(CommandBase):
if self.context.topdir == getcwd():
with cd(path.join('components', 'servo')):
return subprocess.call(
["cargo"] + params, env=self.build_env())
return subprocess.call(['cargo'] + params,
env=self.build_env())
return call(["cargo"] + params, env=self.build_env())
return call(['cargo'] + params, env=self.build_env())
@Command('cargo-update',
description='Same as update-cargo',
@ -89,8 +87,8 @@ class MachCommands(CommandBase):
for cargo_path in cargo_paths:
with cd(cargo_path):
print(cargo_path)
subprocess.call(["cargo", "update"] + params,
env=self.build_env())
call(["cargo", "update"] + params,
env=self.build_env())
@Command('clippy',
description='Run Clippy',
@ -111,7 +109,7 @@ class MachCommands(CommandBase):
def rustc(self, params):
if params is None:
params = []
return subprocess.call(["rustc"] + params, env=self.build_env())
return call(["rustc"] + params, env=self.build_env())
@Command('rust-root',
description='Print the path to the root of the Rust compiler',
@ -140,7 +138,7 @@ class MachCommands(CommandBase):
root_dirs_abs = [path.join(self.context.topdir, s) for s in root_dirs]
# Absolute paths for all directories to be considered
grep_paths = root_dirs_abs + tests_dirs_abs
return subprocess.call(
return call(
["git"] + ["grep"] + params + ['--'] + grep_paths + [':(exclude)*.min.js'],
env=self.build_env())
@ -149,14 +147,14 @@ class MachCommands(CommandBase):
category='devenv')
def upgrade_wpt_runner(self):
with cd(path.join(self.context.topdir, 'tests', 'wpt', 'harness')):
code = subprocess.call(["git", "init"], env=self.build_env())
code = call(["git", "init"], env=self.build_env())
if code:
return code
subprocess.call(
call(
["git", "remote", "add", "upstream", "https://github.com/w3c/wptrunner.git"], env=self.build_env())
code = subprocess.call(["git", "fetch", "upstream"], env=self.build_env())
code = call(["git", "fetch", "upstream"], env=self.build_env())
if code:
return code
code = subprocess.call(["git", "reset", '--', "hard", "remotes/upstream/master"], env=self.build_env())
code = call(["git", "reset", '--', "hard", "remotes/upstream/master"], env=self.build_env())
if code:
return code

View file

@ -22,7 +22,7 @@ from mach.decorators import (
Command,
)
from servo.command_base import CommandBase, cd
from servo.command_base import CommandBase, cd, call, check_call
def read_file(filename, if_exists=False):
@ -114,7 +114,7 @@ class PostBuildCommands(CommandBase):
args = args + params
try:
subprocess.check_call(args, env=env)
check_call(args, env=env)
except subprocess.CalledProcessError as e:
print("Servo exited with return value %d" % e.returncode)
return e.returncode
@ -142,7 +142,7 @@ class PostBuildCommands(CommandBase):
servo_cmd = [self.get_binary_path(release, dev)] + params
rr_cmd = ['rr', '--fatal-errors', 'record']
try:
subprocess.check_call(rr_cmd + servo_cmd)
check_call(rr_cmd + servo_cmd)
except OSError as e:
if e.errno == 2:
print("rr binary can't be found!")
@ -154,7 +154,7 @@ class PostBuildCommands(CommandBase):
category='post-build')
def rr_replay(self):
try:
subprocess.check_call(['rr', '--fatal-errors', 'replay'])
check_call(['rr', '--fatal-errors', 'replay'])
except OSError as e:
if e.errno == 2:
print("rr binary can't be found!")
@ -191,8 +191,8 @@ class PostBuildCommands(CommandBase):
else:
copy2(full_name, destination)
return subprocess.call(["cargo", "doc"] + params,
env=self.build_env(), cwd=self.servo_crate())
return call(["cargo", "doc"] + params,
env=self.build_env(), cwd=self.servo_crate())
@Command('browse-doc',
description='Generate documentation and open it in a web browser',

View file

@ -26,7 +26,7 @@ from mach.decorators import (
Command,
)
from servo.command_base import CommandBase
from servo.command_base import CommandBase, call, check_call
from wptrunner import wptcommandline
from update import updatecommandline
import tidy
@ -78,7 +78,7 @@ class MachCommands(CommandBase):
def run_test(self, prefix, args=[], release=False):
t = self.find_test(prefix, release=release)
if t:
return subprocess.call([t] + args, env=self.build_env())
return call([t] + args, env=self.build_env())
@Command('test',
description='Run all Servo tests',
@ -203,7 +203,7 @@ class MachCommands(CommandBase):
for crate in packages:
args += ["-p", "%s_tests" % crate]
args += test_patterns
result = subprocess.call(args, env=self.build_env(), cwd=self.servo_crate())
result = call(args, env=self.build_env(), cwd=self.servo_crate())
if result != 0:
return result
@ -237,7 +237,7 @@ class MachCommands(CommandBase):
category='testing')
def test_wpt_failure(self):
self.ensure_bootstrapped()
return not subprocess.call([
return not call([
"bash",
path.join("tests", "wpt", "run.sh"),
"--no-pause-after-test",
@ -395,17 +395,17 @@ class MachCommands(CommandBase):
# Clone the jQuery repository if it doesn't exist
if not os.path.isdir(jquery_dir):
subprocess.check_call(
check_call(
["git", "clone", "-b", "servo", "--depth", "1", "https://github.com/servo/jquery", jquery_dir])
# Run pull in case the jQuery repo was updated since last test run
subprocess.check_call(
check_call(
["git", "-C", jquery_dir, "pull"])
# Check that a release servo build exists
bin_path = path.abspath(self.get_binary_path(release, dev))
return subprocess.check_call(
return check_call(
[run_file, cmd, bin_path, base_dir])
def dromaeo_test_runner(self, tests, release, dev):
@ -416,21 +416,21 @@ class MachCommands(CommandBase):
# Clone the Dromaeo repository if it doesn't exist
if not os.path.isdir(dromaeo_dir):
subprocess.check_call(
check_call(
["git", "clone", "-b", "servo", "--depth", "1", "https://github.com/notriddle/dromaeo", dromaeo_dir])
# Run pull in case the Dromaeo repo was updated since last test run
subprocess.check_call(
check_call(
["git", "-C", dromaeo_dir, "pull"])
# Compile test suite
subprocess.check_call(
check_call(
["make", "-C", dromaeo_dir, "web"])
# Check that a release servo build exists
bin_path = path.abspath(self.get_binary_path(release, dev))
return subprocess.check_call(
return check_call(
[run_file, "|".join(tests), bin_path, base_dir])