diff options
Diffstat (limited to 'build_scripts/options.py')
-rw-r--r-- | build_scripts/options.py | 643 |
1 files changed, 527 insertions, 116 deletions
diff --git a/build_scripts/options.py b/build_scripts/options.py index c17f6a100..806d4a8a3 100644 --- a/build_scripts/options.py +++ b/build_scripts/options.py @@ -1,57 +1,43 @@ -############################################################################# -## -## 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$ -## -############################################################################# - -from __future__ import print_function +# Copyright (C) 2018 The Qt Company Ltd. +# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +from setuptools import Command + import sys -import os -import warnings +import logging +from pathlib import Path + +from .log import log, LogLevel +from .qtinfo import QtInfo +from .utils import memoize, which + +_AVAILABLE_MKSPECS = ["ninja", "msvc", "mingw"] if sys.platform == "win32" else ["ninja", "make"] + + +# Global options not which are not part of the commands +ADDITIONAL_OPTIONS = """ +Additional options: + --limited-api Use Limited API [yes/no] + --macos-use-libc++ Use libc++ on macOS + --snapshot-build Snapshot build + --package-timestamp Package Timestamp + --cmake-toolchain-file Path to CMake toolchain to enable cross-compiling + --shiboken-host-path Path to host shiboken package when cross-compiling + --qt-host-path Path to host Qt installation when cross-compiling + --disable-pyi Disable .pyi file generation +""" def _warn_multiple_option(option): - w = 'Option "{}" occurs multiple times on the command line.'.format(option) - warnings.warn(w) + log.warning(f'Option "{option}" occurs multiple times on the command line.') + def _warn_deprecated_option(option, replacement=None): - w = 'Option "{}" is deprecated and may be removed in a future release.'.format(option) + w = f'Option "{option}" is deprecated and may be removed in a future release.' if replacement: - w = '{}\nUse "{}" instead.'.format(w, replacement) - warnings.warn(w) + w = f'{w}\nUse "{replacement}" instead.' + log.warning(w) + class Options(object): def __init__(self): @@ -62,24 +48,22 @@ class Options(object): def has_option(self, name, remove=True): """ Returns True if argument '--name' was passed on the command line. """ - option = '--' + name + option = f"--{name}" count = sys.argv.count(option) remove_count = count if not remove and count > 0: remove_count -= 1 - for i in range(remove_count): - sys.argv.remove(option) + for _ in range(remove_count): + sys.argv.remove(option) if count > 1: _warn_multiple_option(option) return count > 0 def option_value(self, name, short_option_name=None, remove=True): """ - Returns the value of a command line option or environment - variable. + Returns the value of a command line option. - :param name: The name of the command line option or environment - variable. + :param name: The name of the command line option. :param remove: Whether the option and its value should be removed from sys.argv. Useful when there's a need to query for @@ -87,9 +71,10 @@ class Options(object): :return: Either the option value or None. """ - option = '--' + name - short_option = '-' + short_option_name if short_option_name else None - single_option_prefix = option + '=' + + option = f"--{name}" + short_option = f"-{short_option_name}" if short_option_name else None + single_option_prefix = f"{option}=" value = None for index in reversed(range(len(sys.argv))): arg = sys.argv[index] @@ -98,7 +83,7 @@ class Options(object): _warn_multiple_option(option) else: if index + 1 >= len(sys.argv): - raise RuntimeError("The option {} requires a value".format(option)) + raise RuntimeError(f"The option {option} requires a value") value = sys.argv[index + 1] if remove: @@ -113,9 +98,6 @@ class Options(object): if remove: sys.argv[index:index + 1] = [] - if value is None: - value = os.getenv(name.upper().replace('-', '_')) - self.dict[name] = value return value @@ -127,61 +109,490 @@ def has_option(*args, **kwargs): return options.has_option(*args, **kwargs) -def option_value(*args,**kwargs): - return options.option_value(*args,**kwargs) - - -# Declare options -OPTION_BUILD_TYPE = option_value("build-type") -OPTION_INTERNAL_BUILD_TYPE = option_value("internal-build-type") -OPTION_DEBUG = has_option("debug") -OPTION_RELWITHDEBINFO = has_option('relwithdebinfo') -OPTION_QMAKE = option_value("qmake") -OPTION_QT_VERSION = option_value("qt") -OPTION_CMAKE = option_value("cmake") -OPTION_OPENSSL = option_value("openssl") -OPTION_SHIBOKEN_CONFIG_DIR = option_value("shiboken-config-dir") -OPTION_ONLYPACKAGE = has_option("only-package") -OPTION_STANDALONE = has_option("standalone") -OPTION_MAKESPEC = option_value("make-spec") -OPTION_IGNOREGIT = has_option("ignore-git") -# don't generate documentation -OPTION_SKIP_DOCS = has_option("skip-docs") -# don't include pyside2-examples -OPTION_NOEXAMPLES = has_option("no-examples") -# number of parallel build jobs -OPTION_JOBS = option_value('parallel', short_option_name='j') +def option_value(*args, **kwargs): + return options.option_value(*args, **kwargs) + + +def _jobs_option_value(): + """Option value for parallel builds.""" + value = option_value('parallel', short_option_name='j') + if value: + return f"-j{value}" if not value.startswith('-j') else value + return '' + + +def find_qtpaths(): + # for these command --qtpaths should not be required + no_qtpaths_commands = ["--help", "--help-commands", "--qt-target-path", "build_base_docs"] + + for no_qtpaths_command in no_qtpaths_commands: + if any(no_qtpaths_command in argument for argument in sys.argv): + return None + + qtpaths = option_value("qtpaths") + if qtpaths: + return qtpaths + + # if qtpaths is not given as cli option, try to find it in PATH + qtpaths = which("qtpaths6") + if qtpaths: + return str(qtpaths.resolve()) + + qtpaths = which("qtpaths") + if qtpaths: + return str(qtpaths.resolve()) + + return qtpaths + + +# Declare options which need to be known when instantiating the setuptools +# commands or even earlier during SetupRunner.run(). +OPTION = { + "BUILD_TYPE": option_value("build-type"), + "INTERNAL_BUILD_TYPE": option_value("internal-build-type"), + # number of parallel build jobs + "JOBS": _jobs_option_value(), + # Legacy, not used any more. + "JOM": has_option('jom'), + "MACOS_USE_LIBCPP": has_option("macos-use-libc++"), + "LOG_LEVEL": option_value("log-level", remove=False), + "QUIET": has_option('quiet'), + "VERBOSE_BUILD": has_option('verbose-build'), + "SNAPSHOT_BUILD": has_option("snapshot-build"), + "LIMITED_API": option_value("limited-api"), + "DISABLE_PYI": has_option("disable-pyi"), + "PACKAGE_TIMESTAMP": option_value("package-timestamp"), + # This is used automatically by setuptools.command.install object, to + # specify the final installation location. + "FINAL_INSTALL_PREFIX": option_value("prefix", remove=False), + "CMAKE_TOOLCHAIN_FILE": option_value("cmake-toolchain-file"), + "SHIBOKEN_HOST_PATH": option_value("shiboken-host-path"), + "SHIBOKEN_HOST_PATH_QUERY_FILE": option_value("internal-shiboken-host-path-query-file"), + "QT_HOST_PATH": option_value("qt-host-path"), + # This is used to identify the template for doc builds + "QTPATHS": find_qtpaths() + # This is an optional command line option. If --qtpaths is not provided via command-line, + # then qtpaths is checked inside PATH variable +} + _deprecated_option_jobs = option_value('jobs') if _deprecated_option_jobs: _warn_deprecated_option('jobs', 'parallel') - OPTION_JOBS = _deprecated_option_jobs -# Legacy, not used any more. -OPTION_JOM = has_option('jom') -# Do not use jom instead of nmake with msvc -OPTION_NO_JOM = has_option('no-jom') -OPTION_BUILDTESTS = has_option("build-tests") -OPTION_MACOS_ARCH = option_value("macos-arch") -OPTION_MACOS_USE_LIBCPP = has_option("macos-use-libc++") -OPTION_MACOS_SYSROOT = option_value("macos-sysroot") -OPTION_MACOS_DEPLOYMENT_TARGET = option_value("macos-deployment-target") -OPTION_XVFB = has_option("use-xvfb") -OPTION_REUSE_BUILD = has_option("reuse-build") -OPTION_SKIP_CMAKE = has_option("skip-cmake") -OPTION_SKIP_MAKE_INSTALL = has_option("skip-make-install") -OPTION_SKIP_PACKAGING = has_option("skip-packaging") -OPTION_SKIP_MODULES = option_value("skip-modules") -OPTION_MODULE_SUBSET = option_value("module-subset") -OPTION_RPATH_VALUES = option_value("rpath") -OPTION_QT_CONF_PREFIX = option_value("qt-conf-prefix") -OPTION_QT_SRC = option_value("qt-src-dir") -OPTION_QUIET = has_option('quiet', remove=False) -OPTION_VERBOSE_BUILD = has_option("verbose-build") -OPTION_SANITIZE_ADDRESS = has_option("sanitize-address") -OPTION_SNAPSHOT_BUILD = has_option("snapshot-build") -OPTION_LIMITED_API = option_value("limited-api") -OPTION_PACKAGE_TIMESTAMP = option_value("package-timestamp") -OPTION_SHORTER_PATHS = has_option("shorter-paths") - -# This is used automatically by distutils.command.install object, to -# specify the final installation location. -OPTION_FINAL_INSTALL_PREFIX = option_value("prefix", remove=False) + OPTION["JOBS"] = _deprecated_option_jobs + + +class CommandMixin(object): + """Mixin for the setuptools build/install commands handling the options.""" + + _static_class_finalized_once = False + + mixin_user_options = [ + ('avoid-protected-hack', None, 'Force --avoid-protected-hack'), + ('debug', None, 'Build with debug information'), + ('relwithdebinfo', None, 'Build in release mode with debug information'), + ('only-package', None, 'Package only'), + ('no-strip', None, 'Do not strip package libraries (release mode)'), + ('standalone', None, 'Standalone build'), + ('ignore-git', None, 'Do update subrepositories'), + ('skip-docs', None, 'Skip documentation build (deprecated)'), + ('build-docs', None, 'Build the API documentation'), + ('no-jom', None, 'Do not use jom (MSVC)'), + ('build-tests', None, 'Build tests'), + ('use-xvfb', None, 'Use Xvfb for testing'), + ('reuse-build', None, 'Reuse existing build'), + ('compiler-launcher=', None, 'Use a compiler launcher like ccache or sccache for builds'), + ('skip-cmake', None, 'Skip CMake step'), + ('skip-make-install', None, 'Skip install step'), + ('skip-packaging', None, 'Skip packaging step'), + ('log-level=', None, 'Log level of the build.'), + ('verbose-build', None, 'Verbose build'), + ('quiet', None, 'Quiet build'), + ('sanitize-address', None, 'Build with address sanitizer'), + ('shorter-paths', None, 'Use shorter paths'), + ('doc-build-online', None, 'Build online documentation'), + ('qtpaths=', None, 'Path to qtpaths'), + ('qmake=', None, 'Path to qmake (deprecated, use qtpaths)'), + ('qt=', None, 'Qt version'), + ('qt-target-path=', None, + 'Path to device Qt installation (use Qt libs when cross-compiling)'), + ('cmake=', None, 'Path to CMake'), + ('openssl=', None, 'Path to OpenSSL libraries'), + + # FIXME: Deprecated in favor of shiboken-target-path + ('shiboken-config-dir=', None, 'shiboken configuration directory'), + + ('shiboken-target-path=', None, 'Path to target shiboken package'), + ('python-target-path=', None, 'Path to target Python installation / prefix'), + ('make-spec=', None, 'Qt make-spec'), + ('macos-arch=', None, 'macOS architecture'), + ('macos-sysroot=', None, 'macOS sysroot'), + ('macos-deployment-target=', None, 'macOS deployment target'), + ('skip-modules=', None, 'Qt modules to be skipped'), + ('module-subset=', None, 'Qt modules to be built'), + ('rpath=', None, 'RPATH'), + ('qt-conf-prefix=', None, 'Qt configuration prefix'), + ('qt-src-dir=', None, 'Qt source directory'), + ('no-qt-tools', None, 'Do not copy the Qt tools'), + ('no-size-optimization', None, 'Turn off size optimization for PySide6 binaries'), + # Default is auto-detected by PysideBuild._enable_numpy() + ('pyside-numpy-support', None, 'libpyside: Add numpy support (deprecated)'), + ('enable-numpy-support', None, 'Enable numpy support'), + ('disable-numpy-support', None, 'Disable numpy support'), + ('internal-cmake-install-dir-query-file-path=', None, + 'Path to file where the CMake install path of the project will be saved'), + + # We redeclare plat-name as an option so it's recognized by the + # install command and doesn't throw an error. + ('plat-name=', None, 'The platform name for which we are cross-compiling'), + ('unity', None, 'Use CMake UNITY_BUILD_MODE (obsolete)'), + ('no-unity', None, 'Disable CMake UNITY_BUILD_MODE'), + ('unity-build-batch-size=', None, 'Value of CMAKE_UNITY_BUILD_BATCH_SIZE') + ] + + def __init__(self): + self.avoid_protected_hack = False + self.debug = False + self.relwithdebinfo = False + self.no_strip = False + self.only_package = False + self.standalone = False + self.ignore_git = False + self.skip_docs = False + self.build_docs = False + self.no_jom = False + self.build_tests = False + self.use_xvfb = False + self.reuse_build = False + self.compiler_launcher = None + self.skip_cmake = False + self.skip_make_install = False + self.skip_packaging = False + self.log_level = "info" + self.verbose_build = False + self.sanitize_address = False + self.snapshot_build = False + self.shorter_paths = False + self.doc_build_online = False + self.qtpaths = None + self.qmake = None + self.has_qmake_option = False + self.qt = '5' + self.qt_host_path = None + self.qt_target_path = None + self.cmake = None + self.openssl = None + self.shiboken_config_dir = None + self.shiboken_host_path = None + self.shiboken_host_path_query_file = None + self.shiboken_target_path = None + self.python_target_path = None + self.is_cross_compile = False + self.cmake_toolchain_file = None + self.make_spec = None + self.macos_arch = None + self.macos_sysroot = None + self.macos_deployment_target = None + self.skip_modules = None + self.module_subset = None + self.rpath = None + self.qt_conf_prefix = None + self.qt_src_dir = None + self.no_qt_tools = False + self.no_size_optimization = False + self.pyside_numpy_support = False + self.enable_numpy_support = False + self.disable_numpy_support = False + self.plat_name = None + self.internal_cmake_install_dir_query_file_path = None + self._per_command_mixin_options_finalized = False + self.unity = False + self.no_unity = False + self.unity_build_batch_size = "16" + + # When initializing a command other than the main one (so the + # first one), we need to copy the user options from the main + # command to the new command options dict. Then + # Distribution.get_command_obj will pick up the copied options + # ensuring that all commands that inherit from + # the mixin, get our custom properties set by the time + # finalize_options is called. + if CommandMixin._static_class_finalized_once: + current_command: Command = self + dist = current_command.distribution + main_command_name = dist.commands[0] + main_command_opts = dist.get_option_dict(main_command_name) + current_command_name = current_command.get_command_name() + current_command_opts = dist.get_option_dict(current_command_name) + mixin_options_set = self.get_mixin_options_set() + for key, value in main_command_opts.items(): + if key not in current_command_opts and key in mixin_options_set: + current_command_opts[key] = value + + # qtpaths is already known before running SetupRunner + self.qtpaths = OPTION["QTPATHS"] + + @staticmethod + @memoize + def get_mixin_options_set(): + keys = set() + for (name, _, _) in CommandMixin.mixin_user_options: + keys.add(name.rstrip("=").replace("-", "_")) + return keys + + def mixin_finalize_options(self): + # The very first we finalize options, record that. + if not CommandMixin._static_class_finalized_once: + CommandMixin._static_class_finalized_once = True + + # Ensure we finalize once per command object, rather than per + # setup.py invocation. We want to have the option values + # available in all commands that derive from the mixin. + if not self._per_command_mixin_options_finalized: + self._per_command_mixin_options_finalized = True + self._do_finalize() + + def _do_finalize(self): + # is_cross_compile must be set before checking for qtpaths/qmake + # because we DON'T want those to be found when cross compiling. + # Currently when cross compiling, qt-target-path MUST be used. + using_cmake_toolchain_file = False + cmake_toolchain_file = None + if OPTION["CMAKE_TOOLCHAIN_FILE"]: + self.is_cross_compile = True + using_cmake_toolchain_file = True + cmake_toolchain_file = OPTION["CMAKE_TOOLCHAIN_FILE"] + self.cmake_toolchain_file = cmake_toolchain_file + + if not self._determine_defaults_and_check(): + sys.exit(-1) + OPTION['AVOID_PROTECTED_HACK'] = self.avoid_protected_hack + OPTION['DEBUG'] = self.debug + OPTION['RELWITHDEBINFO'] = self.relwithdebinfo + OPTION['NO_STRIP'] = self.no_strip + OPTION['ONLYPACKAGE'] = self.only_package + OPTION['STANDALONE'] = self.standalone + if self.ignore_git: + _warn_deprecated_option('ignore_git') + OPTION['SKIP_DOCS'] = self.skip_docs + OPTION['BUILD_DOCS'] = self.build_docs + OPTION['BUILDTESTS'] = self.build_tests + + OPTION['NO_JOM'] = self.no_jom + OPTION['XVFB'] = self.use_xvfb + OPTION['REUSE_BUILD'] = self.reuse_build + OPTION['COMPILER_LAUNCHER'] = self.compiler_launcher + OPTION['SKIP_CMAKE'] = self.skip_cmake + OPTION['SKIP_MAKE_INSTALL'] = self.skip_make_install + OPTION['SKIP_PACKAGING'] = self.skip_packaging + # Logging options: + # 'quiet' and 'verbose-build' are deprecated, + # log-level has higher priority when used. + OPTION['LOG_LEVEL'] = self.log_level + OPTION['VERBOSE_BUILD'] = self.verbose_build + # The OPTION["QUIET"] doesn't need to be initialized with a value + # because is an argument that it will not be removed due to being + # a setuptools argument as well. + + # By default they are False, so we check if they changed with xor + if bool(OPTION["QUIET"]) != bool(OPTION["VERBOSE_BUILD"]): + log.warning("Using --quiet and --verbose-build is deprecated. " + "Please use --log-level=quiet or --log-level=verbose instead.") + # We assign a string value instead of the enum + # because is what we get from the command line. + # Later we assign the enum + if OPTION["QUIET"]: + OPTION["LOG_LEVEL"] = "quiet" + elif OPTION["VERBOSE_BUILD"]: + OPTION["LOG_LEVEL"] = "verbose" + + if OPTION["LOG_LEVEL"] not in ("quiet", "info", "verbose"): + log.error(f"Invalid value for log level: '--log-level={OPTION['LOG_LEVEL']}'. " + "Use 'quiet', 'info', or 'verbose'.") + sys.exit(-1) + else: + if OPTION["LOG_LEVEL"] == "quiet": + OPTION["LOG_LEVEL"] = LogLevel.QUIET + log.setLevel(logging.ERROR) + elif OPTION["LOG_LEVEL"] == "info": + OPTION["LOG_LEVEL"] = LogLevel.INFO + log.setLevel(logging.INFO) + elif OPTION["LOG_LEVEL"] == "verbose": + OPTION["LOG_LEVEL"] = LogLevel.VERBOSE + log.setLevel(logging.DEBUG) + + OPTION['SANITIZE_ADDRESS'] = self.sanitize_address + OPTION['SHORTER_PATHS'] = self.shorter_paths + OPTION['DOC_BUILD_ONLINE'] = self.doc_build_online + if self.unity: + log.warning("Using --unity no longer has any effect, " + "Unity build mode is now the default.") + OPTION['UNITY'] = not self.no_unity + OPTION['UNITY_BUILD_BATCH_SIZE'] = self.unity_build_batch_size + + qtpaths_abs_path = None + if self.qtpaths and Path(self.qtpaths).exists(): + qtpaths_abs_path = Path(self.qtpaths).resolve() + + # FIXME PYSIDE7: Remove qmake handling + # make qtinfo.py independent of relative paths. + qmake_abs_path = None + if self.qmake: + qmake_abs_path = Path(self.qmake).resolve() + OPTION['QMAKE'] = qmake_abs_path + OPTION['HAS_QMAKE_OPTION'] = self.has_qmake_option + OPTION['QT_VERSION'] = self.qt + self.qt_host_path = OPTION['QT_HOST_PATH'] + OPTION['QT_TARGET_PATH'] = self.qt_target_path + + qt_target_path = self.qt_target_path + + # We use the CMake project to find host Qt if neither qmake or + # qtpaths is available. This happens when building the host + # tools in the overall cross-building process. + use_cmake = False + if (using_cmake_toolchain_file or (not self.qmake + and not self.qtpaths and self.qt_target_path)): + use_cmake = True + + QtInfo().setup(qtpaths_abs_path, self.cmake, qmake_abs_path, + self.has_qmake_option, + use_cmake=use_cmake, + qt_target_path=qt_target_path, + cmake_toolchain_file=cmake_toolchain_file) + + if 'build_base_docs' not in sys.argv: + try: + QtInfo().prefix_dir + except Exception as e: + if not self.qt_target_path: + log.error( + "\nCould not find Qt. You can pass the --qt-target-path=<qt-dir> option " + "as a hint where to find Qt. Error was:\n\n\n") + else: + log.error( + f"\nCould not find Qt via provided option --qt-target-path={qt_target_path}" + "Error was:\n\n\n") + raise e + + OPTION['CMAKE'] = self.cmake.resolve() + OPTION['OPENSSL'] = self.openssl + OPTION['SHIBOKEN_CONFIG_DIR'] = self.shiboken_config_dir + if self.shiboken_config_dir: + _warn_deprecated_option('shiboken-config-dir', 'shiboken-target-path') + + self.shiboken_host_path = OPTION['SHIBOKEN_HOST_PATH'] + self.shiboken_host_path_query_file = OPTION['SHIBOKEN_HOST_PATH_QUERY_FILE'] + + if not self.shiboken_host_path and self.shiboken_host_path_query_file: + try: + queried_shiboken_host_path = Path(self.shiboken_host_path_query_file).read_text() + self.shiboken_host_path = queried_shiboken_host_path + OPTION['SHIBOKEN_HOST_PATH'] = queried_shiboken_host_path + except Exception as e: + log.error( + f"\n Could not find shiboken host tools via the query file: " + f"{self.shiboken_host_path_query_file:} Error was:\n\n\n") + raise e + + OPTION['SHIBOKEN_TARGET_PATH'] = self.shiboken_target_path + OPTION['PYTHON_TARGET_PATH'] = self.python_target_path + OPTION['MAKESPEC'] = self.make_spec + OPTION['MACOS_ARCH'] = self.macos_arch + OPTION['MACOS_SYSROOT'] = self.macos_sysroot + OPTION['MACOS_DEPLOYMENT_TARGET'] = self.macos_deployment_target + OPTION['SKIP_MODULES'] = self.skip_modules + OPTION['MODULE_SUBSET'] = self.module_subset + OPTION['RPATH_VALUES'] = self.rpath + OPTION['QT_CONF_PREFIX'] = self.qt_conf_prefix + OPTION['QT_SRC'] = self.qt_src_dir + OPTION['NO_QT_TOOLS'] = self.no_qt_tools + OPTION['NO_OVERRIDE_OPTIMIZATION_FLAGS'] = self.no_size_optimization + OPTION['DISABLE_NUMPY_SUPPORT'] = self.disable_numpy_support + OPTION['ENABLE_NUMPY_SUPPORT'] = self.enable_numpy_support + OPTION['PYSIDE_NUMPY_SUPPORT'] = self.pyside_numpy_support + + if not self._extra_checks(): + sys.exit(-1) + + OPTION['PLAT_NAME'] = self.plat_name + + def _extra_checks(self): + if self.is_cross_compile and not self.plat_name: + log.error("No value provided to --plat-name while cross-compiling.") + return False + return True + + def _determine_defaults_and_check(self): + if not self.cmake: + self.cmake = Path(which("cmake")) + elif isinstance(self.cmake, str): # command line option + self.cmake = Path(self.cmake) + if not self.cmake: + log.error("cmake could not be found.") + return False + if not self.cmake.exists(): + log.error(f"'{self.cmake}' does not exist.") + return False + + # Setting up the Paths when passing via command line + if isinstance(self.qtpaths, str): + self.qtpaths = Path(self.qtpaths) + if isinstance(self.qmake, str): + self.qmake = Path(self.qmake) + if self.qt_target_path and isinstance(self.qt_target_path, str): + self.qt_target_path = Path(self.qt_target_path) + + # When cross-compiling, we only accept the qt-target-path + # option and don't rely on auto-searching in PATH or the other + # qtpaths / qmake options. + # We also don't do auto-searching if qt-target-path is passed + # explicitly. This is to help with the building of host tools + # while cross-compiling. + # Skip this process for the 'build_base_docs' command + if (not self.is_cross_compile + and not self.qt_target_path + and 'build_base_docs' not in sys.argv): + # Enforce usage of qmake in QtInfo if it was given explicitly. + if self.qmake: + self.has_qmake_option = True + _warn_deprecated_option('qmake', 'qtpaths') + + # If no tool was specified and qtpaths was not found in PATH, + # ask to provide a path to qtpaths. + if not self.qtpaths and not self.qmake and not self.qt_target_path: + log.error("No value provided to --qtpaths option. Please provide one to find Qt.") + return False + + # Validate that the given tool path exists. + if self.qtpaths and not self.qtpaths.exists(): + log.error(f"The specified qtpaths path '{self.qtpaths}' does not exist.") + return False + + if self.qmake and not self.qmake.exists(): + log.error(f"The specified qmake path '{self.qmake}' does not exist.") + return False + else: + # Check for existence, but don't require if it's not set. A + # check later will be done to see if it's needed. + if self.qt_target_path and not self.qt_target_path.exists(): + log.error(f"Provided --qt-target-path='{self.qt_target_path}' " + "path does not exist.") + return False + + if not self.make_spec: + self.make_spec = _AVAILABLE_MKSPECS[0] + if self.make_spec not in _AVAILABLE_MKSPECS: + log.error(f'Invalid option --make-spec "{self.make_spec}". ' + f'Available values are {_AVAILABLE_MKSPECS}') + return False + + if OPTION["JOBS"] and sys.platform == 'win32' and self.no_jom: + log.error("Option --jobs can only be used with jom on Windows.") + return False + + if sys.platform == 'win32' and OPTION["LIMITED_API"] == "yes" and self.debug: + log.error("It is not possible to make a debug build of PySide6 with limited API. " + "Please select a release build or disable limited API.") + return False + + return True |