summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlexandru Croitor <alexandru.croitor@qt.io>2018-05-24 11:26:34 +0200
committerFriedemann Kleint <Friedemann.Kleint@qt.io>2018-05-31 07:32:46 +0000
commit15a8919455ed58c1c318770ba60feb2b7a000646 (patch)
tree16321d25de0977aff46db926a08673df70367aac
parent6b4155223ce1670ed630b0b8780187cfeeadb564 (diff)
Adjust wheel names when building with limited api
Wheel has poor support for naming wheel packages that were built with limited API enabled. We need to override some of bdist_wheel's methods to generate a correct name and correct metadata. Move the pyside_bdist_wheel class into a separate file, and implement the necessary logic. Change-Id: I23d814cbb794052fb18a1e018f7b767c60945254 Reviewed-by: Friedemann Kleint <Friedemann.Kleint@qt.io> Reviewed-by: Cristian Maureira-Fredes <cristian.maureira-fredes@qt.io>
-rw-r--r--build_scripts/main.py60
-rw-r--r--build_scripts/wheel_override.py186
-rw-r--r--setup.py6
3 files changed, 212 insertions, 40 deletions
diff --git a/build_scripts/main.py b/build_scripts/main.py
index f2774355..b2dbc546 100644
--- a/build_scripts/main.py
+++ b/build_scripts/main.py
@@ -73,6 +73,18 @@ def get_package_version():
final_version += ".dev{}".format(get_package_timestamp())
return final_version
+def get_setuptools_extension_modules():
+ # Setting py_limited_api on the extension is the "correct" thing
+ # to do, but it doesn't actually do anything, because we
+ # override build_ext. So this is just foolproofing for the
+ # future.
+ extension_args = ('QtCore', [])
+ extension_kwargs = {}
+ if OPTION_LIMITED_API:
+ extension_kwargs['py_limited_api'] = True
+ extension_modules = [Extension(*extension_args, **extension_kwargs)]
+ return extension_modules
+
# Buildable extensions.
contained_modules = ['shiboken2', 'pyside2', 'pyside2-tools']
@@ -113,19 +125,12 @@ from setuptools.command.bdist_egg import bdist_egg as _bdist_egg
from setuptools.command.develop import develop as _develop
from setuptools.command.build_py import build_py as _build_py
-wheel_module_exists = False
-try:
- from wheel.bdist_wheel import bdist_wheel as _bdist_wheel
- from wheel.bdist_wheel import safer_name as _safer_name
- wheel_module_exists = True
-except ImportError:
- pass
-
from .qtinfo import QtInfo
from .utils import rmtree, detect_clang, copyfile, copydir, run_process_output, run_process
from .utils import update_env_path, init_msvc_env, filter_match, macos_fix_rpaths_for_library
from .platforms.unix import prepare_packages_posix
from .platforms.windows_desktop import prepare_packages_win32
+from .wheel_override import wheel_module_exists, get_bdist_wheel_override
from textwrap import dedent
@@ -378,35 +383,7 @@ class PysideBuildExt(_build_ext):
def run(self):
pass
-if wheel_module_exists:
- class PysideBuildWheel(_bdist_wheel):
- def __init__(self, *args, **kwargs):
- _bdist_wheel.__init__(self, *args, **kwargs)
-
- @property
- def wheel_dist_name(self):
- # Slightly modified version of wheel's wheel_dist_name
- # method, to add the Qt version as well.
- # Example:
- # PySide2-5.6-5.6.4-cp27-cp27m-macosx_10_10_intel.whl
- # The PySide2 version is "5.6".
- # The Qt version built against is "5.6.4".
- qt_version = get_qt_version()
- package_version = get_package_version()
- wheel_version = "{}-{}".format(package_version, qt_version)
- components = (_safer_name(self.distribution.get_name()),
- wheel_version)
- if self.build_number:
- components += (self.build_number,)
- return '-'.join(components)
-
- def finalize_options(self):
- if sys.platform == 'darwin':
- # Override the platform name to contain the correct
- # minimum deployment target.
- # This is used in the final wheel name.
- self.plat_name = PysideBuild.macos_plat_name()
- _bdist_wheel.finalize_options(self)
+
# pyside_build_py and pyside_install_lib are reimplemented to preserve
# symlinks when distutils / setuptools copy files to various
@@ -1317,4 +1294,11 @@ cmd_class_dict = {
'install_lib': PysideInstallLib
}
if wheel_module_exists:
- cmd_class_dict['bdist_wheel'] = PysideBuildWheel
+ params = {}
+ params['qt_version'] = get_qt_version()
+ params['package_version'] = get_package_version()
+ if sys.platform == 'darwin':
+ params['macos_plat_name'] = PysideBuild.macos_plat_name()
+ pyside_bdist_wheel = get_bdist_wheel_override(params)
+ if pyside_bdist_wheel:
+ cmd_class_dict['bdist_wheel'] = pyside_bdist_wheel
diff --git a/build_scripts/wheel_override.py b/build_scripts/wheel_override.py
new file mode 100644
index 00000000..cb022099
--- /dev/null
+++ b/build_scripts/wheel_override.py
@@ -0,0 +1,186 @@
+#############################################################################
+##
+## Copyright (C) 2018 The Qt Company Ltd.
+## Contact: https://www.qt.io/licensing/
+##
+## This file is part of Qt for Python.
+##
+## $QT_BEGIN_LICENSE:LGPL$
+## Commercial License Usage
+## Licensees holding valid commercial Qt licenses may use this file in
+## accordance with the commercial license agreement provided with the
+## Software or, alternatively, in accordance with the terms contained in
+## a written agreement between you and The Qt Company. For licensing terms
+## and conditions see https://www.qt.io/terms-conditions. For further
+## information use the contact form at https://www.qt.io/contact-us.
+##
+## GNU Lesser General Public License Usage
+## Alternatively, this file may be used under the terms of the GNU Lesser
+## General Public License version 3 as published by the Free Software
+## Foundation and appearing in the file LICENSE.LGPL3 included in the
+## packaging of this file. Please review the following information to
+## ensure the GNU Lesser General Public License version 3 requirements
+## will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
+##
+## GNU General Public License Usage
+## Alternatively, this file may be used under the terms of the GNU
+## General Public License version 2.0 or (at your option) the GNU General
+## Public license version 3 or any later version approved by the KDE Free
+## Qt Foundation. The licenses are as published by the Free Software
+## Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
+## included in the packaging of this file. Please review the following
+## information to ensure the GNU General Public License requirements will
+## be met: https://www.gnu.org/licenses/gpl-2.0.html and
+## https://www.gnu.org/licenses/gpl-3.0.html.
+##
+## $QT_END_LICENSE$
+##
+#############################################################################
+
+
+wheel_module_exists = False
+
+try:
+ import os, sys
+
+ from distutils import log
+ from wheel import pep425tags
+ from wheel.bdist_wheel import bdist_wheel as _bdist_wheel
+ from wheel.bdist_wheel import safer_name as _safer_name
+ from wheel.pep425tags import get_abbr_impl, get_impl_ver, get_abi_tag
+ from wheel.pep425tags import get_platform as wheel_get_platform
+ from email.generator import Generator
+ from wheel import __version__ as wheel_version
+
+ from .options import *
+
+ wheel_module_exists = True
+except Exception as e:
+ print('***** Exception while trying to prepare bdist_wheel override class: {}. Skipping wheel overriding.'.format(e))
+
+def get_bdist_wheel_override(params):
+ if wheel_module_exists:
+ class PysideBuildWheelDecorated(PysideBuildWheel):
+ def __init__(self, *args, **kwargs):
+ self.params = params
+ PysideBuildWheel.__init__(self, *args, **kwargs)
+ return PysideBuildWheelDecorated
+ else:
+ return None
+
+if wheel_module_exists:
+ class PysideBuildWheel(_bdist_wheel):
+ def __init__(self, *args, **kwargs):
+ self.pyside_params = None
+ _bdist_wheel.__init__(self, *args, **kwargs)
+
+ @property
+ def wheel_dist_name(self):
+ # Slightly modified version of wheel's wheel_dist_name
+ # method, to add the Qt version as well.
+ # Example:
+ # PySide2-5.6-5.6.4-cp27-cp27m-macosx_10_10_intel.whl
+ # The PySide2 version is "5.6".
+ # The Qt version built against is "5.6.4".
+ qt_version = self.params['qt_version']
+ package_version = self.params['package_version']
+ wheel_version = "{}-{}".format(package_version, qt_version)
+ components = (_safer_name(self.distribution.get_name()),
+ wheel_version)
+ if self.build_number:
+ components += (self.build_number,)
+ return '-'.join(components)
+
+ # Copy of get_tag from bdist_wheel.py, to allow setting a
+ # multi-python impl tag, by removing an assert. Otherwise we
+ # would have to rename wheels manually for limited api
+ # packages. Also we set "none" abi tag on Windows, because
+ # pip does not yet support "abi3" tag, leading to
+ # installation failure when tried.
+ def get_tag(self):
+ # bdist sets self.plat_name if unset, we should only use
+ # it for purepy wheels if the user supplied it.
+ if self.plat_name_supplied:
+ plat_name = self.plat_name
+ elif self.root_is_pure:
+ plat_name = 'any'
+ else:
+ plat_name = self.plat_name or wheel_get_platform()
+ if plat_name in ('linux-x86_64', 'linux_x86_64') and sys.maxsize == 2147483647:
+ plat_name = 'linux_i686'
+ plat_name = plat_name.replace('-', '_').replace('.', '_')
+
+ if self.root_is_pure:
+ if self.universal:
+ impl = 'py2.py3'
+ else:
+ impl = self.python_tag
+ tag = (impl, 'none', plat_name)
+ else:
+ impl_name = get_abbr_impl()
+ impl_ver = get_impl_ver()
+ impl = impl_name + impl_ver
+ # We don't work on CPython 3.1, 3.0.
+ if self.py_limited_api and (impl_name + impl_ver).startswith('cp3'):
+ impl = self.py_limited_api
+ if sys.platform == "win32":
+ abi_tag = 'none'
+ else:
+ abi_tag = 'abi3'
+ else:
+ abi_tag = str(get_abi_tag()).lower()
+ tag = (impl, abi_tag, plat_name)
+ supported_tags = pep425tags.get_supported(
+ supplied_platform=plat_name if self.plat_name_supplied else None)
+ # XXX switch to this alternate implementation for
+ # non-pure:
+ if not self.py_limited_api:
+ assert tag == supported_tags[0], "%s != %s" % (tag, supported_tags[0])
+ assert tag in supported_tags, \
+ "would build wheel with unsupported tag {}".format(tag)
+ return tag
+
+ # Copy of get_tag from bdist_wheel.py, to write a triplet Tag
+ # only once for the limited_api case.
+ def write_wheelfile(self, wheelfile_base, generator='bdist_wheel (' + wheel_version + ')'):
+ from email.message import Message
+ msg = Message()
+ msg['Wheel-Version'] = '1.0' # of the spec
+ msg['Generator'] = generator
+ msg['Root-Is-Purelib'] = str(self.root_is_pure).lower()
+ if self.build_number is not None:
+ msg['Build'] = self.build_number
+
+ # Doesn't work for bdist_wininst
+ impl_tag, abi_tag, plat_tag = self.get_tag()
+ limited_api_enabled = OPTION_LIMITED_API and sys.version_info[0] >= 3
+
+ def writeTag(impl):
+ for abi in abi_tag.split('.'):
+ for plat in plat_tag.split('.'):
+ msg['Tag'] = '-'.join((impl, abi, plat))
+ if limited_api_enabled:
+ writeTag(impl_tag)
+ else:
+ for impl in impl_tag.split('.'):
+ writeTag(impl)
+
+ wheelfile_path = os.path.join(wheelfile_base, 'WHEEL')
+ log.info('creating %s', wheelfile_path)
+ with open(wheelfile_path, 'w') as f:
+ Generator(f, maxheaderlen=0).flatten(msg)
+
+ def finalize_options(self):
+ if sys.platform == 'darwin':
+ # Override the platform name to contain the correct
+ # minimum deployment target.
+ # This is used in the final wheel name.
+ self.plat_name = self.params['macos_plat_name']
+
+ # When limited API is requested, notify bdist_wheel to
+ # create a properly named package.
+ limited_api_enabled = OPTION_LIMITED_API and sys.version_info[0] >= 3
+ if limited_api_enabled:
+ self.py_limited_api = "cp35.cp36.cp37.cp38"
+
+ _bdist_wheel.finalize_options(self)
diff --git a/setup.py b/setup.py
index 60b86adc..ca26084d 100644
--- a/setup.py
+++ b/setup.py
@@ -219,7 +219,7 @@ this_file = os.path.abspath(this_file)
if os.path.dirname(this_file):
os.chdir(os.path.dirname(this_file))
-from build_scripts.main import get_package_version
+from build_scripts.main import get_package_version, get_setuptools_extension_modules
from build_scripts.main import pyside_package_dir_name
from build_scripts.main import cmd_class_dict
from build_scripts.main import README, CHANGES
@@ -229,6 +229,8 @@ from setuptools import setup, Extension
# used as a value source.
__version__ = get_package_version()
+extension_modules = get_setuptools_extension_modules()
+
setup(
name = "PySide2",
version = get_package_version(),
@@ -286,6 +288,6 @@ setup(
# are overriding the build command to do it using cmake) so things
# like bdist_egg will know that there are extension modules and
# will name the dist with the full platform info.
- ext_modules = [Extension('QtCore', [])],
+ ext_modules = extension_modules,
ext_package = 'PySide2',
)