aboutsummaryrefslogtreecommitdiffstats
path: root/python/servo/platform/windows.py
diff options
context:
space:
mode:
authorMartin Robinson <mrobinson@igalia.com>2023-05-19 14:07:46 +0200
committerMartin Robinson <mrobinson@igalia.com>2023-05-25 08:22:21 +0200
commit7d20f16d9f746399811b1c4582e83efde1416bff (patch)
treef9aed7799918e930e43ab7ed834afdea9623b0d2 /python/servo/platform/windows.py
parenta56abe44e02ddf3e634fd1a3953cd0cffc22d460 (diff)
downloadservo-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.py97
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