aboutsummaryrefslogtreecommitdiffstats
path: root/python/servo/build_commands.py
diff options
context:
space:
mode:
authorMartin Robinson <mrobinson@igalia.com>2024-01-17 11:53:34 +0100
committerGitHub <noreply@github.com>2024-01-17 10:53:34 +0000
commitd86e713a9cb5be2555d63bd477d47d440fa8c832 (patch)
treee7bbc0783b19f4b4500fb350e60654c276ad0b1d /python/servo/build_commands.py
parentf76982e2e7f411e2e2fd8e6dbfe92a080acefc54 (diff)
downloadservo-d86e713a9cb5be2555d63bd477d47d440fa8c832.tar.gz
servo-d86e713a9cb5be2555d63bd477d47d440fa8c832.zip
build: Clean up post-build copy of Windows DLLs (#31092)
* build: Clean up post-build copy of Windows DLLs - No longer use vcvarsall.bat at all. Instead find the Windows SDK directory by looking in the registry. - Split logic for copying Windows dependencies into its own function and do some minor clean up, such as collecting all MSVC functionality into visual_studio.py. - Remove support for Visual Studio 2015 and Visual Studio 2017. This is a preparatory change in order to support Visual Studio 2022. * More cleanup of the code
Diffstat (limited to 'python/servo/build_commands.py')
-rw-r--r--python/servo/build_commands.py151
1 files changed, 40 insertions, 111 deletions
diff --git a/python/servo/build_commands.py b/python/servo/build_commands.py
index 9935e2c1c48..f61c82fe5b3 100644
--- a/python/servo/build_commands.py
+++ b/python/servo/build_commands.py
@@ -8,9 +8,9 @@
# except according to those terms.
import datetime
-import locale
import os
import os.path as path
+import pathlib
import shutil
import stat
import subprocess
@@ -35,6 +35,7 @@ import servo.util
from servo.command_base import BuildType, CommandBase, call, check_call
from servo.gstreamer import windows_dlls, windows_plugins, macos_plugins
+from python.servo.visual_studio import find_msvc_redist_dirs
@CommandProvider
@@ -80,9 +81,6 @@ class MachCommands(CommandBase):
build_start = time()
host = servo.platform.host_triple()
- if 'windows' in host:
- vs_dirs = self.vs_dirs()
-
target_triple = self.cross_compile_target or servo.platform.host_triple()
if host != target_triple and 'windows' in target_triple:
if os.environ.get('VisualStudioVersion') or os.environ.get('VCINSTALLDIR'):
@@ -91,29 +89,6 @@ class MachCommands(CommandBase):
"Visual Studio shell, and make sure the VisualStudioVersion and "
"VCINSTALLDIR environment variables are not set.")
sys.exit(1)
- vcinstalldir = vs_dirs['vcdir']
- if not os.path.exists(vcinstalldir):
- print("Can't find Visual C++ %s installation at %s." % (vs_dirs['vs_version'], vcinstalldir))
- sys.exit(1)
-
- env['PKG_CONFIG_ALLOW_CROSS'] = "1"
-
- if 'windows' in host:
- process = subprocess.Popen('("%s" %s > nul) && "python" -c "import os; print(repr(os.environ))"' %
- (os.path.join(vs_dirs['vcdir'], "Auxiliary", "Build", "vcvarsall.bat"), "x64"),
- stdout=subprocess.PIPE, shell=True)
- stdout, stderr = process.communicate()
- exitcode = process.wait()
- encoding = locale.getpreferredencoding() # See https://stackoverflow.com/a/9228117
- if exitcode == 0:
- decoded = stdout.decode(encoding)
- if decoded.startswith("environ("):
- decoded = decoded.strip()[8:-1]
- os.environ.update(eval(decoded))
- else:
- print("Failed to run vcvarsall. stderr:")
- print(stderr.decode(encoding))
- exit(1)
# Gather Cargo build timings (https://doc.rust-lang.org/cargo/reference/timings.html).
opts = ["--timings"] + opts
@@ -130,6 +105,7 @@ class MachCommands(CommandBase):
)
# Do some additional things if the build succeeded
+ built_binary = self.get_binary_path(build_type, target=self.cross_compile_target, simpleservo=libsimpleservo)
if status == 0:
if self.is_android_build and not no_package:
flavor = None
@@ -143,43 +119,7 @@ class MachCommands(CommandBase):
return rv
if sys.platform == "win32":
- servo_exe_dir = os.path.dirname(
- self.get_binary_path(build_type, target=self.cross_compile_target, simpleservo=libsimpleservo)
- )
- assert os.path.exists(servo_exe_dir)
-
- build_path = path.join(servo_exe_dir, "build")
- assert os.path.exists(build_path)
-
- # on msvc, we need to copy in some DLLs in to the servo.exe dir and the directory for unit tests.
- def package_generated_shared_libraries(libs, build_path, servo_exe_dir):
- for root, dirs, files in os.walk(build_path):
- remaining_libs = list(libs)
- for lib in libs:
- if lib in files:
- shutil.copy(path.join(root, lib), servo_exe_dir)
- remaining_libs.remove(lib)
- continue
- libs = remaining_libs
- if not libs:
- return True
- for lib in libs:
- print("WARNING: could not find " + lib)
-
- print("Packaging EGL DLLs")
- egl_libs = ["libEGL.dll", "libGLESv2.dll"]
- if not package_generated_shared_libraries(egl_libs, build_path, servo_exe_dir):
- status = 1
-
- # copy needed gstreamer DLLs in to servo.exe dir
- if self.enable_media:
- print("Packaging gstreamer DLLs")
- if not package_gstreamer_dlls(env, servo_exe_dir, target_triple):
- status = 1
-
- # UWP app packaging already bundles all required DLLs for us.
- print("Packaging MSVC DLLs")
- if not package_msvc_dlls(servo_exe_dir, target_triple, vs_dirs['vcdir'], vs_dirs['vs_version']):
+ if not copy_windows_dlls_to_build_directory(built_binary, target_triple):
status = 1
elif sys.platform == "darwin":
@@ -423,7 +363,38 @@ def package_gstreamer_dylibs(cross_compilation_target, servo_bin):
return True
-def package_gstreamer_dlls(env, servo_exe_dir, target):
+def copy_windows_dlls_to_build_directory(servo_binary: str, target_triple: str) -> bool:
+ servo_exe_dir = os.path.dirname(servo_binary)
+ assert os.path.exists(servo_exe_dir)
+
+ build_path = path.join(servo_exe_dir, "build")
+ assert os.path.exists(build_path)
+
+ # Copy in the built EGL and GLES libraries from where they were built to
+ # the final build dirctory
+ def find_and_copy_built_dll(dll_name):
+ try:
+ file_to_copy = next(pathlib.Path(build_path).rglob(dll_name))
+ shutil.copy(file_to_copy, servo_exe_dir)
+ except StopIteration:
+ print(f"WARNING: could not find {dll_name}")
+
+ print(" • Copying ANGLE DLLs to binary directory...")
+ find_and_copy_built_dll("libEGL.dll")
+ find_and_copy_built_dll("libGLESv2.dll")
+
+ print(" • Copying GStreamer DLLs to binary directory...")
+ if not package_gstreamer_dlls(servo_exe_dir, target_triple):
+ return False
+
+ print(" • Copying MSVC DLLs to binary directory...")
+ if not package_msvc_dlls(servo_exe_dir, target_triple):
+ return False
+
+ return True
+
+
+def package_gstreamer_dlls(servo_exe_dir: str, target: str):
gst_root = servo.platform.get().gstreamer_root(cross_compilation_target=target)
if not gst_root:
print("Could not find GStreamer installation directory.")
@@ -462,58 +433,16 @@ def package_gstreamer_dlls(env, servo_exe_dir, target):
return not missing
-def package_msvc_dlls(servo_exe_dir, target, vcinstalldir, vs_version):
- # copy some MSVC DLLs to servo.exe dir
- msvc_redist_dir = None
- vs_platforms = {
- "x86_64": "x64",
- "i686": "x86",
- "aarch64": "arm64",
- }
- target_arch = target.split('-')[0]
- vs_platform = vs_platforms[target_arch]
- vc_dir = vcinstalldir or os.environ.get("VCINSTALLDIR", "")
- if not vs_version:
- vs_version = os.environ.get("VisualStudioVersion", "")
+def package_msvc_dlls(servo_exe_dir, target):
msvc_deps = [
"msvcp140.dll",
"vcruntime140.dll",
]
- if target_arch != "aarch64" and vs_version in ("14.0", "15.0", "16.0"):
+ if "aarch64" not in target != "aarch64":
msvc_deps += ["api-ms-win-crt-runtime-l1-1-0.dll"]
- # Check if it's Visual C++ Build Tools or Visual Studio 2015
- vs14_vcvars = path.join(vc_dir, "vcvarsall.bat")
- is_vs14 = True if os.path.isfile(vs14_vcvars) or vs_version == "14.0" else False
- if is_vs14:
- msvc_redist_dir = path.join(vc_dir, "redist", vs_platform, "Microsoft.VC140.CRT")
- elif vs_version in ("15.0", "16.0"):
- redist_dir = path.join(vc_dir, "Redist", "MSVC")
- if os.path.isdir(redist_dir):
- for p in os.listdir(redist_dir)[::-1]:
- redist_path = path.join(redist_dir, p)
- for v in ["VC141", "VC142", "VC150", "VC160"]:
- # there are two possible paths
- # `x64\Microsoft.VC*.CRT` or `onecore\x64\Microsoft.VC*.CRT`
- redist1 = path.join(redist_path, vs_platform, "Microsoft.{}.CRT".format(v))
- redist2 = path.join(redist_path, "onecore", vs_platform, "Microsoft.{}.CRT".format(v))
- if os.path.isdir(redist1):
- msvc_redist_dir = redist1
- break
- elif os.path.isdir(redist2):
- msvc_redist_dir = redist2
- break
- if msvc_redist_dir:
- break
- if not msvc_redist_dir:
- print("Couldn't locate MSVC redistributable directory")
- return False
- redist_dirs = [
- msvc_redist_dir,
- ]
- if "WindowsSdkDir" in os.environ:
- redist_dirs += [path.join(os.environ["WindowsSdkDir"], "Redist", "ucrt", "DLLs", vs_platform)]
missing = []
+ redist_dirs = find_msvc_redist_dirs(target)
for msvc_dll in msvc_deps:
for dll_dir in redist_dirs:
dll = path.join(dll_dir, msvc_dll)
@@ -528,5 +457,5 @@ def package_msvc_dlls(servo_exe_dir, target, vcinstalldir, vs_version):
missing += [msvc_dll]
for msvc_dll in missing:
- print("DLL file `{}` not found!".format(msvc_dll))
+ print(f"Could not find DLL dependency: {msvc_dll}")
return not missing