| # Copyright 2017 The Chromium Authors. All rights reserved. |
| # Use of this source code is governed by a BSD-style license that can be |
| # found in the LICENSE file. |
| |
| from . import build_platform |
| from . import source |
| from . import util |
| |
| from .builder import Builder, BuildPackageFromPyPiWheel, BuildPackageFromSource |
| |
| from .build_types import Spec |
| |
| |
| class ConditionalWheel(Builder): |
| """Builds a wheel selected based on different conditions. |
| |
| ConditionalWheel can help user select wheel based on platform without |
| match_tag |
| |
| Args: |
| name (str): The name of the conditional wheel. |
| version (str): The conditional wheel version. Note there is no |
| patch_version for ConditionalWheel, as the bundle wheel version |
| can be set to any value we like. |
| select_fn (Callable[[System, Wheel], Wheel]): A function select the wheel |
| to be built. |
| pyversions (iterable or None): The list of "python" wheel fields (see |
| "Wheel.pyversion_str"). If None, a default Python version will be |
| used. |
| default (bool): If true, the wheel will be built by default. |
| only_plat: (See Builder's "only_plat" argument.) |
| skip_plat: (See Builder's "skip_plat" argument.) |
| patch_version (str or None): If set, this string is appended to the CIPD |
| version tag, for example if set to 'chromium.1', the version tag |
| for version 1.2.3 of the wheel would be 'version:1.2.3.chromium.1'. |
| """ |
| |
| def __init__(self, |
| name, |
| version, |
| select_fn, |
| pyversions=None, |
| only_plat=None, |
| skip_plat=None, |
| default=True, |
| patch_version=None): |
| self._select_fn = select_fn |
| version_suffix = '.' + patch_version if patch_version else None |
| super(ConditionalWheel, self).__init__( |
| Spec( |
| name, |
| version, |
| universal=False, |
| pyversions=pyversions, |
| default=default, |
| version_suffix=version_suffix), |
| only_plat=only_plat, |
| skip_plat=skip_plat) |
| |
| def build_fn(self, system, wheel, output_dir): |
| b = self._select_fn(system, wheel) |
| w = b.wheel(system, wheel.plat) |
| return b.build_wheel(w, system, output_dir, rebuild=True) |
| |
| |
| class SourceOrPrebuilt(Builder): |
| |
| def __init__(self, |
| name, |
| version, |
| pyversions=None, |
| default=True, |
| patches=(), |
| patch_base=None, |
| patch_version=None, |
| build_deps=None, |
| tpp_libs_cb=None, |
| tpp_tools=None, |
| src_filter=None, |
| skip_auditwheel=False, |
| **kwargs): |
| """General-purpose wheel builder. |
| |
| If the wheel is "packaged" (see arg for description), it is expected that it |
| is resident in PyPi and will be downloaded; otherwise, it will be built from |
| source. |
| |
| Args: |
| name (str): The wheel name. |
| version (str): The wheel version. |
| pyversions (iterable or None): The list of "python" wheel fields (see |
| "Wheel.pyversion_str"). If None, a default Python version will be |
| used. |
| default (bool): If true, the wheel will be built by default. |
| patches (tuple): Short patch names to apply to the source tree. |
| patch_base (str or None): Optionally override the base names for patches. |
| patch_version (str or None): If set, this string is appended to the CIPD |
| version tag, for example if set to 'chromium.1', the version tag |
| for version 1.2.3 of the wheel would be 'version:1.2.3.chromium.1'. |
| build_deps (dockerbuild.builder.BuildDependencies|None): Dependencies |
| required to build the wheel. |
| tpp_libs_cb (Callable[[Wheel], List[builder.TppLib]]|None): Callback that |
| returns 3pp libraries to install in the build environment. |
| tpp_tools (List[builder.TppTool]|None): 3pp tools (for the build platform) |
| which are needed to build the wheel. |
| src_filter (Callable[[str], bool]): Filtering files from the source. This |
| is a workaround for python < 3.6 on Windows to prevent failure caused |
| by 260 path length limit. |
| skip_auditwheel (bool): If True, do not run 'auditwheel' tool to fix up |
| manylinux wheel library dependencies. This option may be necessary |
| if the generated wheel does not contain any compiled code, since |
| this causes a hard error from auditwheel. |
| packaged (iterable or None): The names of platforms that have this wheel |
| available via PyPi. If None, a default set of packaged wheels will be |
| generated based on standard PyPi expectations, encoded with each |
| Platform's "packaged" property. |
| env_cb (Callable[[Wheel], Dict[str, str]]|None): Envvars to set when |
| building the wheel from source. The Wheel object is received as an |
| argument. |
| kwargs: Keyword arguments forwarded to Builder. |
| """ |
| self._pypi_src = source.pypi_sdist( |
| name, version, patches=patches, patch_base=patch_base) |
| self._packaged = set( |
| kwargs.pop('packaged', (p.name for p in build_platform.PACKAGED))) |
| self._build_deps = build_deps |
| self._tpp_libs_cb = tpp_libs_cb |
| self._tpp_tools = tpp_tools |
| self._src_filter = src_filter |
| self._skip_auditwheel = skip_auditwheel |
| self._env_cb = kwargs.pop('env_cb', None) |
| version_suffix = '.' + patch_version if patch_version else None |
| spec = Spec( |
| name, |
| self._pypi_src.version, |
| universal=False, |
| pyversions=pyversions, |
| default=default, |
| version_suffix=version_suffix) |
| |
| for p in self._packaged: |
| assert p in build_platform.NAMES, ( |
| "Wheel %r has invalid platform %s in packaged" % (spec, p)) |
| |
| super(SourceOrPrebuilt, self).__init__(spec, **kwargs) |
| |
| def build_fn(self, system, wheel, output_dir): |
| if wheel.plat.name in self._packaged: |
| return BuildPackageFromPyPiWheel(system, wheel, output_dir) |
| wheel_env = self._env_cb(wheel) if self._env_cb else None |
| tpp_libs = self._tpp_libs_cb(wheel) if self._tpp_libs_cb else None |
| return BuildPackageFromSource(system, wheel, self._pypi_src, output_dir, |
| self._src_filter, self._build_deps, tpp_libs, |
| self._tpp_tools, wheel_env, |
| self._skip_auditwheel) |
| |
| |
| class MultiWheel(Builder): |
| |
| def __init__(self, |
| name, |
| version, |
| wheels, |
| pyversions=None, |
| only_plat=None, |
| skip_plat=None, |
| default=True, |
| patch_version=None): |
| """Builds a wheel consisting of multiple other wheels. |
| |
| Bundles can be useful when a user always wants a common set of packages. |
| |
| Args: |
| name (str): The name of the bundle wheel. |
| version (str): The bundle wheel version. Note there is no patch_version |
| for MultiWheels, as the bundle wheel version can be set to any value |
| we like. |
| wheels (iterable): A set of embedded wheel rules to add to the bundle. |
| pyversions (iterable or None): The list of "python" wheel fields (see |
| "Wheel.pyversion_str"). If None, a default Python version will be |
| used. |
| default (bool): If true, the wheel will be built by default. |
| only_plat: (See Builder's "only_plat" argument.) |
| skip_plat: (See Builder's "skip_plat" argument.) |
| patch_version (str or None): If set, this string is appended to the CIPD |
| version tag, for example if set to 'chromium.1', the version tag |
| for version 1.2.3 of the wheel would be 'version:1.2.3.chromium.1'. |
| """ |
| self._wheels = wheels |
| version_suffix = '.' + patch_version if patch_version else None |
| super(MultiWheel, self).__init__( |
| Spec( |
| name, |
| version, |
| universal=False, |
| pyversions=pyversions, |
| default=default, |
| version_suffix=version_suffix), |
| only_plat=only_plat, |
| skip_plat=skip_plat) |
| |
| def build_fn(self, system, wheel, output_dir): |
| sub_wheels = [] |
| for w in self._wheels: |
| subwheel_plat = ( |
| build_platform.ALL[build_platform.UNIVERSAL[0]] |
| if w.spec.universal else wheel.plat) |
| sub_wheel = w.wheel(system, subwheel_plat) |
| util.LOGGER.info('Building sub-wheel: %s', sub_wheel) |
| # Any time the MultiWheel is built, rebuild all the subwheels. |
| sub_wheels += w.build_wheel(sub_wheel, system, output_dir, rebuild=True) |
| return sub_wheels |
| |
| |
| class Prebuilt(Builder): |
| """Wheel builder for prepared wheels that must be downloaded from PyPi. |
| |
| Args: |
| name (str): The wheel name. |
| version (str): The wheel version. |
| only_plat: (See Builder's "only_plat" argument.) |
| pyversions (iterable or None): The list of "python" wheel fields (see |
| "Wheel.pyversion_str"). If None, a default Python version will be |
| used. |
| default (bool): If true, the wheel will be built by default. |
| kwargs: Keyword arguments forwarded to Builder. |
| """ |
| |
| def __init__(self, |
| name, |
| version, |
| only_plat, |
| pyversions=None, |
| default=True, |
| **kwargs): |
| kwargs['only_plat'] = only_plat |
| super(Prebuilt, self).__init__( |
| Spec( |
| name, |
| version, |
| universal=False, |
| pyversions=pyversions, |
| default=default, |
| version_suffix=None), **kwargs) |
| |
| def build_fn(self, system, wheel, output_dir): |
| return BuildPackageFromPyPiWheel(system, wheel, output_dir) |
| |
| |
| class Universal(Builder): |
| |
| def __init__(self, name, version, pyversions=None, default=True, **kwargs): |
| """Universal wheel version of SourceOrPrebuilt. |
| |
| Args: |
| name (str): The wheel name. |
| version (str): The wheel version. |
| pyversions (iterable or None): The list of "python" wheel fields (see |
| "Wheel.pyversion_str"). If None, a default Python version will be |
| used. |
| kwargs: Keyword arguments forwarded to Builder. |
| """ |
| super(Universal, self).__init__( |
| Spec( |
| name, |
| version, |
| universal=True, |
| pyversions=pyversions, |
| default=default, |
| version_suffix=None, |
| ), **kwargs) |
| |
| def build_fn(self, system, wheel, output_dir): |
| return BuildPackageFromPyPiWheel(system, wheel, output_dir) |
| |
| |
| class UniversalSource(Builder): |
| |
| def __init__(self, |
| name, |
| pypi_version, |
| pyversions=None, |
| pypi_name=None, |
| patches=(), |
| patch_base=None, |
| patch_version=None, |
| **kwargs): |
| """Universal wheel version of SourceOrPrebuilt that always builds from |
| source. |
| |
| Args: |
| name (str): The wheel name. |
| version (str): The wheel version. |
| pyversions (iterable or None): The list of "python" wheel fields (see |
| "Wheel.pyversion_str"). If None, a default Python version will be |
| used. |
| pypi_name (str or None): Name of the package in PyPi. This can be useful |
| when translating between the CIPD package name (uses underscores) and |
| the PyPi package name (may use hyphens). |
| patches (tuple): Short patch names to apply to the source tree. |
| patch_base (str or None): Optionally override the base name for patches. |
| patch_version (str or None): If set, this string is appended to the CIPD |
| version tag, for example if set to 'chromium.1', the version tag |
| for version 1.2.3 of the wheel would be 'version:1.2.3.chromium.1'. |
| May not be used in combination with 'patches', since 'patches' |
| already appends a hash of the patches to the version. |
| kwargs: Keyword arguments forwarded to Builder. |
| |
| Returns (Builder): A configured Builder for the specified wheel. |
| """ |
| self._pypi_src = source.pypi_sdist( |
| name=pypi_name or name, |
| version=pypi_version, |
| patches=patches, |
| patch_base=patch_base) |
| if patches: |
| if patch_version: |
| raise ValueError('patches and patch_version may not be used together.') |
| # For backward compatibility. |
| version_suffix = '-' + self._pypi_src.patches_hash |
| elif patch_version: |
| version_suffix = '.' + patch_version |
| else: |
| version_suffix = None |
| super(UniversalSource, self).__init__( |
| Spec( |
| name, |
| self._pypi_src.version, |
| universal=True, |
| pyversions=pyversions, |
| default=True, |
| version_suffix=version_suffix, |
| ), **kwargs) |
| |
| def build_fn(self, system, wheel, output_dir): |
| return BuildPackageFromSource(system, wheel, self._pypi_src, output_dir) |
| |
| def md_data_fn(self): |
| if not self._pypi_src.patches: |
| return [] |
| |
| return ['\n* custom patches: %s' % (', '.join(self._pypi_src.patches),)] |
| |
| |
| class GitUniversalSource(Builder): |
| |
| def __init__(self, |
| name, |
| version, |
| git_repo, |
| git_commit, |
| setup_path='', |
| **kwargs): |
| """Version of UniversalSource that always builds a Universal wheel |
| from a git repo source rather than pypi.org. |
| |
| Args: |
| name (str): The wheel name. |
| version (str): The wheel version. |
| git_repo (str): The git repository to fetch. |
| git_commit (str): The commit or tag to fetch. |
| setup_path (str): The repository-relative path to setup.py. |
| kwargs: Keyword arguments forwarded to Builder. |
| |
| Returns (Builder): A configured Builder for the specified wheel. |
| """ |
| self._git_repo = git_repo |
| self._git_commit = git_commit |
| self._setup_path = setup_path |
| super(GitUniversalSource, self).__init__( |
| Spec( |
| name, |
| version, |
| universal=True, |
| pyversions=['py3'], |
| default=True, |
| version_suffix=None, |
| ), **kwargs) |
| |
| def build_fn(self, system, wheel, output_dir): |
| return BuildPackageFromSource( |
| system, wheel, |
| source.git_source( |
| self.spec.name, self.spec.version, |
| source.GitSource(system, self._git_repo, self._git_commit, |
| self._setup_path, self.spec.name)), output_dir) |