Fix the build on Ubuntu 20.04 (#31019)

Ubuntu 20.04 doesn't have a new enough version of GStreamer, so
automatically disable media when running on that platform.

This also cleans up the media detection a bit, putting the result in a
`enable-media` variable and moving some of the logic into the build
scripts themselves rather than the platform module.
This commit is contained in:
Martin Robinson 2024-01-07 22:25:22 +01:00 committed by GitHub
parent d0ce48db06
commit 79a0f76d26
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 38 additions and 45 deletions

View file

@ -58,7 +58,6 @@ class MachCommands(CommandBase):
def build(self, build_type: BuildType, jobs=None, params=None, no_package=False, def build(self, build_type: BuildType, jobs=None, params=None, no_package=False,
verbose=False, very_verbose=False, libsimpleservo=False, **kwargs): verbose=False, very_verbose=False, libsimpleservo=False, **kwargs):
opts = params or [] opts = params or []
has_media_stack = "media-gstreamer" in self.features
if build_type.is_release(): if build_type.is_release():
opts += ["--release"] opts += ["--release"]
@ -74,7 +73,7 @@ class MachCommands(CommandBase):
if very_verbose: if very_verbose:
opts += ["-vv"] opts += ["-vv"]
env = self.build_env(is_build=True) env = self.build_env()
self.ensure_bootstrapped() self.ensure_bootstrapped()
self.ensure_clobbered() self.ensure_clobbered()
@ -173,7 +172,7 @@ class MachCommands(CommandBase):
status = 1 status = 1
# copy needed gstreamer DLLs in to servo.exe dir # copy needed gstreamer DLLs in to servo.exe dir
if has_media_stack: if self.enable_media:
print("Packaging gstreamer DLLs") print("Packaging gstreamer DLLs")
if not package_gstreamer_dlls(env, servo_exe_dir, target_triple): if not package_gstreamer_dlls(env, servo_exe_dir, target_triple):
status = 1 status = 1
@ -189,7 +188,7 @@ class MachCommands(CommandBase):
servo_bin_dir = os.path.dirname(servo_path) servo_bin_dir = os.path.dirname(servo_path)
assert os.path.exists(servo_bin_dir) assert os.path.exists(servo_bin_dir)
if has_media_stack: if self.enable_media:
print("Packaging gstreamer dylibs") print("Packaging gstreamer dylibs")
if not package_gstreamer_dylibs(self.cross_compile_target, servo_path): if not package_gstreamer_dylibs(self.cross_compile_target, servo_path):
return 1 return 1

View file

@ -250,6 +250,7 @@ class CommandBase(object):
def __init__(self, context): def __init__(self, context):
self.context = context self.context = context
self.enable_media = False
self.features = [] self.features = []
self.cross_compile_target = None self.cross_compile_target = None
self.is_android_build = False self.is_android_build = False
@ -493,13 +494,13 @@ class CommandBase(object):
'vcdir': vcinstalldir, 'vcdir': vcinstalldir,
} }
def build_env(self, is_build=False): def build_env(self):
"""Return an extended environment dictionary.""" """Return an extended environment dictionary."""
env = os.environ.copy() env = os.environ.copy()
servo.platform.get().set_gstreamer_environment_variables_if_necessary( if self.enable_media and not self.is_android_build:
env, cross_compilation_target=self.cross_compile_target, servo.platform.get().set_gstreamer_environment_variables_if_necessary(
check_installation=is_build) env, cross_compilation_target=self.cross_compile_target)
effective_target = self.cross_compile_target or servo.platform.host_triple() effective_target = self.cross_compile_target or servo.platform.host_triple()
if "msvc" in effective_target: if "msvc" in effective_target:
@ -806,7 +807,7 @@ class CommandBase(object):
if build_configuration: if build_configuration:
self.configure_cross_compilation(kwargs['target'], kwargs['android'], kwargs['win_arm64']) self.configure_cross_compilation(kwargs['target'], kwargs['android'], kwargs['win_arm64'])
self.features = kwargs.get("features", None) or [] self.features = kwargs.get("features", None) or []
self.configure_media_stack(kwargs['media_stack']) self.enable_media = self.is_media_enabled(kwargs['media_stack'])
return original_function(self, *args, **kwargs) return original_function(self, *args, **kwargs)
@ -874,10 +875,10 @@ class CommandBase(object):
if self.cross_compile_target: if self.cross_compile_target:
print(f"Targeting '{self.cross_compile_target}' for cross-compilation") print(f"Targeting '{self.cross_compile_target}' for cross-compilation")
def configure_media_stack(self, media_stack: Optional[str]): def is_media_enabled(self, media_stack: Optional[str]):
"""Determine what media stack to use based on the value of the build target """Determine whether media is enabled based on the value of the build target
platform and the value of the '--media-stack' command-line argument. platform and the value of the '--media-stack' command-line argument.
The chosen media stack is written into the `features` instance variable.""" Returns true if media is enabled."""
if not media_stack: if not media_stack:
if self.config["build"]["media-stack"] != "auto": if self.config["build"]["media-stack"] != "auto":
media_stack = self.config["build"]["media-stack"] media_stack = self.config["build"]["media-stack"]
@ -890,8 +891,16 @@ class CommandBase(object):
media_stack = "gstreamer" media_stack = "gstreamer"
else: else:
media_stack = "dummy" media_stack = "dummy"
if media_stack != "dummy":
self.features += ["media-" + media_stack] # This is a workaround for Ubuntu 20.04, which doesn't support a new enough GStreamer.
# Once we drop support for this platform (it's currently needed for wpt.fyi runners),
# we can remove this workaround and officially only support Ubuntu 22.04 and up.
platform = servo.platform.get()
if not self.cross_compile_target and platform.is_linux and \
not platform.is_gstreamer_installed(self.cross_compile_target):
return False
return media_stack != "dummy"
def run_cargo_build_like_command( def run_cargo_build_like_command(
self, command: str, cargo_args: List[str], self, command: str, cargo_args: List[str],
@ -903,6 +912,17 @@ class CommandBase(object):
): ):
env = env or self.build_env() env = env or self.build_env()
# Android GStreamer integration is handled elsewhere.
# NB: On non-Linux platforms we cannot check whether GStreamer is installed until
# environment variables are set via `self.build_env()`.
platform = servo.platform.get()
if self.enable_media and not self.is_android_build and \
not platform.is_gstreamer_installed(self.cross_compile_target):
raise FileNotFoundError(
"GStreamer libraries not found (>= version 1.18)."
"Please see installation instructions in README.md"
)
args = [] args = []
if "--manifest-path" not in cargo_args: if "--manifest-path" not in cargo_args:
if libsimpleservo or self.is_android_build: if libsimpleservo or self.is_android_build:
@ -922,6 +942,8 @@ class CommandBase(object):
if "-p" not in cargo_args: # We're building specific package, that may not have features if "-p" not in cargo_args: # We're building specific package, that may not have features
features = list(self.features) features = list(self.features)
if self.enable_media:
features.append("media-gstreamer")
if self.config["build"]["debug-mozjs"] or debug_mozjs: if self.config["build"]["debug-mozjs"] or debug_mozjs:
features.append("debugmozjs") features.append("debugmozjs")

View file

@ -26,11 +26,6 @@ class Base:
def set_gstreamer_environment_variables_if_necessary( def set_gstreamer_environment_variables_if_necessary(
self, env: Dict[str, str], cross_compilation_target: Optional[str], check_installation=True self, env: Dict[str, str], cross_compilation_target: Optional[str], check_installation=True
): ):
# Environment variables are not needed when cross-compiling on any platform other
# than Windows. GStreamer for Android is handled elsewhere.
if cross_compilation_target and (not self.is_windows or "android" in cross_compilation_target):
return
# We may not need to update environment variables if GStreamer is installed # We may not need to update environment variables if GStreamer is installed
# for the system on Linux. # for the system on Linux.
gstreamer_root = self.gstreamer_root(cross_compilation_target) gstreamer_root = self.gstreamer_root(cross_compilation_target)
@ -52,14 +47,6 @@ class Base:
) )
env["GST_PLUGIN_SYSTEM_PATH"] = os.path.join(gstreamer_root, "lib", "gstreamer-1.0") env["GST_PLUGIN_SYSTEM_PATH"] = os.path.join(gstreamer_root, "lib", "gstreamer-1.0")
# If we are not cross-compiling GStreamer must be installed for the system. In
# the cross-compilation case, we might be picking it up from another directory.
if check_installation and not self.is_gstreamer_installed(cross_compilation_target):
raise FileNotFoundError(
"GStreamer libraries not found (>= version 1.18)."
"Please see installation instructions in README.md"
)
def gstreamer_root(self, _cross_compilation_target: Optional[str]) -> Optional[str]: def gstreamer_root(self, _cross_compilation_target: Optional[str]) -> Optional[str]:
raise NotImplementedError("Do not know how to get GStreamer path for platform.") raise NotImplementedError("Do not know how to get GStreamer path for platform.")

