From 731a00716fd3b6673ec09e30ec661a3f2d70c49d Mon Sep 17 00:00:00 2001 From: Eloston Date: Mon, 17 Oct 2016 19:08:41 -0700 Subject: [PATCH] Refactor buildlib into separate components for different patching and meta-build configuration implementations --- buildlib/_util.py | 4 +- buildlib/common.py | 313 ++++++++++++++++++++++++++++---------------- buildlib/debian.py | 58 +------- buildlib/linux.py | 39 +----- buildlib/macos.py | 50 +------ buildlib/windows.py | 31 +---- 6 files changed, 214 insertions(+), 281 deletions(-) diff --git a/buildlib/_util.py b/buildlib/_util.py index 666075f9..d08f0afd 100644 --- a/buildlib/_util.py +++ b/buildlib/_util.py @@ -165,7 +165,7 @@ def download_if_needed(logger, file_path, url, force_download): # This is a port from https://hg.python.org/cpython/file/3.5/Lib/subprocess.py#l629 # TODO: Delete this when Python 3.5 is required -class _CompletedProcess(object): +class _CompletedProcess(object): # pylint: disable=too-few-public-methods """A process that has finished running. This is returned by run(). @@ -198,7 +198,7 @@ class _CompletedProcess(object): # This is a port of run() from https://hg.python.org/cpython/file/3.5/Lib/subprocess.py#l662 # TODO: Delete this when Python 3.5 is required -def subprocess_run(*popenargs, input=None, timeout=None, check=False, **kwargs): +def subprocess_run(*popenargs, input=None, timeout=None, check=False, **kwargs): # pylint: disable=redefined-builtin """Run command with arguments and return a CompletedProcess instance. The returned instance will have attributes args, returncode, stdout and diff --git a/buildlib/common.py b/buildlib/common.py index 4c2bac70..07e0e2b6 100644 --- a/buildlib/common.py +++ b/buildlib/common.py @@ -27,6 +27,7 @@ import configparser import distutils.dir_util import os import enum +import shutil from . import _util from ._util import BuilderException @@ -37,8 +38,9 @@ DOMAIN_SUBSTITUTION_LIST = pathlib.Path("domain_substitution_list") PATCHES = pathlib.Path("patches") EXTRA_DEPS = pathlib.Path("extra_deps.ini") PATCH_ORDER = pathlib.Path("patch_order") + GYP_FLAGS = pathlib.Path("gyp_flags") -#GN_ARGS = pathlib.Path("gn_args.ini") +GN_ARGS = pathlib.Path("gn_args.ini") class CPUArch(enum.Enum): ''' @@ -52,6 +54,8 @@ class Builder: Generic builder class. Also a metaclass for specific Builder implementations ''' + # pylint: disable=too-many-instance-attributes + _resources = pathlib.Path("resources", "common") # Force the downloading of dependencies instead of checking if they exist @@ -63,8 +67,6 @@ class Builder: # Switch for running domain substitution run_domain_substitution = True - #gn_command = None - # The command to invoke Python 2 # If set to none, the shebang line or file associations are used python2_command = None @@ -151,18 +153,6 @@ class Builder: combined_dict[section][config_key] = resource_config[section][config_key] return combined_dict - def _get_gyp_flags(self): - args_dict = dict() - for i in self._read_list_resource(GYP_FLAGS): - arg_key, arg_value = i.split("=", 1) - args_dict[arg_key] = arg_value - if not self.target_arch is None: - if self.target_arch == CPUArch.x86: - args_dict["target_arch"] = "ia32" - else: - args_dict["target_arch"] = self.target_arch.value - return args_dict - def _setup_tar_dependency(self, tar_url, tar_filename, strip_tar_dirs, dep_destination): tar_destination = self._downloads_dir / pathlib.Path(tar_filename) _util.download_if_needed(self.logger, tar_destination, tar_url, self.force_download) @@ -198,53 +188,6 @@ class Builder: (self.build_dir / PATCHES).rglob("*.patch"), log_warnings=False) - def _gyp_generate_ninja(self, args_dict, append_environ): - command_list = list() - if not self.python2_command is None: - command_list.append(self.python2_command) - command_list.append(str(pathlib.Path("build", "gyp_chromium"))) - command_list += ["--depth=.", "--check"] - for arg_key, arg_value in args_dict.items(): - command_list.append("-D{}={}".format(arg_key, arg_value)) - self.logger.debug("GYP command: {}".format(" ".join(command_list))) - result = self._run_subprocess(command_list, append_environ=append_environ, - cwd=str(self._sandbox_dir)) - if not result.returncode == 0: - raise BuilderException("GYP command returned non-zero exit code: {}".format( - result.returncode)) - - def _gn_write_args(self, args_map): - ''' - `args_map` can be any object supporting the mapping interface - ''' - gn_imports = list() - gn_flags = list() - for gn_path in args_map: - # Checking against DEFAULT for configparser mapping interface - if not gn_path == "DEFAULT" and not gn_path == "global": - if not gn_path.lower().endswith(".gn"): - gn_imports.append('import("{}")'.format(gn_path)) - for flag in args_map[gn_path]: - gn_flags.append("{}={}".format(flag, args_map[gn_path][flag])) - with (self._sandbox_dir / self.build_output / - pathlib.Path("args.gn")).open("w") as file_obj: - file_obj.write("\n".join(gn_imports)) - file_obj.write("\n") - file_obj.write("\n".join(gn_flags)) - - #def _gn_generate_ninja(self, gn_override=None): - # command_list = list() - # if gn_override is None: - # command_list.append(self.gn_command) - # else: - # command_list.append(gn_override) - # command_list.append("gen") - # command_list.append(str(self.build_output)) - # result = self._run_subprocess(command_list, cwd=str(self._sandbox_dir)) - # if not result.returncode == 0: - # raise BuilderException("gn gen returned non-zero exit code: {}".format( - # result.returncode)) - def _run_ninja(self, output, targets): # TODO: Use iterable unpacking instead when requiring Python 3.5 result = self._run_subprocess([self.ninja_command, "-C", str(output)] + targets, @@ -253,36 +196,6 @@ class Builder: raise BuilderException("ninja returned non-zero exit code: {}".format( result.returncode)) - #def _build_gn(self): - # ''' - # Build the GN tool to out/gn_tool in the build sandbox. Returns the gn command string. - # - # Only works on Linux or Mac. - # ''' - # self.logger.info("Building gn...") - # temp_gn_executable = pathlib.Path("out", "temp_gn") - # if (self._sandbox_dir / temp_gn_executable).exists(): - # self.logger.info("Bootstrap gn already exists") - # else: - # self.logger.info("Building bootstrap gn") - # command_list = [str(pathlib.Path("tools", "gn", "bootstrap", "bootstrap.py")), - # "-v", "-s", "-o", str(temp_gn_executable), - # "--gn-gen-args= use_sysroot=false"] - # if not self.python2_command is None: - # command_list.insert(0, self.python2_command) - # result = self._run_subprocess(command_list, cwd=str(self._sandbox_dir)) - # if not result.returncode == 0: - # raise BuilderException("GN bootstrap command returned " - # "non-zero exit code: {}".format(result.returncode)) - # self.logger.info("Building gn using bootstrap gn...") - # build_output = pathlib.Path("out", "gn_release") - # (self._sandbox_dir / build_output).mkdir(parents=True, exist_ok=True) - # self._gn_write_args({"global": {"use_sysroot": "false", "is_debug": "false"}}, - # build_output) - # self._gn_generate_ninja(build_output, gn_override=str(temp_gn_executable)) - # self._run_ninja(build_output, ["gn"]) - # return str(build_output / pathlib.Path("gn")) - def check_build_environment(self): '''Checks the build environment before building''' @@ -402,6 +315,202 @@ class Builder: # TODO: Use Python to apply patches defined in `patch_order` pass + def setup_build_utilities(self): + '''Sets up additional build utilities not provided by the build environment''' + pass + + def generate_build_configuration(self): + '''Generates build configuration''' + pass + + def build(self): + '''Starts building''' + self.logger.info("Running build command...") + self._run_ninja(self.build_output, self.build_targets) + + def generate_package(self): + '''Generates binary packages ready for distribution''' + # TODO: Create .tar.xz of binaries? + pass + +class QuiltPatchComponent(Builder): + '''Patching component implemented with quilt''' + + quilt_command = "quilt" + + def __init__(self, *args, **kwargs): + super(QuiltPatchComponent, self).__init__(*args, **kwargs) + + self.quilt_env_vars = { + "QUILT_PATCHES": str(pathlib.Path("..") / PATCHES), + "QUILT_SERIES": str(PATCH_ORDER) + } + + def apply_patches(self): + self.logger.debug("Copying patches to {}...".format(str(self.build_dir / PATCHES))) + + if (self.build_dir / PATCHES).exists(): + self.logger.warning("Sandbox patches directory already exists. Trying to unapply...") + result = self._run_subprocess([self.quilt_command, "pop", "-a"], + append_environ=self.quilt_env_vars, + cwd=str(self._sandbox_dir)) + if not result.returncode == 0 and not result.returncode == 2: + raise BuilderException("Quilt returned non-zero exit code: {}".format( + result.returncode)) + shutil.rmtree(str(self.build_dir / PATCHES)) + + self._generate_patches() + + self.logger.info("Applying patches via quilt...") + result = self._run_subprocess([self.quilt_command, "push", "-a"], + append_environ=self.quilt_env_vars, + cwd=str(self._sandbox_dir)) + if not result.returncode == 0: + raise BuilderException("Quilt returned non-zero exit code: {}".format( + result.returncode)) + + def check_build_environment(self): + super(QuiltPatchComponent, self).check_build_environment() + + self.logger.info("Checking quilt command...") + result = self._run_subprocess([self.quilt_command, "--version"], stdout=subprocess.PIPE, + universal_newlines=True) + if not result.returncode is 0: + raise BuilderException("quilt command returned non-zero exit code {}".format( + result.returncode)) + self.logger.debug("Using quilt command '{!s}'".format(result.stdout.strip("\n"))) + +class GNUPatchComponent(Builder): + '''Patching component implemented with GNU patch''' + + patch_command = ["patch", "-p1"] + + def apply_patches(self): + self.logger.info("Applying patches via '{}' ...".format(" ".join(self.patch_command))) + self._generate_patches() + with (self.build_dir / PATCHES / PATCH_ORDER).open() as patch_order_file: + for i in [x for x in patch_order_file.read().splitlines() if len(x) > 0]: + self.logger.debug("Applying patch {} ...".format(i)) + with (self.build_dir / PATCHES / i).open("rb") as patch_file: + result = self._run_subprocess(self.patch_command, cwd=str(self._sandbox_dir), + stdin=patch_file) + if not result.returncode == 0: + raise BuilderException("'{}' returned non-zero exit code {}".format( + " ".join(self.patch_command), result.returncode)) + + def check_build_environment(self): + super(GNUPatchComponent, self).check_build_environment() + + self.logger.info("Checking patch command...") + result = self._run_subprocess([self.patch_command[0], "--version"], stdout=subprocess.PIPE, + universal_newlines=True) + if not result.returncode is 0: + raise BuilderException("patch command returned non-zero exit code {}".format( + result.returncode)) + self.logger.debug("Using patch command '{!s}'".format(result.stdout.split("\n")[0])) + +class GYPMetaBuildComponent(Builder): + '''Meta-build configuration component implemented with GYP''' + + def _get_gyp_flags(self): + args_dict = dict() + for i in self._read_list_resource(GYP_FLAGS): + arg_key, arg_value = i.split("=", 1) + args_dict[arg_key] = arg_value + if not self.target_arch is None: + if self.target_arch == CPUArch.x86: + args_dict["target_arch"] = "ia32" + else: + args_dict["target_arch"] = self.target_arch.value + return args_dict + + def _gyp_generate_ninja(self, args_dict, append_environ): + command_list = list() + if not self.python2_command is None: + command_list.append(self.python2_command) + command_list.append(str(pathlib.Path("build", "gyp_chromium"))) + command_list += ["--depth=.", "--check"] + for arg_key, arg_value in args_dict.items(): + command_list.append("-D{}={}".format(arg_key, arg_value)) + self.logger.debug("GYP command: {}".format(" ".join(command_list))) + result = self._run_subprocess(command_list, append_environ=append_environ, + cwd=str(self._sandbox_dir)) + if not result.returncode == 0: + raise BuilderException("GYP command returned non-zero exit code: {}".format( + result.returncode)) + + def generate_build_configuration(self): + '''Generates build configuration using GYP''' + self.logger.info("Running gyp command...") + self._gyp_generate_ninja(self._get_gyp_flags(), None) + +class GNMetaBuildComponent(Builder): + '''Meta-build configuration component implemented with GN''' + + gn_command = None + + def _gn_write_args(self, args_map): + ''' + `args_map` can be any object supporting the mapping interface + ''' + gn_imports = list() + gn_flags = list() + for gn_path in args_map: + # Checking against DEFAULT for configparser mapping interface + if not gn_path == "DEFAULT" and not gn_path == "global": + if not gn_path.lower().endswith(".gn"): + gn_imports.append('import("{}")'.format(gn_path)) + for flag in args_map[gn_path]: + gn_flags.append("{}={}".format(flag, args_map[gn_path][flag])) + with (self._sandbox_dir / self.build_output / + pathlib.Path("args.gn")).open("w") as file_obj: + file_obj.write("\n".join(gn_imports)) + file_obj.write("\n") + file_obj.write("\n".join(gn_flags)) + + #def _gn_generate_ninja(self, gn_override=None): + # command_list = list() + # if gn_override is None: + # command_list.append(self.gn_command) + # else: + # command_list.append(gn_override) + # command_list.append("gen") + # command_list.append(str(self.build_output)) + # result = self._run_subprocess(command_list, cwd=str(self._sandbox_dir)) + # if not result.returncode == 0: + # raise BuilderException("gn gen returned non-zero exit code: {}".format( + # result.returncode)) + + #def _build_gn(self): + # ''' + # Build the GN tool to out/gn_tool in the build sandbox. Returns the gn command string. + # + # Only works on Linux or Mac. + # ''' + # self.logger.info("Building gn...") + # temp_gn_executable = pathlib.Path("out", "temp_gn") + # if (self._sandbox_dir / temp_gn_executable).exists(): + # self.logger.info("Bootstrap gn already exists") + # else: + # self.logger.info("Building bootstrap gn") + # command_list = [str(pathlib.Path("tools", "gn", "bootstrap", "bootstrap.py")), + # "-v", "-s", "-o", str(temp_gn_executable), + # "--gn-gen-args= use_sysroot=false"] + # if not self.python2_command is None: + # command_list.insert(0, self.python2_command) + # result = self._run_subprocess(command_list, cwd=str(self._sandbox_dir)) + # if not result.returncode == 0: + # raise BuilderException("GN bootstrap command returned " + # "non-zero exit code: {}".format(result.returncode)) + # self.logger.info("Building gn using bootstrap gn...") + # build_output = pathlib.Path("out", "gn_release") + # (self._sandbox_dir / build_output).mkdir(parents=True, exist_ok=True) + # self._gn_write_args({"global": {"use_sysroot": "false", "is_debug": "false"}}, + # build_output) + # self._gn_generate_ninja(build_output, gn_override=str(temp_gn_executable)) + # self._run_ninja(build_output, ["gn"]) + # return str(build_output / pathlib.Path("gn")) + #def setup_build_utilities(self, build_gn=True, gn_command=None, python2_command=None, # ninja_command="ninja"): # ''' @@ -424,11 +533,6 @@ class Builder: # else: # self.gn_command = gn_command - def setup_build_utilities(self): - '''Sets up additional build utilities not provided by the build environment''' - # TODO: Implement this when switching to GN - pass - #def generate_build_configuration(self, gn_args=pathlib.Path("gn_args.ini"), # build_output=pathlib.Path("out", "Default")): # (self._sandbox_dir / build_output).mkdir(parents=True, exist_ok=True) @@ -436,18 +540,3 @@ class Builder: # config.read(str(gn_args)) # self._gn_write_args(config, build_output) # self._gn_generate_ninja(build_output) - - def generate_build_configuration(self): - '''Generates build configuration''' - self.logger.info("Running gyp command...") - self._gyp_generate_ninja(self._get_gyp_flags(), None) - - def build(self): - '''Starts building''' - self.logger.info("Running build command...") - self._run_ninja(self.build_output, self.build_targets) - - def generate_package(self): - '''Generates binary packages ready for distribution''' - # TODO: Create .tar.xz of binaries? - pass diff --git a/buildlib/debian.py b/buildlib/debian.py index 6336b370..c90210c8 100644 --- a/buildlib/debian.py +++ b/buildlib/debian.py @@ -23,23 +23,21 @@ import pathlib import datetime import locale import string -import shutil import itertools import distutils.dir_util import re from ._util import BuilderException -from .common import Builder, PATCHES, PATCH_ORDER +from .common import QuiltPatchComponent, GYPMetaBuildComponent __all__ = ["DebianBuilder", "DebianStretchBuilder", "UbuntuXenialBuilder"] -class DebianBuilder(Builder): +class DebianBuilder(QuiltPatchComponent, GYPMetaBuildComponent): '''Generic Builder for all Debian and derivative distributions''' _resources = pathlib.Path("resources", "common_debian") _dpkg_dir = _resources / pathlib.Path("dpkg_dir") - quilt_command = "quilt" build_targets = ["chrome", "chrome_sandbox", "chromedriver"] class BuildFileStringTemplate(string.Template): @@ -81,11 +79,6 @@ class DebianBuilder(Builder): self._sandbox_dpkg_dir = self._sandbox_dir / pathlib.Path("debian") - self.quilt_env_vars = { - "QUILT_PATCHES": str(pathlib.Path("..") / PATCHES), - "QUILT_SERIES": str(PATCH_ORDER) - } - def check_build_environment(self): self.logger.info("Checking installed packages...") result = self._run_subprocess(["dpkg-checkbuilddeps", @@ -109,53 +102,6 @@ class DebianBuilder(Builder): symlink_path.unlink() symlink_path.symlink_to(system_path) - def apply_patches(self): - self.logger.debug("Copying patches to {}...".format(str(self.build_dir / PATCHES))) - - if (self.build_dir / PATCHES).exists(): - self.logger.warning("Sandbox patches directory already exists. Trying to unapply...") - result = self._run_subprocess([self.quilt_command, "pop", "-a"], - append_environ=self.quilt_env_vars, - cwd=str(self._sandbox_dir)) - if not result.returncode == 0 and not result.returncode == 2: - raise BuilderException("Quilt returned non-zero exit code: {}".format( - result.returncode)) - shutil.rmtree(str(self.build_dir / PATCHES)) - - self._generate_patches() - - self.logger.info("Applying patches via quilt...") - result = self._run_subprocess([self.quilt_command, "push", "-a"], - append_environ=self.quilt_env_vars, - cwd=str(self._sandbox_dir)) - if not result.returncode == 0: - raise BuilderException("Quilt returned non-zero exit code: {}".format( - result.returncode)) - - #def generate_build_configuration(self, gn_args=pathlib.Path("gn_args.ini"), - # build_output=pathlib.Path("out", "Default"), - # debian_gn_args=(self.PLATFORM_RESOURCES / - # pathlib.Path("gn_args.ini")): - # (self._sandbox_dir / build_output).mkdir(parents=True, exist_ok=True) - # common_config = configparser.ConfigParser() - # common_config.read(str(gn_args)) - # debian_config = configparser.ConfigParser() - # debian_config.read(str(debian_gn_args)) - # combined_dict = dict() - # for section in common_config: - # if not section == "DEFAULT": - # combined_dict[section] = dict() - # for config_key in common_config[section]: - # combined_dict[section][config_key] = common_config[section][config_key] - # for section in debian_config: - # if not section == "DEFAULT": - # if not section in combined_dict: - # combined_dict[section] = dict() - # for config_key in debian_config[section]: - # combined_dict[section][config_key] = debian_config[section][config_key] - # self._gn_write_args(combined_dict, build_output) - # self._gn_generate_ninja(build_output) - def generate_package(self): build_file_subs = dict( changelog_version="{}-{}".format(self.chromium_version, self.release_revision), diff --git a/buildlib/linux.py b/buildlib/linux.py index 19671a5f..a0943a38 100644 --- a/buildlib/linux.py +++ b/buildlib/linux.py @@ -19,48 +19,13 @@ '''Code for generic Linux builders''' -import shutil import pathlib -from ._util import BuilderException -from .common import Builder, PATCHES, PATCH_ORDER +from .common import QuiltPatchComponent, GYPMetaBuildComponent __all__ = ["LinuxStaticBuilder"] -class LinuxStaticBuilder(Builder): +class LinuxStaticBuilder(QuiltPatchComponent, GYPMetaBuildComponent): '''Builder for statically-linked Linux builds''' _resources = pathlib.Path("resources", "linux_static") - - quilt_command = "quilt" - - def __init__(self, *args, **kwargs): - super(LinuxStaticBuilder, self).__init__(*args, **kwargs) - - self.quilt_env_vars = { - "QUILT_PATCHES": str(pathlib.Path("..") / PATCHES), - "QUILT_SERIES": str(PATCH_ORDER) - } - - def apply_patches(self): - self.logger.debug("Copying patches to {}...".format(str(self.build_dir / PATCHES))) - - if (self.build_dir / PATCHES).exists(): - self.logger.warning("Sandbox patches directory already exists. Trying to unapply...") - result = self._run_subprocess([self.quilt_command, "pop", "-a"], - append_environ=self.quilt_env_vars, - cwd=str(self._sandbox_dir)) - if not result.returncode == 0 and not result.returncode == 2: - raise BuilderException("Quilt returned non-zero exit code: {}".format( - result.returncode)) - shutil.rmtree(str(self.build_dir / PATCHES)) - - self._generate_patches() - - self.logger.info("Applying patches via quilt...") - result = self._run_subprocess([self.quilt_command, "push", "-a"], - append_environ=self.quilt_env_vars, - cwd=str(self._sandbox_dir)) - if not result.returncode == 0: - raise BuilderException("Quilt returned non-zero exit code: {}".format( - result.returncode)) diff --git a/buildlib/macos.py b/buildlib/macos.py index 8a1f26cd..5d560ff7 100644 --- a/buildlib/macos.py +++ b/buildlib/macos.py @@ -25,34 +25,16 @@ import subprocess import shutil from ._util import BuilderException -from .common import Builder, PATCHES, PATCH_ORDER +from .common import QuiltPatchComponent, GYPMetaBuildComponent -class MacOSBuilder(Builder): +class MacOSBuilder(QuiltPatchComponent, GYPMetaBuildComponent): '''Builder for macOS''' _resources = pathlib.Path("resources", "macos") - quilt_command = "quilt" - - def __init__(self, *args, **kwargs): - super(MacOSBuilder, self).__init__(*args, **kwargs) - - self.quilt_env_vars = { - "QUILT_PATCHES": str(pathlib.Path("..") / PATCHES), - "QUILT_SERIES": str(PATCH_ORDER) - } - def check_build_environment(self): super(MacOSBuilder, self).check_build_environment() - self.logger.info("Checking quilt command...") - result = self._run_subprocess([self.quilt_command, "--version"], stdout=subprocess.PIPE, - universal_newlines=True) - if not result.returncode is 0: - raise BuilderException("quilt command returned non-zero exit code {}".format( - result.returncode)) - self.logger.debug("Using quilt command '{!s}'".format(result.stdout.strip("\n"))) - self.logger.info("Checking svn command...") result = self._run_subprocess(["svn", "--version", "--quiet"], stdout=subprocess.PIPE, universal_newlines=True) @@ -69,32 +51,10 @@ class MacOSBuilder(Builder): # TODO: Maybe add check for macOS SDK version self.logger.info("Checking g++ compiler for building libc++...") - if not pathlib.Path(shutil.which("g++-4.9")).is_file(): + gxx_compiler = shutil.which("g++-4.9") + if not pathlib.Path(gxx_compiler).is_file(): raise BuilderException("GNU compiler '{}' does not exist or is not a file".format( - compiler)) - - def apply_patches(self): - self.logger.debug("Copying patches to {}...".format(str(self.build_dir / PATCHES))) - - if (self.build_dir / PATCHES).exists(): - self.logger.warning("Sandbox patches directory already exists. Trying to unapply...") - result = self._run_subprocess([self.quilt_command, "pop", "-a"], - append_environ=self.quilt_env_vars, - cwd=str(self._sandbox_dir)) - if not result.returncode == 0 and not result.returncode == 2: - raise BuilderException("Quilt returned non-zero exit code: {}".format( - result.returncode)) - shutil.rmtree(str(self.build_dir / PATCHES)) - - self._generate_patches() - - self.logger.info("Applying patches via quilt...") - result = self._run_subprocess([self.quilt_command, "push", "-a"], - append_environ=self.quilt_env_vars, - cwd=str(self._sandbox_dir)) - if not result.returncode == 0: - raise BuilderException("Quilt returned non-zero exit code: {}".format( - result.returncode)) + gxx_compiler)) def build(self): if (self._sandbox_dir / pathlib.Path("third_party", "libc++-static", "libc++.a")).exists(): diff --git a/buildlib/windows.py b/buildlib/windows.py index c7bd41f5..ea0b5374 100644 --- a/buildlib/windows.py +++ b/buildlib/windows.py @@ -21,20 +21,17 @@ import pathlib import os -import subprocess import zipfile -from ._util import BuilderException -from .common import Builder, PATCHES, PATCH_ORDER, CPUArch +from .common import GNUPatchComponent, GYPMetaBuildComponent, CPUArch __all__ = ["WindowsBuilder"] -class WindowsBuilder(Builder): +class WindowsBuilder(GNUPatchComponent, GYPMetaBuildComponent): '''Builder for Windows''' _resources = pathlib.Path("resources", "windows") - patch_command = ["patch", "-p1"] python2_command = "python" use_depot_tools_toolchain = False target_arch = CPUArch.x86 @@ -55,30 +52,6 @@ class WindowsBuilder(Builder): self._files_cfg = (self._sandbox_dir / pathlib.Path("chrome", "tools", "build", "win", "FILES.cfg")) - def check_build_environment(self): - super(WindowsBuilder, self).check_build_environment() - - self.logger.info("Checking patch command...") - result = self._run_subprocess([self.patch_command[0], "--version"], stdout=subprocess.PIPE, - universal_newlines=True) - if not result.returncode is 0: - raise BuilderException("patch command returned non-zero exit code {}".format( - result.returncode)) - self.logger.debug("Using patch command '{!s}'".format(result.stdout.split("\n")[0])) - - def apply_patches(self): - self.logger.info("Applying patches via '{}' ...".format(" ".join(self.patch_command))) - self._generate_patches() - with (self.build_dir / PATCHES / PATCH_ORDER).open() as patch_order_file: - for i in [x for x in patch_order_file.read().splitlines() if len(x) > 0]: - self.logger.debug("Applying patch {} ...".format(i)) - with (self.build_dir / PATCHES / i).open("rb") as patch_file: - result = self._run_subprocess(self.patch_command, cwd=str(self._sandbox_dir), - stdin=patch_file) - if not result.returncode == 0: - raise BuilderException("'{}' returned non-zero exit code {}".format( - " ".join(self.patch_command), result.returncode)) - def generate_build_configuration(self): self.logger.info("Running gyp command...") if self.use_depot_tools_toolchain: