aboutsummaryrefslogtreecommitdiffstats
path: root/python/servo/platform
diff options
context:
space:
mode:
authorMartin Robinson <mrobinson@webkit.org>2023-06-23 11:07:18 +0200
committerMartin Robinson <mrobinson@igalia.com>2023-07-03 21:40:24 +0200
commit633d9b0eb964b09bf4dbb46d81a965a4be2fe8f5 (patch)
tree9b1eed6c332aaff352d9e6c52a9fe2c081129b69 /python/servo/platform
parent35ab3116358a50a0ffa549bbe90ce8d2cc755ddb (diff)
downloadservo-633d9b0eb964b09bf4dbb46d81a965a4be2fe8f5.tar.gz
servo-633d9b0eb964b09bf4dbb46d81a965a4be2fe8f5.zip
Windows bootstrap support
Diffstat (limited to 'python/servo/platform')
-rw-r--r--python/servo/platform/base.py14
-rw-r--r--python/servo/platform/linux.py2
-rw-r--r--python/servo/platform/macos.py2
-rw-r--r--python/servo/platform/windows.py88
4 files changed, 56 insertions, 50 deletions
diff --git a/python/servo/platform/base.py b/python/servo/platform/base.py
index b0ac64386bd..65731ba0364 100644
--- a/python/servo/platform/base.py
+++ b/python/servo/platform/base.py
@@ -75,7 +75,7 @@ class Base:
def executable_suffix(self):
return ""
- def _platform_bootstrap(self, _cache_dir: str, _force: bool) -> bool:
+ def _platform_bootstrap(self, _force: bool) -> bool:
raise NotImplementedError("Bootstrap installation detection not yet available.")
def _platform_bootstrap_gstreamer(self, _force: bool) -> bool:
@@ -97,11 +97,17 @@ class Base:
== 0
)
- def bootstrap(self, cache_dir: str, force: bool):
- if not self._platform_bootstrap(cache_dir, force):
+ def bootstrap(self, force: bool):
+ if not self._platform_bootstrap(force):
print("Dependencies were already installed!")
- def bootstrap_gstreamer(self, _cache_dir: str, force: bool):
+ def passive_bootstrap(self) -> bool:
+ """A bootstrap method that is called without explicitly invoking `./mach bootstrap`
+ but that is executed in the process of other `./mach` commands. This should be
+ as fast as possible."""
+ return False
+
+ def bootstrap_gstreamer(self, force: bool):
if not self._platform_bootstrap_gstreamer(force):
root = self.gstreamer_root(None)
if root:
diff --git a/python/servo/platform/linux.py b/python/servo/platform/linux.py
index 2e3a7d2a5c7..516b7448686 100644
--- a/python/servo/platform/linux.py
+++ b/python/servo/platform/linux.py
@@ -94,7 +94,7 @@ class Linux(Base):
return (distrib, version)
- def _platform_bootstrap(self, _cache_dir: str, force: bool) -> bool:
+ def _platform_bootstrap(self, force: bool) -> bool:
if self.distro.lower() == 'nixos':
print('NixOS does not need bootstrap, it will automatically enter a nix-shell')
print('Just run ./mach build')
diff --git a/python/servo/platform/macos.py b/python/servo/platform/macos.py
index 38169e9a75a..00f9ad185ed 100644
--- a/python/servo/platform/macos.py
+++ b/python/servo/platform/macos.py
@@ -54,7 +54,7 @@ class MacOS(Base):
return False
return True
- def _platform_bootstrap(self, _cache_dir: str, force: bool) -> bool:
+ def _platform_bootstrap(self, _force: bool) -> bool:
installed_something = False
try:
brewfile = os.path.join(util.SERVO_ROOT, "etc", "homebrew", "Brewfile")
diff --git a/python/servo/platform/windows.py b/python/servo/platform/windows.py
index 8ea2a0a5650..c687d0abf4e 100644
--- a/python/servo/platform/windows.py
+++ b/python/servo/platform/windows.py
@@ -8,25 +8,19 @@
# except according to those terms.
import os
-import shutil
import subprocess
import tempfile
from typing import Optional
import urllib
import zipfile
-from distutils.version import LooseVersion
-import six
from .. import util
from .base import Base
DEPS_URL = "https://github.com/servo/servo-build-deps/releases/download/msvc-deps/"
DEPENDENCIES = {
- "cmake": "3.14.3",
"llvm": "15.0.5",
"moztools": "3.2",
- "ninja": "1.7.1",
- "nuget": "08-08-2019",
"openssl": "111.3.0+1.1.1c-vs2017-2019-09-18",
"gstreamer-uwp": "1.16.0.5",
"openxr-loader-uwp": "1.0",
@@ -38,6 +32,11 @@ GSTREAMER_DEVEL_URL = f"{URL_BASE}/gstreamer-1.0-devel-msvc-x86_64-1.16.0.msi"
DEPENDENCIES_DIR = os.path.join(util.get_target_dir(), "dependencies")
+def get_dependency_dir(package):
+ """Get the directory that a given Windows dependency should extract to."""
+ return os.path.join(DEPENDENCIES_DIR, package, DEPENDENCIES[package])
+
+
class Windows(Base):
def __init__(self, triple: str):
super().__init__(triple)
@@ -49,64 +48,65 @@ class Windows(Base):
def library_path_variable_name(self):
return "LIB"
- @staticmethod
- def cmake_already_installed(required_version: str) -> bool:
- cmake_path = shutil.which("cmake")
- if not cmake_path:
- return False
-
- output = subprocess.check_output([cmake_path, "--version"])
- cmake_version_output = six.ensure_str(output).splitlines()[0]
- installed_version = cmake_version_output.replace("cmake version ", "")
- return LooseVersion(installed_version) >= LooseVersion(required_version)
-
@classmethod
- def prepare_file(cls, deps_dir: str, zip_path: str, full_spec: str):
+ def download_and_extract_dependency(cls, zip_path: str, full_spec: str):
if not os.path.isfile(zip_path):
- zip_url = "{}{}.zip".format(DEPS_URL, urllib.parse.quote(full_spec))
+ zip_url = f"{DEPS_URL}{urllib.parse.quote(full_spec)}.zip"
util.download_file(full_spec, zip_url, zip_path)
- print("Extracting {}...".format(full_spec), end="")
+ zip_dir = os.path.dirname(zip_path)
+ print(f"Extracting {full_spec} to {zip_dir}...", end="")
try:
- util.extract(zip_path, deps_dir)
+ util.extract(zip_path, zip_dir)
except zipfile.BadZipfile:
- print("\nError: %s.zip is not a valid zip file, redownload..." % full_spec)
+ print(f"\nError: {full_spec}.zip is not a valid zip file, redownload...")
os.remove(zip_path)
- cls.prepare_file(deps_dir, zip_path, full_spec)
+ cls.download_and_extract_dependency(zip_path, full_spec)
else:
print("done")
- def _platform_bootstrap(self, cache_dir: str, _force: bool = False) -> bool:
- deps_dir = os.path.join(cache_dir, "msvc-dependencies")
-
- def get_package_dir(package, version) -> str:
- return os.path.join(deps_dir, package, version)
-
- to_install = {}
- for package, version in DEPENDENCIES.items():
- # Don't install CMake if it already exists in PATH
- if package == "cmake" and self.cmake_already_installed(version):
- continue
-
- if not os.path.isdir(get_package_dir(package, version)):
- to_install[package] = version
+ def _platform_bootstrap(self, force: bool = False) -> bool:
+ installed_something = self.passive_bootstrap()
+ try:
+ choco_config = os.path.join(util.SERVO_ROOT, "support", "windows", "chocolatey.config")
+
+ # This is the format that PowerShell wants arguments passed to it.
+ cmd_exe_args = f"'/K','choco','install','-y','{choco_config}'"
+ if force:
+ cmd_exe_args += ",'-f'"
+
+ print(cmd_exe_args)
+ subprocess.check_output([
+ "powershell", "Start-Process", "-Wait", "-verb", "runAs",
+ "cmd.exe", "-ArgumentList", f"@({cmd_exe_args})"
+ ]).decode("utf-8")
+ except subprocess.CalledProcessError as e:
+ print("Could not run chocolatey. Follow manual build setup instructions.")
+ raise e
+
+ return installed_something
+
+ def passive_bootstrap(self) -> bool:
+ """A bootstrap method that is called without explicitly invoking `./mach bootstrap`
+ but that is executed in the process of other `./mach` commands. This should be
+ as fast as possible."""
+ to_install = [package for package in DEPENDENCIES if
+ not os.path.isdir(get_dependency_dir(package))]
if not to_install:
return False
print("Installing missing MSVC dependencies...")
- for package, version in to_install.items():
- full_spec = "{}-{}".format(package, version)
+ for package in to_install:
+ full_spec = "{}-{}".format(package, DEPENDENCIES[package])
- package_dir = get_package_dir(package, version)
+ package_dir = get_dependency_dir(package)
parent_dir = os.path.dirname(package_dir)
if not os.path.isdir(parent_dir):
os.makedirs(parent_dir)
- self.prepare_file(deps_dir, package_dir + ".zip", full_spec)
-
- extracted_path = os.path.join(deps_dir, full_spec)
- os.rename(extracted_path, package_dir)
+ self.download_and_extract_dependency(package_dir + ".zip", full_spec)
+ os.rename(os.path.join(parent_dir, full_spec), package_dir)
return True