aboutsummaryrefslogtreecommitdiffstats
path: root/build_scripts
diff options
context:
space:
mode:
authorFriedemann Kleint <Friedemann.Kleint@qt.io>2020-10-08 14:21:19 +0200
committerFriedemann Kleint <Friedemann.Kleint@qt.io>2020-10-08 14:21:19 +0200
commit00fa3966dbed373e341710f1145fd23a88f1bdb0 (patch)
tree331be762988f22221b40ed93486b9b05b657f0bd /build_scripts
parente801fdab20ad4f5f47deaf49600af0d5f02ecc51 (diff)
parent2ed45ce8991408de91d7e02a2b80a09a2d9e5083 (diff)
Merge remote-tracking branch 'origin/5.15' into dev
Diffstat (limited to 'build_scripts')
-rw-r--r--build_scripts/build_scripts.pyproject2
-rw-r--r--build_scripts/config.py1
-rw-r--r--build_scripts/main.py449
-rw-r--r--build_scripts/qp5_tool.py2
-rw-r--r--build_scripts/qtinfo.py2
-rw-r--r--build_scripts/setup_runner.py1
-rw-r--r--build_scripts/utils.py16
-rw-r--r--build_scripts/wheel_override.py22
-rw-r--r--build_scripts/wheel_utils.py162
9 files changed, 353 insertions, 304 deletions
diff --git a/build_scripts/build_scripts.pyproject b/build_scripts/build_scripts.pyproject
index 604419c10..80df4d386 100644
--- a/build_scripts/build_scripts.pyproject
+++ b/build_scripts/build_scripts.pyproject
@@ -1,6 +1,6 @@
{
"files": ["main.py", "__init__.py", "config.py", "options.py", "qtinfo.py",
- "setup_runner.py", "utils.py", "wheel_override.py",
+ "setup_runner.py", "utils.py", "wheel_override.py", "wheel_utils.py",
"platforms/__init__.py", "platforms/linux.py",
"platforms/macos.py", "platforms/unix.py",
"platforms/windows_desktop.py",
diff --git a/build_scripts/config.py b/build_scripts/config.py
index 0a6c3bbb2..86482a043 100644
--- a/build_scripts/config.py
+++ b/build_scripts/config.py
@@ -137,7 +137,6 @@ class Config(object):
setup_kwargs['version'] = package_version
setup_kwargs['python_requires'] = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, <3.10"
-
if quiet:
# Tells distutils / setuptools to be quiet, and only print warnings or errors.
# Makes way less noise in the terminal when building.
diff --git a/build_scripts/main.py b/build_scripts/main.py
index c0fa16a51..8429c1fdb 100644
--- a/build_scripts/main.py
+++ b/build_scripts/main.py
@@ -41,10 +41,17 @@ from __future__ import print_function
from distutils.version import LooseVersion
import os
+import platform
+import re
+import sys
+from textwrap import dedent
import time
from .config import config
-from .utils import memoize, get_python_dict
+from .utils import get_python_dict
from .options import OPTION
+from .wheel_utils import (get_package_version, get_qt_version,
+ get_package_timestamp, macos_plat_name,
+ macos_pyside_min_deployment_target)
setup_script_dir = os.getcwd()
build_scripts_dir = os.path.join(setup_script_dir, 'build_scripts')
@@ -57,37 +64,6 @@ def elapsed():
return int(time.time()) - start_time
-@memoize
-def get_package_timestamp():
- """ In a Coin CI build the returned timestamp will be the
- Coin integration id timestamp. For regular builds it's
- just the current timestamp or a user provided one."""
- return OPTION["PACKAGE_TIMESTAMP"] if OPTION["PACKAGE_TIMESTAMP"] else start_time
-
-
-@memoize
-def get_package_version():
- """ Returns the version string for the PySide2 package. """
- pyside_version_py = os.path.join(
- setup_script_dir, "sources", "pyside2", "pyside_version.py")
- d = get_python_dict(pyside_version_py)
-
- final_version = "{}.{}.{}".format(
- d['major_version'], d['minor_version'], d['patch_version'])
- release_version_type = d['release_version_type']
- pre_release_version = d['pre_release_version']
- if pre_release_version and release_version_type:
- final_version += release_version_type + pre_release_version
- if release_version_type.startswith("comm"):
- final_version += "." + release_version_type
-
- # Add the current timestamp to the version number, to suggest it
- # is a development snapshot build.
- if OPTION["SNAPSHOT_BUILD"]:
- 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
@@ -101,16 +77,162 @@ def get_setuptools_extension_modules():
return extension_modules
+def _get_make(platform_arch, build_type):
+ """Helper for retrieving the make command and CMake generator name"""
+ makespec = OPTION["MAKESPEC"]
+ if makespec == "make":
+ return ("make", "Unix Makefiles")
+ if makespec == "msvc":
+ nmake_path = find_executable("nmake")
+ if nmake_path is None or not os.path.exists(nmake_path):
+ log.info("nmake not found. Trying to initialize the MSVC env...")
+ init_msvc_env(platform_arch, build_type)
+ nmake_path = find_executable("nmake")
+ if not nmake_path or not os.path.exists(nmake_path):
+ raise DistutilsSetupError('"nmake" could not be found.')
+ if not OPTION["NO_JOM"]:
+ jom_path = find_executable("jom")
+ if jom_path:
+ log.info("jom was found in {}".format(jom_path))
+ return (jom_path, "NMake Makefiles JOM")
+ log.info("nmake was found in {}".format(nmake_path))
+ if OPTION["JOBS"]:
+ msg = "Option --jobs can only be used with 'jom' on Windows."
+ raise DistutilsSetupError(msg)
+ return (nmake_path, "NMake Makefiles")
+ if makespec == "mingw":
+ return ("mingw32-make", "mingw32-make")
+ if makespec == "ninja":
+ return ("ninja", "Ninja")
+ m = 'Invalid option --make-spec "{}".'.format(makespec)
+ raise DistutilsSetupError(m)
+
+
+def get_make(platform_arch, build_type):
+ """Retrieve the make command and CMake generator name"""
+ (make_path, make_generator) = _get_make(platform_arch, build_type)
+ if not os.path.isabs(make_path):
+ make_path = find_executable(make_path)
+ if not make_path or not os.path.exists(make_path):
+ raise DistutilsSetupError("You need the program '{}' on your system path to "
+ "compile PySide2.".format(make_path))
+ return (make_path, make_generator)
+
+
+def _get_py_library_win(build_type, py_version, py_prefix, py_libdir,
+ py_include_dir):
+ """Helper for finding the Python library on Windows"""
+ if py_include_dir is None or not os.path.exists(py_include_dir):
+ py_include_dir = os.path.join(py_prefix, "include")
+ if py_libdir is None or not os.path.exists(py_libdir):
+ # For virtual environments on Windows, the py_prefix will contain a
+ # path pointing to it, instead of the system Python installation path.
+ # Since INCLUDEPY contains a path to the system location, we use the
+ # same base directory to define the py_libdir variable.
+ py_libdir = os.path.join(os.path.dirname(py_include_dir), "libs")
+ if not os.path.isdir(py_libdir):
+ raise DistutilsSetupError("Failed to locate the 'libs' directory")
+ dbg_postfix = "_d" if build_type == "Debug" else ""
+ if OPTION["MAKESPEC"] == "mingw":
+ static_lib_name = "libpython{}{}.a".format(
+ py_version.replace(".", ""), dbg_postfix)
+ return os.path.join(py_libdir, static_lib_name)
+ v = py_version.replace(".", "")
+ python_lib_name = "python{}{}.lib".format(v, dbg_postfix)
+ return os.path.join(py_libdir, python_lib_name)
+
+
+def _get_py_library_unix(build_type, py_version, py_prefix, py_libdir,
+ py_include_dir):
+ """Helper for finding the Python library on UNIX"""
+ if py_libdir is None or not os.path.exists(py_libdir):
+ py_libdir = os.path.join(py_prefix, "lib")
+ if py_include_dir is None or not os.path.exists(py_include_dir):
+ dir = "include/python{}".format(py_version)
+ py_include_dir = os.path.join(py_prefix, dir)
+ dbg_postfix = "_d" if build_type == "Debug" else ""
+ lib_exts = ['.so']
+ if sys.platform == 'darwin':
+ lib_exts.append('.dylib')
+ if sys.version_info[0] > 2:
+ lib_suff = getattr(sys, 'abiflags', None)
+ else: # Python 2
+ lib_suff = ''
+ lib_exts.append('.so.1')
+ # Suffix for OpenSuSE 13.01
+ lib_exts.append('.so.1.0')
+ # static library as last gasp
+ lib_exts.append('.a')
+
+ if sys.version_info[0] == 2 and dbg_postfix:
+ # For Python2 add a duplicate set of extensions combined with the
+ # dbg_postfix, so we test for both the debug version of the lib
+ # and the normal one. This allows a debug PySide2 to be built with a
+ # non-debug Python.
+ lib_exts = [dbg_postfix + e for e in lib_exts] + lib_exts
+
+ libs_tried = []
+ for lib_ext in lib_exts:
+ lib_name = "libpython{}{}{}".format(py_version, lib_suff, lib_ext)
+ py_library = os.path.join(py_libdir, lib_name)
+ if os.path.exists(py_library):
+ return py_library
+ libs_tried.append(py_library)
+ # At least on macOS 10.11, the system Python 2.6 does not include a
+ # symlink to the framework file disguised as a .dylib file, thus finding
+ # the library would fail. Manually check if a framework file "Python"
+ # exists in the Python framework bundle.
+ if sys.platform == 'darwin' and sys.version_info[:2] == (2, 6):
+ # These manipulations essentially transform
+ # /System/Library/Frameworks/Python.framework/Versions/2.6/lib
+ # to
+ # /System/Library/Frameworks/Python.framework/Versions/2.6/Python
+ possible_framework_path = os.path.realpath(os.path.join(py_libdir, '..'))
+ possible_framework_version = os.path.basename(possible_framework_path)
+ possible_framework_library = os.path.join(possible_framework_path, 'Python')
+
+ if (possible_framework_version == '2.6'
+ and os.path.exists(possible_framework_library)):
+ return possible_framework_library
+ libs_tried.append(possible_framework_library)
+
+ # Try to find shared libraries which have a multi arch
+ # suffix.
+ py_multiarch = get_config_var("MULTIARCH")
+ if py_multiarch:
+ try_py_libdir = os.path.join(py_libdir, py_multiarch)
+ libs_tried = []
+ for lib_ext in lib_exts:
+ lib_name = "libpython{}{}{}".format(py_version, lib_suff, lib_ext)
+ py_library = os.path.join(try_py_libdir, lib_name)
+ if os.path.exists(py_library):
+ return py_library
+ libs_tried.append(py_library)
+
+ m = "Failed to locate the Python library with {}".format(", ".join(libs_tried))
+ raise DistutilsSetupError(m)
+
+
+def get_py_library(build_type, py_version, py_prefix, py_libdir, py_include_dir):
+ """Find the Python library"""
+ if sys.platform == "win32":
+ py_library = _get_py_library_win(build_type, py_version, py_prefix,
+ py_libdir, py_include_dir)
+ else:
+ py_library = _get_py_library_unix(build_type, py_version, py_prefix,
+ py_libdir, py_include_dir)
+ if py_library.endswith('.a'):
+ # Python was compiled as a static library
+ log.error("Failed to locate a dynamic Python library, using {}".format(py_library))
+ return py_library
+
+
try:
import setuptools
except ImportError:
from ez_setup import use_setuptools
use_setuptools()
-import sys
-import platform
-import re
-
import distutils.log as log
from distutils.errors import DistutilsSetupError
from distutils.sysconfig import get_config_var
@@ -137,8 +259,6 @@ 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
-
def check_allowed_python_version():
"""
@@ -243,21 +363,6 @@ qtinfo = QtInfo()
qtinfo.setup(OPTION["QMAKE"], OPTION["QT_VERSION"])
-def get_qt_version():
- qt_version = qtinfo.version
-
- if not qt_version:
- log.error("Failed to query the Qt version with qmake {0}".format(qtinfo.qmake_command))
- sys.exit(1)
-
- if LooseVersion(qtinfo.version) < LooseVersion("5.7"):
- log.error("Incompatible Qt version detected: {}. A Qt version >= 5.7 is "
- "required.".format(qt_version))
- sys.exit(1)
-
- return qt_version
-
-
def prepare_build():
# Clean up temp build folder.
for n in ["build"]:
@@ -374,7 +479,7 @@ class PysideBuild(_build):
def finalize_options(self):
os_name_backup = os.name
if sys.platform == 'darwin':
- self.plat_name = PysideBuild.macos_plat_name()
+ self.plat_name = macos_plat_name()
# This is a hack to circumvent the dubious check in
# distutils.commands.build -> finalize_options, which only
# allows setting the plat_name for windows NT.
@@ -421,49 +526,7 @@ class PysideBuild(_build):
make_path = None
make_generator = None
if not OPTION["ONLYPACKAGE"]:
- if OPTION["MAKESPEC"] == "make":
- make_name = "make"
- make_generator = "Unix Makefiles"
- elif OPTION["MAKESPEC"] == "msvc":
- nmake_path = find_executable("nmake")
- if nmake_path is None or not os.path.exists(nmake_path):
- log.info("nmake not found. Trying to initialize the MSVC env...")
- init_msvc_env(platform_arch, build_type)
- nmake_path = find_executable("nmake")
- assert(nmake_path is not None and os.path.exists(nmake_path))
- jom_path = None if OPTION["NO_JOM"] else find_executable("jom")
- if jom_path is not None and os.path.exists(jom_path):
- log.info("jom was found in {}".format(jom_path))
- make_name = "jom"
- make_generator = "NMake Makefiles JOM"
- else:
- log.info("nmake was found in {}".format(nmake_path))
- make_name = "nmake"
- make_generator = "NMake Makefiles"
- if OPTION["JOBS"]:
- msg = "Option --jobs can only be used with 'jom' on Windows."
- raise DistutilsSetupError(msg)
- elif OPTION["MAKESPEC"] == "mingw":
- make_name = "mingw32-make"
- make_generator = "MinGW Makefiles"
- elif OPTION["MAKESPEC"] == "ninja":
- make_name = "ninja"
- make_generator = "Ninja"
- else:
- raise DistutilsSetupError("Invalid option --make-spec.")
- make_path = find_executable(make_name)
- if make_path is None or not os.path.exists(make_path):
- raise DistutilsSetupError("You need the program '{}' on your system path to "
- "compile PySide2.".format(make_name))
-
- if OPTION["CMAKE"] is None or not os.path.exists(OPTION["CMAKE"]):
- raise DistutilsSetupError("Failed to find cmake."
- " Please specify the path to cmake with "
- "--cmake parameter.")
-
- if OPTION["QMAKE"] is None or not os.path.exists(OPTION["QMAKE"]):
- raise DistutilsSetupError("Failed to find qmake. "
- "Please specify the path to qmake with --qmake parameter.")
+ (make_path, make_generator) = get_make(platform_arch, build_type)
# Prepare parameters
py_executable = sys.executable
@@ -479,111 +542,6 @@ class PysideBuild(_build):
else:
py_scripts_dir = os.path.join(py_prefix, "bin")
self.py_scripts_dir = py_scripts_dir
- if py_libdir is None or not os.path.exists(py_libdir):
- if sys.platform == "win32":
- # For virtual environments on Windows, the py_prefix will contain a path pointing
- # to it, instead of the system Python installation path.
- # Since INCLUDEPY contains a path to the system location, we use the same base
- # directory to define the py_libdir variable.
- py_libdir = os.path.join(os.path.dirname(py_include_dir), "libs")
- if not os.path.isdir(py_libdir):
- raise DistutilsSetupError("Failed to locate the 'libs' directory")
- else:
- py_libdir = os.path.join(py_prefix, "lib")
- if py_include_dir is None or not os.path.exists(py_include_dir):
- if sys.platform == "win32":
- py_include_dir = os.path.join(py_prefix, "include")
- else:
- py_include_dir = os.path.join(py_prefix, "include/python{}".format(py_version))
- dbg_postfix = ""
- if build_type == "Debug":
- dbg_postfix = "_d"
- if sys.platform == "win32":
- if OPTION["MAKESPEC"] == "mingw":
- static_lib_name = "libpython{}{}.a".format(
- py_version.replace(".", ""), dbg_postfix)
- py_library = os.path.join(py_libdir, static_lib_name)
- else:
- python_lib_name = "python{}{}.lib".format(
- py_version.replace(".", ""), dbg_postfix)
- py_library = os.path.join(py_libdir, python_lib_name)
- else:
- lib_exts = ['.so']
- if sys.platform == 'darwin':
- lib_exts.append('.dylib')
- if sys.version_info[0] > 2:
- lib_suff = getattr(sys, 'abiflags', None)
- else: # Python 2
- lib_suff = ''
- lib_exts.append('.so.1')
- # Suffix for OpenSuSE 13.01
- lib_exts.append('.so.1.0')
- # static library as last gasp
- lib_exts.append('.a')
-
- if sys.version_info[0] == 2 and dbg_postfix:
- # For Python2 add a duplicate set of extensions
- # combined with the dbg_postfix, so we test for both the
- # debug version of the lib and the normal one.
- # This allows a debug PySide2 to be built with a
- # non-debug Python.
- lib_exts = [dbg_postfix + e for e in lib_exts] + lib_exts
-
- python_library_found = False
- libs_tried = []
- for lib_ext in lib_exts:
- lib_name = "libpython{}{}{}".format(py_version, lib_suff, lib_ext)
- py_library = os.path.join(py_libdir, lib_name)
- if os.path.exists(py_library):
- python_library_found = True
- break
- libs_tried.append(py_library)
- else:
- # At least on macOS 10.11, the system Python 2.6 does
- # not include a symlink to the framework file disguised
- # as a .dylib file, thus finding the library would
- # fail.
- # Manually check if a framework file "Python" exists in
- # the Python framework bundle.
- if sys.platform == 'darwin' and sys.version_info[:2] == (2, 6):
- # These manipulations essentially transform
- # /System/Library/Frameworks/Python.framework/Versions/2.6/lib
- # to
- # /System/Library/Frameworks/Python.framework/Versions/2.6/Python
- possible_framework_path = os.path.realpath(os.path.join(py_libdir, '..'))
- possible_framework_version = os.path.basename(possible_framework_path)
- possible_framework_library = os.path.join(possible_framework_path, 'Python')
-
- if (possible_framework_version == '2.6'
- and os.path.exists(possible_framework_library)):
- py_library = possible_framework_library
- python_library_found = True
- else:
- libs_tried.append(possible_framework_library)
-
- # Try to find shared libraries which have a multi arch
- # suffix.
- if not python_library_found:
- py_multiarch = get_config_var("MULTIARCH")
- if py_multiarch and not python_library_found:
- try_py_libdir = os.path.join(py_libdir, py_multiarch)
- libs_tried = []
- for lib_ext in lib_exts:
- lib_name = "libpython{}{}{}".format(py_version, lib_suff, lib_ext)
- py_library = os.path.join(try_py_libdir, lib_name)
- if os.path.exists(py_library):
- py_libdir = try_py_libdir
- python_library_found = True
- break
- libs_tried.append(py_library)
-
- if not python_library_found:
- raise DistutilsSetupError(
- "Failed to locate the Python library with {}".format(", ".join(libs_tried)))
-
- if py_library.endswith('.a'):
- # Python was compiled as a static library
- log.error("Failed to locate a dynamic Python library, using {}".format(py_library))
self.qtinfo = qtinfo
qt_dir = os.path.dirname(OPTION["QMAKE"])
@@ -633,7 +591,8 @@ class PysideBuild(_build):
self.install_dir = install_dir
self.py_executable = py_executable
self.py_include_dir = py_include_dir
- self.py_library = py_library
+ self.py_library = get_py_library(build_type, py_version, py_prefix,
+ py_libdir, py_include_dir)
self.py_version = py_version
self.build_type = build_type
self.site_packages_dir = get_python_lib(1, 0, prefix=install_dir)
@@ -743,74 +702,12 @@ class PysideBuild(_build):
log.info("OpenSSL dll directory: {}".format(OPTION["OPENSSL"]))
if sys.platform == 'darwin':
pyside_macos_deployment_target = (
- PysideBuild.macos_pyside_min_deployment_target()
+ macos_pyside_min_deployment_target()
)
log.info("MACOSX_DEPLOYMENT_TARGET set to: {}".format(
pyside_macos_deployment_target))
log.info("=" * 30)
- @staticmethod
- def macos_qt_min_deployment_target():
- target = qtinfo.macos_min_deployment_target
-
- if not target:
- raise DistutilsSetupError("Failed to query for Qt's QMAKE_MACOSX_DEPLOYMENT_TARGET.")
- return target
-
- @staticmethod
- @memoize
- def macos_pyside_min_deployment_target():
- """
- Compute and validate PySide2 MACOSX_DEPLOYMENT_TARGET value.
- Candidate sources that are considered:
- - setup.py provided value
- - maximum value between minimum deployment target of the
- Python interpreter and the minimum deployment target of
- the Qt libraries.
- If setup.py value is provided, that takes precedence.
- Otherwise use the maximum of the above mentioned two values.
- """
- python_target = get_config_var('MACOSX_DEPLOYMENT_TARGET') or None
- qt_target = PysideBuild.macos_qt_min_deployment_target()
- setup_target = OPTION["MACOS_DEPLOYMENT_TARGET"]
-
- qt_target_split = [int(x) for x in qt_target.split('.')]
- if python_target:
- python_target_split = [int(x) for x in python_target.split('.')]
- if setup_target:
- setup_target_split = [int(x) for x in setup_target.split('.')]
-
- message = ("Can't set MACOSX_DEPLOYMENT_TARGET value to {} because "
- "{} was built with minimum deployment target set to {}.")
- # setup.py provided OPTION["MACOS_DEPLOYMENT_TARGET"] value takes
- # precedence.
- if setup_target:
- if python_target and setup_target_split < python_target_split:
- raise DistutilsSetupError(message.format(setup_target, "Python",
- python_target))
- if setup_target_split < qt_target_split:
- raise DistutilsSetupError(message.format(setup_target, "Qt",
- qt_target))
- # All checks clear, use setup.py provided value.
- return setup_target
-
- # Setup.py value not provided,
- # use same value as provided by Qt.
- if python_target:
- maximum_target = '.'.join([str(e) for e in max(python_target_split, qt_target_split)])
- else:
- maximum_target = qt_target
- return maximum_target
-
- @staticmethod
- @memoize
- def macos_plat_name():
- deployment_target = PysideBuild.macos_pyside_min_deployment_target()
- # Example triple "macosx-10.12-x86_64".
- plat = get_platform().split("-")
- plat_name = "{}-{}-{}".format(plat[0], deployment_target, plat[2])
- return plat_name
-
def build_patchelf(self):
if not sys.platform.startswith('linux'):
return
@@ -1004,7 +901,7 @@ class PysideBuild(_build):
# interpreter sysconfig value.
# Doing so could break the detected clang include paths
# for example.
- deployment_target = PysideBuild.macos_pyside_min_deployment_target()
+ deployment_target = macos_pyside_min_deployment_target()
cmake_cmd.append("-DCMAKE_OSX_DEPLOYMENT_TARGET={}".format(deployment_target))
os.environ['MACOSX_DEPLOYMENT_TARGET'] = deployment_target
@@ -1268,9 +1165,11 @@ class PysideBuild(_build):
log.info("Patched rpath to '$ORIGIN/' (Linux) or "
"updated rpath (OS/X) in {}.".format(srcpath))
+
class PysideRstDocs(Command):
description = "Build .rst documentation only"
user_options = []
+
def initialize_options(self):
log.info("-- This build process will not include the API documentation."
"API documentation requires a full build of pyside/shiboken.")
@@ -1331,12 +1230,8 @@ class PysideRstDocs(Command):
elif self.name == "shiboken2":
self.sphinx_src = self.out_dir
- sphinx_cmd = ["sphinx-build",
- "-b", "html",
- "-c", self.sphinx_src,
- self.doc_dir,
- self.out_dir
- ]
+ sphinx_cmd = ["sphinx-build", "-b", "html", "-c", self.sphinx_src,
+ self.doc_dir, self.out_dir]
if run_process(sphinx_cmd) != 0:
raise DistutilsSetupError("Error running CMake for {}".format(self.doc_dir))
# Last message
@@ -1346,6 +1241,7 @@ class PysideRstDocs(Command):
def finalize_options(self):
pass
+
cmd_class_dict = {
'build': PysideBuild,
'build_py': PysideBuildPy,
@@ -1357,11 +1253,6 @@ cmd_class_dict = {
'build_rst_docs': PysideRstDocs,
}
if wheel_module_exists:
- 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)
+ pyside_bdist_wheel = get_bdist_wheel_override()
if pyside_bdist_wheel:
cmd_class_dict['bdist_wheel'] = pyside_bdist_wheel
diff --git a/build_scripts/qp5_tool.py b/build_scripts/qp5_tool.py
index 1358b21c2..b213948e7 100644
--- a/build_scripts/qp5_tool.py
+++ b/build_scripts/qp5_tool.py
@@ -390,7 +390,7 @@ if __name__ == '__main__':
build_mode = BuildMode.RECONFIGURE
if build_mode == BuildMode.NONE and not (options.clean or options.reset
- or options.pull or options.test):
+ or options.pull or options.test):
argument_parser.print_help()
sys.exit(0)
diff --git a/build_scripts/qtinfo.py b/build_scripts/qtinfo.py
index fa2d771b2..62bfee812 100644
--- a/build_scripts/qtinfo.py
+++ b/build_scripts/qtinfo.py
@@ -125,7 +125,7 @@ class QtInfo(object):
return self.get_property("QT_INSTALL_PREFIX/src")
def get_property(self, prop_name):
- if not self._query_dict:
+ if not self._query_dict:
self._get_query_properties()
self._get_other_properties()
if prop_name not in self._query_dict:
diff --git a/build_scripts/setup_runner.py b/build_scripts/setup_runner.py
index 15a0bf380..b54c62796 100644
--- a/build_scripts/setup_runner.py
+++ b/build_scripts/setup_runner.py
@@ -54,6 +54,7 @@ from setuptools import setup
if OPTION["VERBOSE_BUILD"]:
log.set_verbosity(1)
+
class SetupRunner(object):
def __init__(self, orig_argv):
self.invocations_list = []
diff --git a/build_scripts/utils.py b/build_scripts/utils.py
index ad17a7ba8..220d32efe 100644
--- a/build_scripts/utils.py
+++ b/build_scripts/utils.py
@@ -1081,18 +1081,20 @@ def get_qtci_virtualEnv(python_ver, host, hostArch, targetArch):
# With windows we are creating building 32-bit target in 64-bit host
if hostArch == "X86_64" and targetArch == "X86":
if python_ver.startswith("3"):
- print("Try to find python from {} env variable".format("PYTHON"+python_ver+"-32_PATH"))
- _path = os.getenv("PYTHON"+python_ver+"-32_PATH", "")
+ var = "PYTHON" + python_ver + "-32_PATH"
+ print("Try to find python from {} env variable".format(var))
+ _path = os.getenv(var, "")
_pExe = os.path.join(_path, "python.exe")
if not os.path.isfile(_pExe):
print("Can't find python.exe from {}, using default python3".format(_pExe))
_pExe = os.path.join(os.getenv("PYTHON3_32_PATH"), "python.exe")
else:
- _pExe = os.path.join(os.getenv("PYTHON2_32_PATH"), "python.exe")
+ _pExe = os.path.join(os.getenv("PYTHON2_32_PATH"), "python.exe")
else:
- if python_ver.startswith("3"):
- print("Try to find python from {} env variable".format("PYTHON"+python_ver+"-64_PATH"))
- _path = os.getenv("PYTHON"+python_ver+"-64_PATH", "")
+ if python_ver.startswith("3"):
+ var = "PYTHON" + python_ver + "-64_PATH"
+ print("Try to find python from {} env variable".format(var))
+ _path = os.getenv(var, "")
_pExe = os.path.join(_path, "python.exe")
if not os.path.isfile(_pExe):
print("Can't find python.exe from {}, using default python3".format(_pExe))
@@ -1137,6 +1139,6 @@ def get_ci_qmake_path(ci_install_dir, ci_host_os):
if ci_host_os == "MacOS":
return qmake_path + "/bin/qmake"
elif ci_host_os == "Windows":
- return qmake_path + "\\bin\\qmake.exe"
+ return qmake_path + "\\bin\\qmake.exe"
else:
return qmake_path + "/bin/qmake"
diff --git a/build_scripts/wheel_override.py b/build_scripts/wheel_override.py
index 0a3cb0dbf..e4147a5bc 100644
--- a/build_scripts/wheel_override.py
+++ b/build_scripts/wheel_override.py
@@ -54,6 +54,7 @@ try:
from wheel import __version__ as wheel_version
from .options import OPTION
+ from .wheel_utils import get_package_version, get_qt_version, macos_plat_name
wheel_module_exists = True
except Exception as e:
@@ -62,20 +63,13 @@ except Exception as e:
'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
+def get_bdist_wheel_override():
+ return PysideBuildWheel if wheel_module_exists else None
class PysideBuildWheel(_bdist_wheel):
def __init__(self, *args, **kwargs):
- self.pyside_params = None
+ self._package_version = None
_bdist_wheel.__init__(self, *args, **kwargs)
def finalize_options(self):
@@ -83,7 +77,7 @@ class PysideBuildWheel(_bdist_wheel):
# 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']
+ self.plat_name = macos_plat_name()
# When limited API is requested, notify bdist_wheel to
# create a properly named package.
@@ -92,6 +86,8 @@ class PysideBuildWheel(_bdist_wheel):
if limited_api_enabled:
self.py_limited_api = "cp35.cp36.cp37.cp38.cp39"
+ self._package_version = get_package_version()
+
_bdist_wheel.finalize_options(self)
@property
@@ -102,9 +98,7 @@ class PysideBuildWheel(_bdist_wheel):
# 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)
+ wheel_version = "{}-{}".format(self._package_version, get_qt_version())
components = (_safer_name(self.distribution.get_name()), wheel_version)
if self.build_number:
components += (self.build_number,)
diff --git a/build_scripts/wheel_utils.py b/build_scripts/wheel_utils.py
new file mode 100644
index 000000000..71b4e0acf
--- /dev/null
+++ b/build_scripts/wheel_utils.py
@@ -0,0 +1,162 @@
+#############################################################################
+##
+## Copyright (C) 2020 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$
+##
+#############################################################################
+
+from __future__ import print_function
+
+import os
+import time
+
+from distutils.errors import DistutilsSetupError
+from distutils.sysconfig import get_config_var
+from distutils.util import get_platform
+from distutils.version import LooseVersion
+
+from .options import OPTION
+from .qtinfo import QtInfo
+from .utils import memoize, get_python_dict
+
+
+@memoize
+def get_package_timestamp():
+ """ In a Coin CI build the returned timestamp will be the
+ Coin integration id timestamp. For regular builds it's
+ just the current timestamp or a user provided one."""
+ option_value = OPTION["PACKAGE_TIMESTAMP"]
+ return option_value if option_value else int(time.time())
+
+
+def get_qt_version():
+ qtinfo = QtInfo()
+ qt_version = qtinfo.version
+
+ if not qt_version:
+ m = "Failed to query the Qt version with qmake {0}".format(qtinfo.qmake_command)
+ raise DistutilsSetupError(m)
+
+ if LooseVersion(qtinfo.version) < LooseVersion("5.7"):
+ m = "Incompatible Qt version detected: {}. A Qt version >= 5.7 is required.".format(qt_version)
+ raise DistutilsSetupError(m)
+
+ return qt_version
+
+
+@memoize
+def get_package_version():
+ """ Returns the version string for the PySide2 package. """
+ setup_script_dir = os.getcwd()
+ pyside_version_py = os.path.join(
+ setup_script_dir, "sources", "pyside2", "pyside_version.py")
+ d = get_python_dict(pyside_version_py)
+
+ final_version = "{}.{}.{}".format(
+ d['major_version'], d['minor_version'], d['patch_version'])
+ release_version_type = d['release_version_type']
+ pre_release_version = d['pre_release_version']
+ if pre_release_version and release_version_type:
+ final_version += release_version_type + pre_release_version
+ if release_version_type.startswith("comm"):
+ final_version += "." + release_version_type
+
+ # Add the current timestamp to the version number, to suggest it
+ # is a development snapshot build.
+ if OPTION["SNAPSHOT_BUILD"]:
+ final_version += ".dev{}".format(get_package_timestamp())
+ return final_version
+
+
+def macos_qt_min_deployment_target():
+ target = QtInfo().macos_min_deployment_target
+
+ if not target:
+ raise DistutilsSetupError("Failed to query for Qt's QMAKE_MACOSX_DEPLOYMENT_TARGET.")
+ return target
+
+
+@memoize
+def macos_pyside_min_deployment_target():
+ """
+ Compute and validate PySide2 MACOSX_DEPLOYMENT_TARGET value.
+ Candidate sources that are considered:
+ - setup.py provided value
+ - maximum value between minimum deployment target of the
+ Python interpreter and the minimum deployment target of
+ the Qt libraries.
+ If setup.py value is provided, that takes precedence.
+ Otherwise use the maximum of the above mentioned two values.
+ """
+ python_target = get_config_var('MACOSX_DEPLOYMENT_TARGET') or None
+ qt_target = macos_qt_min_deployment_target()
+ setup_target = OPTION["MACOS_DEPLOYMENT_TARGET"]
+
+ qt_target_split = [int(x) for x in qt_target.split('.')]
+ if python_target:
+ python_target_split = [int(x) for x in python_target.split('.')]
+ if setup_target:
+ setup_target_split = [int(x) for x in setup_target.split('.')]
+
+ message = ("Can't set MACOSX_DEPLOYMENT_TARGET value to {} because "
+ "{} was built with minimum deployment target set to {}.")
+ # setup.py provided OPTION["MACOS_DEPLOYMENT_TARGET"] value takes
+ # precedence.
+ if setup_target:
+ if python_target and setup_target_split < python_target_split:
+ raise DistutilsSetupError(message.format(setup_target, "Python",
+ python_target))
+ if setup_target_split < qt_target_split:
+ raise DistutilsSetupError(message.format(setup_target, "Qt",
+ qt_target))
+ # All checks clear, use setup.py provided value.
+ return setup_target
+
+ # Setup.py value not provided,
+ # use same value as provided by Qt.
+ if python_target:
+ maximum_target = '.'.join([str(e) for e in max(python_target_split, qt_target_split)])
+ else:
+ maximum_target = qt_target
+ return maximum_target
+
+
+@memoize
+def macos_plat_name():
+ deployment_target = macos_pyside_min_deployment_target()
+ # Example triple "macosx-10.12-x86_64".
+ plat = get_platform().split("-")
+ plat_name = "{}-{}-{}".format(plat[0], deployment_target, plat[2])
+ return plat_name