View file

@ -12,7 +12,6 @@ import subprocess
from typing import Optional, Tuple from typing import Optional, Tuple
import distro import distro
from .. import util
from .base import Base from .base import Base
# Please keep these in sync with the packages on the wiki, using the instructions below # Please keep these in sync with the packages on the wiki, using the instructions below
@ -75,8 +74,6 @@ XBPS_PKGS = ['libtool', 'gcc', 'libXi-devel', 'freetype-devel',
GSTREAMER_URL = \ GSTREAMER_URL = \
"https://github.com/servo/servo-build-deps/releases/download/linux/gstreamer-1.16-x86_64-linux-gnu.20190515.tar.gz" "https://github.com/servo/servo-build-deps/releases/download/linux/gstreamer-1.16-x86_64-linux-gnu.20190515.tar.gz"
PREPACKAGED_GSTREAMER_ROOT = \
os.path.join(util.get_target_dir(), "dependencies", "gstreamer")
class Linux(Base): class Linux(Base):
@ -154,7 +151,6 @@ class Linux(Base):
f"{self.distro}, please file a bug") f"{self.distro}, please file a bug")
installed_something = self.install_non_gstreamer_dependencies(force) installed_something = self.install_non_gstreamer_dependencies(force)
installed_something |= self._platform_bootstrap_gstreamer(force)
return installed_something return installed_something
def install_non_gstreamer_dependencies(self, force: bool) -> bool: def install_non_gstreamer_dependencies(self, force: bool) -> bool:
@ -199,18 +195,9 @@ class Linux(Base):
return True return True
def gstreamer_root(self, cross_compilation_target: Optional[str]) -> Optional[str]: def gstreamer_root(self, cross_compilation_target: Optional[str]) -> Optional[str]:
if cross_compilation_target:
return None
if os.path.exists(PREPACKAGED_GSTREAMER_ROOT):
return PREPACKAGED_GSTREAMER_ROOT
# GStreamer might be installed system-wide, but we do not return a root in this
# case because we don't have to update environment variables.
return None return None
def _platform_bootstrap_gstreamer(self, force: bool) -> bool: def _platform_bootstrap_gstreamer(self, _force: bool) -> bool:
if not force and self.is_gstreamer_installed(cross_compilation_target=None):
return False
raise EnvironmentError( raise EnvironmentError(
"Bootstrapping GStreamer on Linux is not supported. " "Bootstrapping GStreamer on Linux is not supported. "
+ "Please install it using your distribution package manager.") + "Please install it using your distribution package manager.")

View file

@ -266,7 +266,7 @@ class PostBuildCommands(CommandBase):
else: else:
copy2(full_name, destination) copy2(full_name, destination)
env = self.build_env(is_build=True) env = self.build_env()
returncode = self.run_cargo_build_like_command("doc", params, env=env, **kwargs) returncode = self.run_cargo_build_like_command("doc", params, env=env, **kwargs)
if returncode: if returncode:
return returncode return returncode

View file

@ -258,9 +258,7 @@ class MachCommands(CommandBase):
if nocapture: if nocapture:
args += ["--", "--nocapture"] args += ["--", "--nocapture"]
# We are setting is_build here to true, because running `cargo test` can trigger builds. env = self.build_env()
env = self.build_env(is_build=True)
return self.run_cargo_build_like_command( return self.run_cargo_build_like_command(
"bench" if bench else "test", "bench" if bench else "test",
args, args,