diff options
author | Martin Robinson <mrobinson@igalia.com> | 2023-05-19 14:07:46 +0200 |
---|---|---|
committer | Martin Robinson <mrobinson@igalia.com> | 2023-05-25 08:22:21 +0200 |
commit | 7d20f16d9f746399811b1c4582e83efde1416bff (patch) | |
tree | f9aed7799918e930e43ab7ed834afdea9623b0d2 /python/servo/platform/windows.py | |
parent | a56abe44e02ddf3e634fd1a3953cd0cffc22d460 (diff) | |
download | servo-7d20f16d9f746399811b1c4582e83efde1416bff.tar.gz servo-7d20f16d9f746399811b1c4582e83efde1416bff.zip |
Implement `bootstrap-gstreamer` for all platforms
This change makes it so that the Platform classes can now handle
installing GStreamer dependencies and properly setting up the
environment including when cross-compiling. For Windows and Linux
is now installed into `target/dependencies/gstreamer` when not installed
system-wide. In addition:
1. Creating and moving existing environment path append helpers to
`util.py`.
2. Combining the `set_run_env` and `build_dev` functions and moving
some outside code into them so that it can be shared. Now code that
used to call `set_run_env` calls `build_dev` and then
`os.environ.update(...)`.
3. Adding Python typing information in many places.
Signed-off-by: Martin Robinson <mrobinson@igalia.com>
Diffstat (limited to 'python/servo/platform/windows.py')
-rw-r--r-- | python/servo/platform/windows.py | 97 |
1 files changed, 87 insertions, 10 deletions
diff --git a/python/servo/platform/windows.py b/python/servo/platform/windows.py index cea8de5a5dd..8ea2a0a5650 100644 --- a/python/servo/platform/windows.py +++ b/python/servo/platform/windows.py @@ -10,14 +10,15 @@ 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 -from ..util import extract, download_file DEPS_URL = "https://github.com/servo/servo-build-deps/releases/download/msvc-deps/" DEPENDENCIES = { @@ -31,10 +32,22 @@ DEPENDENCIES = { "openxr-loader-uwp": "1.0", } +URL_BASE = "https://gstreamer.freedesktop.org/data/pkg/windows/1.16.0/" +GSTREAMER_URL = f"{URL_BASE}/gstreamer-1.0-msvc-x86_64-1.16.0.msi" +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") + class Windows(Base): - def __init__(self): - pass + def __init__(self, triple: str): + super().__init__(triple) + self.is_windows = True + + def executable_suffix(self): + return ".exe" + + def library_path_variable_name(self): + return "LIB" @staticmethod def cmake_already_installed(required_version: str) -> bool: @@ -51,11 +64,11 @@ class Windows(Base): def prepare_file(cls, deps_dir: str, zip_path: str, full_spec: str): if not os.path.isfile(zip_path): zip_url = "{}{}.zip".format(DEPS_URL, urllib.parse.quote(full_spec)) - download_file(full_spec, zip_url, zip_path) + util.download_file(full_spec, zip_url, zip_path) - print("Extracting {}...".format(full_spec), end='') + print("Extracting {}...".format(full_spec), end="") try: - extract(zip_path, deps_dir) + util.extract(zip_path, deps_dir) except zipfile.BadZipfile: print("\nError: %s.zip is not a valid zip file, redownload..." % full_spec) os.remove(zip_path) @@ -70,7 +83,7 @@ class Windows(Base): return os.path.join(deps_dir, package, version) to_install = {} - for (package, version) in DEPENDENCIES.items(): + 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 @@ -82,8 +95,8 @@ class Windows(Base): return False print("Installing missing MSVC dependencies...") - for (package, version) in to_install.items(): - full_spec = '{}-{}'.format(package, version) + for package, version in to_install.items(): + full_spec = "{}-{}".format(package, version) package_dir = get_package_dir(package, version) parent_dir = os.path.dirname(package_dir) @@ -96,3 +109,67 @@ class Windows(Base): os.rename(extracted_path, package_dir) return True + + def gstreamer_root(self, cross_compilation_target: Optional[str]) -> Optional[str]: + build_target_triple = cross_compilation_target or self.triple + gst_arch_names = { + "x86_64": "X86_64", + "x86": "X86", + "aarch64": "ARM64", + } + gst_arch_name = gst_arch_names[build_target_triple.split("-")[0]] + + # The bootstraped version of GStreamer always takes precedance of the installed vesion. + prepackaged_root = os.path.join( + DEPENDENCIES_DIR, "gstreamer", "1.0", gst_arch_name + ) + if os.path.exists(os.path.join(prepackaged_root, "bin", "ffi-7.dll")): + return prepackaged_root + + # The installed version of GStreamer often sets an environment variable pointing to + # the install location. + root_from_env = os.environ.get(f"GSTREAMER_1_0_ROOT_{gst_arch_name}") + if root_from_env: + return root_from_env + + # If all else fails, look for an installation in the default install directory. + default_root = os.path.join("C:\\gstreamer\\1.0", gst_arch_name) + if os.path.exists(os.path.join(default_root, "bin", "ffi-7.dll")): + return default_root + + return None + + def is_gstreamer_installed(self, cross_compilation_target: Optional[str]) -> bool: + return self.gstreamer_root(cross_compilation_target) is not None + + def _platform_bootstrap_gstreamer(self, force: bool) -> bool: + if not force and self.is_gstreamer_installed(cross_compilation_target=None): + return False + + if "x86_64" not in self.triple: + print("Bootstrapping gstreamer not supported on " + "non-x86-64 Windows. Please install manually") + return False + + with tempfile.TemporaryDirectory() as temp_dir: + libs_msi = os.path.join(temp_dir, GSTREAMER_URL.rsplit("/", maxsplit=1)[-1]) + devel_msi = os.path.join( + temp_dir, GSTREAMER_DEVEL_URL.rsplit("/", maxsplit=1)[-1] + ) + + util.download_file("GStreamer libraries", GSTREAMER_URL, libs_msi) + util.download_file( + "GStreamer development support", GSTREAMER_DEVEL_URL, devel_msi + ) + + print(f"Installing GStreamer packages to {DEPENDENCIES_DIR}...") + os.makedirs(DEPENDENCIES_DIR, exist_ok=True) + common_args = [ + f"TARGETDIR={DEPENDENCIES_DIR}", # Install destination + "/qn", # Quiet mode + ] + subprocess.check_call(["msiexec", "/a", libs_msi] + common_args) + subprocess.check_call(["msiexec", "/a", devel_msi] + common_args) + + assert self.is_gstreamer_installed(cross_compilation_target=None) + return True |