aboutsummaryrefslogtreecommitdiffstats
diff options
authorCristián Maureira-Fredes <Cristian.Maureira-Fredes@qt.io>2024-12-13 14:53:21 +0100
committerCristián Maureira-Fredes <Cristian.Maureira-Fredes@qt.io>2024-12-18 10:08:05 +0100
commit03a3e61b0cce28c44b68b032cff2e6b8fa869477 (patch)
tree3f70c84532e671436b3ebc30fbc226aedf49d5eb
parentb513d1e0ba84f997561f624c73ee54ab91581861 (diff)
build: improve the build configuration implementation
- Using Singleton for the class - Adding type hints for the Path variables - Use function for parsing modules instead of duplicating it - Adapting related code in other files as well - Remove historical prints when configuring. Pick-to: 6.8 Change-Id: I9fef2e8d7c2033442f89a6f6ca027b5ae2ac6ab4 Reviewed-by: Friedemann Kleint <Friedemann.Kleint@qt.io>
-rw-r--r--build_scripts/config.py64
-rw-r--r--build_scripts/main.py61
-rw-r--r--build_scripts/options.py4
-rw-r--r--build_scripts/qtinfo.py2
-rw-r--r--build_scripts/setup_runner.py2
-rw-r--r--build_scripts/utils.py11
6 files changed, 62 insertions, 82 deletions
diff --git a/build_scripts/config.py b/build_scripts/config.py
index ca7a148ab..d446302de 100644
--- a/build_scripts/config.py
+++ b/build_scripts/config.py
@@ -2,12 +2,14 @@
# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
from __future__ import annotations
+import os
import sys
-from .log import log, LogLevel
from pathlib import Path
+from typing import Any
-from . import PYSIDE, PYSIDE_MODULE, SHIBOKEN, PYPROJECT_PATH
-from .utils import available_pyside_tools
+from . import PYPROJECT_PATH, PYSIDE, PYSIDE_MODULE, SHIBOKEN
+from .log import LogLevel, log
+from .utils import available_pyside_tools, Singleton
try:
import tomllib
@@ -15,7 +17,7 @@ except ModuleNotFoundError:
import tomli as tomllib
-class Config(object):
+class Config(object, metaclass=Singleton):
def __init__(self):
# Constants
self._build_type_all = "all"
@@ -28,7 +30,7 @@ class Config(object):
# The setup.py invocation type.
# top-level
# internal
- self.invocation_type = None
+ self.invocation_type: str = ""
# The type of the top-level build.
# all - build shiboken6 module, shiboken6-generator and PySide6
@@ -36,11 +38,11 @@ class Config(object):
# shiboken6 - build only shiboken6 module
# shiboken6-generator - build only the shiboken6-generator
# pyside6 - build only PySide6 modules
- self.build_type = None
+ self.build_type: str = ""
# The internal build type, used for internal invocations of
# setup.py to build a specific module only.
- self.internal_build_type = None
+ self.internal_build_type: str = ""
# Options that can be given to --build-type and
# --internal-build-type
@@ -51,18 +53,18 @@ class Config(object):
# Names to be passed to setuptools.setup() name key,
# so not package name, but rather project name as it appears
# in the wheel name and on PyPi.
- self.shiboken_module_st_name = SHIBOKEN
- self.shiboken_generator_st_name = f"{SHIBOKEN}-generator"
- self.pyside_st_name = PYSIDE_MODULE
+ self.shiboken_module_st_name: str = SHIBOKEN
+ self.shiboken_generator_st_name: str = f"{SHIBOKEN}-generator"
+ self.pyside_st_name: str = PYSIDE_MODULE
# Path to CMake toolchain file when intending to cross compile
# the project.
- self.cmake_toolchain_file = None
+ self.cmake_toolchain_file: str | os.PathLike = ""
# Store where host shiboken is built during a cross-build.
- self.shiboken_host_query_path = None
+ self.shiboken_host_query_path: str = ""
- self.setup_script_dir = None
+ self.setup_script_dir: str | os.PathLike = ""
# Getting data from base pyproject.toml file to be consistent
@@ -72,7 +74,7 @@ class Config(object):
with open(PYPROJECT_PATH, "rb") as f:
_pyproject_data = tomllib.load(f)["project"]
- self.setup_kwargs = {}
+ self.setup_kwargs: dict[str, Any] = {}
self.setup_kwargs['long_description_content_type'] = 'text/markdown'
self.setup_kwargs['keywords'] = _pyproject_data["keywords"]
@@ -87,15 +89,15 @@ class Config(object):
self.setup_kwargs['classifiers'] = self.classifiers
def init_config(self,
- build_type=None,
- internal_build_type=None,
+ build_type="",
+ internal_build_type="",
cmd_class_dict=None,
package_version=None,
ext_modules=None,
- setup_script_dir=None,
- cmake_toolchain_file=None,
+ setup_script_dir: str | os.PathLike = "",
+ cmake_toolchain_file: str | os.PathLike = "",
log_level=LogLevel.INFO,
- qt_install_path: Path = None):
+ qt_install_dir: str | os.PathLike = ""):
"""
Sets up the global singleton config which is used in many parts
of the setup process.
@@ -182,8 +184,8 @@ class Config(object):
self.setup_kwargs['install_requires'] = [
f"{self.shiboken_module_st_name}=={package_version}"
]
- if qt_install_path:
- _pyside_tools = available_pyside_tools(qt_tools_path=qt_install_path)
+ if qt_install_dir:
+ _pyside_tools = available_pyside_tools(qt_tools_path=Path(qt_install_dir))
# replacing pyside6-android_deploy by pyside6-android-deploy for consistency
# Also, the tool should not exist in any other platform than Linux and macOS
@@ -209,31 +211,23 @@ class Config(object):
elif self.is_internal_pyside_build():
readme_filename = f'README.{PYSIDE}.md'
- content = ''
- changes = ''
- try:
- with open(self.setup_script_dir / readme_filename) as f:
- readme = f.read()
- except Exception as e:
- log.error(f"Couldn't read contents of {readme_filename}. {e}")
- raise
+ with open(Path(self.setup_script_dir) / readme_filename) as f:
+ readme = f.read()
# Don't include CHANGES.rst for now, because we have not decided
# how to handle change files yet.
include_changes = False
if include_changes:
try:
- with open(self.setup_script_dir / changes_filename) as f:
+ changes = ''
+ with open(Path(self.setup_script_dir) / changes_filename) as f:
changes = f.read()
except Exception as e:
log.error(f"Couldn't read contents of {changes_filename}. {e}")
raise
- content += readme
-
- if changes:
- content += f"\n\n{changes}"
+ return f"{readme}\n\n{changes}"
- return content
+ return readme
def package_name(self):
"""
diff --git a/build_scripts/main.py b/build_scripts/main.py
index 529229387..57e337ac2 100644
--- a/build_scripts/main.py
+++ b/build_scripts/main.py
@@ -13,7 +13,6 @@ import time
from packaging.version import parse as parse_version
from pathlib import Path
from shutil import copytree, rmtree
-from textwrap import dedent
# PYSIDE-1760: Pre-load setuptools modules early to avoid racing conditions.
# may be touched (should be avoided anyway, btw.)
@@ -40,7 +39,7 @@ from .platforms.windows_desktop import prepare_packages_win32
from .qtinfo import QtInfo
from .utils import (copydir, copyfile, detect_clang,
get_numpy_location, get_python_dict,
- linux_fix_rpaths_for_library, macos_fix_rpaths_for_library,
+ linux_fix_rpaths_for_library, macos_fix_rpaths_for_library, parse_modules,
platform_cmake_options, remove_tree, run_process,
run_process_output, update_env_path, which)
from . import PYSIDE, PYSIDE_MODULE, SHIBOKEN
@@ -490,27 +489,13 @@ class PysideBuild(_build, CommandMixin, BuildInfoCollectorMixin):
log.info(f"Make generator: {self.make_generator}")
log.info(f"Make jobs: {OPTION['JOBS']}")
log.info("-" * 3)
- log.info(f"setup.py directory: {self.script_dir}")
- log.info(f"Build scripts directory: {build_scripts_dir}")
- log.info(f"Sources directory: {self.sources_dir}")
- log.info(dedent(f"""
- Building {config.package_name()} will create and touch directories
- in the following order:
- make build directory ->
- make install directory ->
- setuptools build directory ->
- setuptools install directory
- (usually path-installed-python/lib/python*/site-packages/*)
- """))
+ log.info(f"setup.py directory: {self.script_dir}")
+ log.info(f"Build scripts directory: {build_scripts_dir}")
+ log.info(f"Sources directory: {self.sources_dir}")
log.info(f"make build directory: {self.build_dir}")
log.info(f"make install directory: {self.install_dir}")
log.info(f"setuptools build directory: {self.st_build_dir}")
log.info(f"setuptools install directory: {setuptools_install_prefix}")
- log.info(dedent(f"""
- make-installed site-packages directory: {self.site_packages_dir}
- (only relevant for copying files from 'make install directory'
- to 'setuptools build directory'
- """))
log.info("-" * 3)
log.info(f"Python executable: {self.py_executable}")
log.info(f"Python includes: {self.py_include_dir}")
@@ -662,24 +647,11 @@ class PysideBuild(_build, CommandMixin, BuildInfoCollectorMixin):
f"Path given: {config_dir}")
if OPTION["MODULE_SUBSET"]:
- module_sub_set = ''
- for m in OPTION["MODULE_SUBSET"].split(','):
- if m.startswith('Qt'):
- m = m[2:]
- if module_sub_set:
- module_sub_set += ';'
- module_sub_set += m
- cmake_cmd.append(f"-DMODULES={module_sub_set}")
+ cmake_cmd.append(f"-DMODULES={parse_modules(OPTION['MODULE_SUBSET'])}")
if OPTION["SKIP_MODULES"]:
- skip_modules = ''
- for m in OPTION["SKIP_MODULES"].split(','):
- if m.startswith('Qt'):
- m = m[2:]
- if skip_modules:
- skip_modules += ';'
- skip_modules += m
- cmake_cmd.append(f"-DSKIP_MODULES={skip_modules}")
+ cmake_cmd.append(f"-DSKIP_MODULES={parse_modules(OPTION['SKIP_MODULES'])}")
+
# Add source location for generating documentation
cmake_src_dir = OPTION["QT_SRC"] if OPTION["QT_SRC"] else qt_src_dir
if cmake_src_dir:
@@ -715,17 +687,20 @@ class PysideBuild(_build, CommandMixin, BuildInfoCollectorMixin):
if OPTION['NO_OVERRIDE_OPTIMIZATION_FLAGS']:
cmake_cmd.append("-DQFP_NO_OVERRIDE_OPTIMIZATION_FLAGS=1")
- if OPTION["LIMITED_API"] == "yes":
- cmake_cmd.append("-DFORCE_LIMITED_API=yes")
- elif OPTION["LIMITED_API"] == "no":
- cmake_cmd.append("-DFORCE_LIMITED_API=no")
- elif not OPTION["LIMITED_API"]:
+ if not OPTION["LIMITED_API"]:
if sys.platform == 'win32' and self.debug:
cmake_cmd.append("-DFORCE_LIMITED_API=no")
else:
- raise SetupError("option limited-api must be 'yes' or 'no' "
- "(default yes if applicable, i.e. Python "
- "version >= 3.9 and release build if on Windows)")
+ if OPTION["LIMITED_API"].lower() in ("yes", "y", "1", "true"):
+ cmake_cmd.append("-DFORCE_LIMITED_API=yes")
+ elif OPTION["LIMITED_API"].lower() in ("no", "n", "0", "false"):
+ cmake_cmd.append("-DFORCE_LIMITED_API=no")
+ else:
+ raise SetupError(
+ "Option '--limited-api' must be 'yes' or 'no'."
+ f"Default is yes if Python version >= {get_allowed_python_versions()[0]} "
+ "and Release build on Windows"
+ )
if OPTION["DISABLE_PYI"]:
cmake_cmd.append("-DDISABLE_PYI=yes")
diff --git a/build_scripts/options.py b/build_scripts/options.py
index f20e79167..dae72faa2 100644
--- a/build_scripts/options.py
+++ b/build_scripts/options.py
@@ -307,7 +307,7 @@ class CommandMixin(object):
self.shiboken_target_path = None
self.python_target_path = None
self.is_cross_compile = False
- self.cmake_toolchain_file = None
+ self.cmake_toolchain_file: str = ""
self.make_spec = None
self.macos_arch = None
self.macos_sysroot = None
@@ -379,7 +379,7 @@ class CommandMixin(object):
# 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
+ cmake_toolchain_file: str = ""
if OPTION["CMAKE_TOOLCHAIN_FILE"]:
self.is_cross_compile = True
using_cmake_toolchain_file = True
diff --git a/build_scripts/qtinfo.py b/build_scripts/qtinfo.py
index f78f1f9ff..50231a942 100644
--- a/build_scripts/qtinfo.py
+++ b/build_scripts/qtinfo.py
@@ -32,7 +32,7 @@ class QtInfo(object):
self._force_qmake = False
self._use_cmake = False
self._qt_target_path = None
- self._cmake_toolchain_file = None
+ self._cmake_toolchain_file: str = ""
# Dict to cache qmake values.
self._query_dict = {}
diff --git a/build_scripts/setup_runner.py b/build_scripts/setup_runner.py
index e8b97afcb..8d79496a9 100644
--- a/build_scripts/setup_runner.py
+++ b/build_scripts/setup_runner.py
@@ -188,7 +188,7 @@ class SetupRunner(object):
setup_script_dir=self.setup_script_dir,
cmake_toolchain_file=OPTION["CMAKE_TOOLCHAIN_FILE"],
log_level=OPTION["LOG_LEVEL"],
- qt_install_path=qt_install_path)
+ qt_install_dir=qt_install_path)
# Enable logging for both the top-level invocation of setup.py
# as well as for child invocations. We we now use
diff --git a/build_scripts/utils.py b/build_scripts/utils.py
index 9d021c81d..ce8b0a246 100644
--- a/build_scripts/utils.py
+++ b/build_scripts/utils.py
@@ -1125,3 +1125,14 @@ def copy_qt_metatypes(destination_qt_dir, _vars):
def in_coin():
return os.environ.get('COIN_LAUNCH_PARAMETERS', None) is not None
+
+
+def parse_modules(modules: str) -> str:
+ module_sub_set = ""
+ for m in modules.split(','):
+ if m.startswith('Qt'):
+ m = m[2:]
+ if module_sub_set:
+ module_sub_set += ';'
+ module_sub_set += m
+ return module_sub_set