diff options
Diffstat (limited to 'build_scripts/platforms/windows_desktop.py')
-rw-r--r-- | build_scripts/platforms/windows_desktop.py | 291 |
1 files changed, 148 insertions, 143 deletions
diff --git a/build_scripts/platforms/windows_desktop.py b/build_scripts/platforms/windows_desktop.py index 9dbdd794e..9c29953be 100644 --- a/build_scripts/platforms/windows_desktop.py +++ b/build_scripts/platforms/windows_desktop.py @@ -1,31 +1,37 @@ # 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 -import fnmatch import functools import os +import tempfile +from pathlib import Path + +from ..log import log from ..config import config from ..options import OPTION -from ..utils import (copydir, copyfile, download_and_extract_7z, filter_match, - makefile) -from ..versions import PYSIDE, SHIBOKEN +from ..utils import (copydir, copyfile, copy_qt_metatypes, + download_and_extract_7z, filter_match, makefile) +from .. import PYSIDE, SHIBOKEN, PYSIDE_WINDOWS_BIN_TOOLS -def prepare_packages_win32(self, _vars): +def prepare_packages_win32(pyside_build, _vars): # For now, debug symbols will not be shipped into the package. copy_pdbs = False pdbs = [] - if (self.debug or self.build_type == 'RelWithDebInfo') and copy_pdbs: + if (pyside_build.debug or pyside_build.build_type == 'RelWithDebInfo') and copy_pdbs: pdbs = ['*.pdb'] + destination_dir = Path("{st_build_dir}/{st_package_name}".format(**_vars)) + destination_qt_dir = destination_dir + log.info("Copying files...") + # <install>/lib/site-packages/{st_package_name}/* -> # <setup>/{st_package_name} # This copies the module .pyd files and various .py files # (__init__, config, git version, etc.) copydir( - "{site_packages_dir}/{st_package_name}", - "{st_build_dir}/{st_package_name}", + "{site_packages_dir}/{st_package_name}", destination_dir, _vars=_vars) if config.is_internal_shiboken_module_build(): @@ -38,15 +44,13 @@ def prepare_packages_win32(self, _vars): # <install>/bin/*.dll -> {st_package_name}/ copydir( - "{install_dir}/bin/", - "{st_build_dir}/{st_package_name}", + "{install_dir}/bin/", destination_qt_dir, _filter=["shiboken*.dll"], recursive=False, _vars=_vars) # <install>/lib/*.lib -> {st_package_name}/ copydir( - "{install_dir}/lib/", - "{st_build_dir}/{st_package_name}", + "{install_dir}/lib/", destination_qt_dir, _filter=["shiboken*.lib"], recursive=False, _vars=_vars) @@ -54,43 +58,37 @@ def prepare_packages_win32(self, _vars): # {shibokengenerator}.pdb file. # Task-number: PYSIDE-615 copydir( - f"{{build_dir}}/{SHIBOKEN}/shibokenmodule", - "{st_build_dir}/{st_package_name}", + f"{{build_dir}}/{SHIBOKEN}/shibokenmodule", destination_dir, _filter=pdbs, recursive=False, _vars=_vars) # pdb files for libshiboken and libpyside copydir( - f"{{build_dir}}/{SHIBOKEN}/libshiboken", - "{st_build_dir}/{st_package_name}", + f"{{build_dir}}/{SHIBOKEN}/libshiboken", destination_dir, _filter=pdbs, recursive=False, _vars=_vars) if config.is_internal_shiboken_generator_build(): # <install>/bin/*.dll -> {st_package_name}/ copydir( - "{install_dir}/bin/", - "{st_build_dir}/{st_package_name}", + "{install_dir}/bin/", destination_dir, _filter=["shiboken*.exe"], recursive=False, _vars=_vars) # Used to create scripts directory. - makefile( - "{st_build_dir}/{st_package_name}/scripts/shiboken_tool.py", - _vars=_vars) + makefile(f"{destination_dir}/scripts/shiboken_tool.py", _vars=_vars) # For setting up setuptools entry points. copyfile( "{install_dir}/bin/shiboken_tool.py", - "{st_build_dir}/{st_package_name}/scripts/shiboken_tool.py", + f"{destination_dir}/scripts/shiboken_tool.py", force=False, _vars=_vars) # @TODO: Fix this .pdb file not to overwrite release # {shibokenmodule}.pdb file. # Task-number: PYSIDE-615 copydir( - f"{{build_dir}}/{SHIBOKEN}/generator", - "{st_build_dir}/{st_package_name}", + f"{{build_dir}}/{SHIBOKEN}/generator", destination_dir, _filter=pdbs, recursive=False, _vars=_vars) @@ -98,102 +96,96 @@ def prepare_packages_win32(self, _vars): # <install>/include/* -> <setup>/{st_package_name}/include copydir( "{install_dir}/include/{cmake_package_name}", - "{st_build_dir}/{st_package_name}/include", + destination_dir / "include", _vars=_vars) if config.is_internal_pyside_build(): # <build>/pyside6/{st_package_name}/*.pdb -> # <setup>/{st_package_name} copydir( - f"{{build_dir}}/{PYSIDE}/{{st_package_name}}", - "{st_build_dir}/{st_package_name}", + f"{{build_dir}}/{PYSIDE}/{{st_package_name}}", destination_dir, _filter=pdbs, recursive=False, _vars=_vars) - makefile( - "{st_build_dir}/{st_package_name}/scripts/__init__.py", - _vars=_vars) + makefile(f"{destination_dir}/scripts/__init__.py", _vars=_vars) # For setting up setuptools entry points - for script in ("pyside_tool.py", "metaobjectdump.py", "project.py", "qml.py"): + for script in ("pyside_tool.py", "metaobjectdump.py", "project.py", "qml.py", + "qtpy2cpp.py", "deploy.py"): src = f"{{install_dir}}/bin/{script}" target = f"{{st_build_dir}}/{{st_package_name}}/scripts/{script}" copyfile(src, target, force=False, _vars=_vars) + for script_dir in ("qtpy2cpp_lib", "deploy_lib", "project"): + src = f"{{install_dir}}/bin/{script_dir}" + target = f"{{st_build_dir}}/{{st_package_name}}/scripts/{script_dir}" + # Exclude subdirectory tests + copydir(src, target, _filter=["*.py", "*.spec", "*.jpg", "*.icns", "*.ico"], + recursive=False, _vars=_vars) + # <install>/bin/*.exe,*.dll -> {st_package_name}/ filters = ["pyside*.exe", "pyside*.dll"] if not OPTION['NO_QT_TOOLS']: - filters.extend(["lrelease.exe", "lupdate.exe", "uic.exe", - "rcc.exe", "qmllint.exe", "qmltyperegistrar.exe" - "assistant.exe", "designer.exe", - "linguist.exe"]) - copydir( - "{install_dir}/bin/", - "{st_build_dir}/{st_package_name}", - _filter=filters, - recursive=False, _vars=_vars) - - # <qt>/lib/metatypes/* -> <setup>/{st_package_name}/lib/metatypes - destination_lib_dir = "{st_build_dir}/{st_package_name}/lib" - copydir("{qt_lib_dir}/metatypes", f"{destination_lib_dir}/metatypes", - _filter=["*.json"], + filters.extend([f"{tool}.exe" for tool in PYSIDE_WINDOWS_BIN_TOOLS]) + copydir("{install_dir}/bin/", destination_qt_dir, + _filter=filters, recursive=False, _vars=_vars) + copy_qt_metatypes(destination_qt_dir, _vars) + # <install>/lib/*.lib -> {st_package_name}/ copydir( - "{install_dir}/lib/", - "{st_build_dir}/{st_package_name}", + "{install_dir}/lib/", destination_dir, _filter=["pyside*.lib"], recursive=False, _vars=_vars) + copydir("{qt_module_json_files_dir}", + destination_qt_dir / "modules", + _filter=["*.json"], _vars=_vars) + # <install>/share/{st_package_name}/typesystems/* -> # <setup>/{st_package_name}/typesystems copydir( "{install_dir}/share/{st_package_name}/typesystems", - "{st_build_dir}/{st_package_name}/typesystems", + destination_dir / "typesystems", _vars=_vars) # <install>/share/{st_package_name}/glue/* -> # <setup>/{st_package_name}/glue copydir( "{install_dir}/share/{st_package_name}/glue", - "{st_build_dir}/{st_package_name}/glue", + destination_dir / "glue", _vars=_vars) # <source>/pyside6/{st_package_name}/support/* -> # <setup>/{st_package_name}/support/* copydir( f"{{build_dir}}/{PYSIDE}/{{st_package_name}}/support", - "{st_build_dir}/{st_package_name}/support", + destination_dir / "support", + _vars=_vars) + + # <source>/pyside6/{st_package_name}/QtAsyncio/* -> + # <setup>/{st_package_name}/QtAsyncio/* + copydir( + "{site_packages_dir}/{st_package_name}/QtAsyncio", + "{st_build_dir}/{st_package_name}/QtAsyncio", _vars=_vars) # <source>/pyside6/{st_package_name}/*.pyi -> # <setup>/{st_package_name}/*.pyi copydir( - f"{{build_dir}}/{PYSIDE}/{{st_package_name}}", - "{st_build_dir}/{st_package_name}", + f"{{build_dir}}/{PYSIDE}/{{st_package_name}}", destination_dir, _filter=["*.pyi", "py.typed"], _vars=_vars) copydir( - f"{{build_dir}}/{PYSIDE}/libpyside", - "{st_build_dir}/{st_package_name}", + f"{{build_dir}}/{PYSIDE}/libpyside", destination_dir, _filter=pdbs, recursive=False, _vars=_vars) - if not OPTION["NOEXAMPLES"]: - def pycache_dir_filter(dir_name, parent_full_path, dir_full_path): - if fnmatch.fnmatch(dir_name, "__pycache__"): - return False - return True - # examples/* -> <setup>/{st_package_name}/examples - copydir(os.path.join(self.script_dir, "examples"), - "{st_build_dir}/{st_package_name}/examples", - force=False, _vars=_vars, dir_filter_function=pycache_dir_filter) - if _vars['ssl_libs_dir']: # <ssl_libs>/* -> <setup>/{st_package_name}/openssl - copydir("{ssl_libs_dir}", "{st_build_dir}/{st_package_name}/openssl", + copydir("{ssl_libs_dir}", destination_dir / "openssl", _filter=[ "libeay32.dll", "ssleay32.dll"], @@ -202,57 +194,80 @@ def prepare_packages_win32(self, _vars): if config.is_internal_shiboken_module_build(): # The C++ std library dlls need to be packaged with the # shiboken module, because libshiboken uses C++ code. - copy_msvc_redist_files(_vars, "{build_dir}/msvc_redist".format(**_vars)) + copy_msvc_redist_files(destination_dir) if config.is_internal_pyside_build() or config.is_internal_shiboken_generator_build(): - copy_qt_artifacts(self, copy_pdbs, _vars) - copy_msvc_redist_files(_vars, "{build_dir}/msvc_redist".format(**_vars)) - - -def copy_msvc_redist_files(_vars, redist_target_path): - # MSVC redistributable file list. - msvc_redist = [ - "concrt140.dll", - "msvcp140.dll", - "ucrtbase.dll", - "vcamp140.dll", - "vccorlib140.dll", - "vcomp140.dll", - "vcruntime140.dll", - "vcruntime140_1.dll", - "msvcp140_1.dll", - "msvcp140_2.dll", - "msvcp140_codecvt_ids.dll" - ] + copy_qt_artifacts(pyside_build, destination_qt_dir, copy_pdbs, _vars) + copy_msvc_redist_files(destination_dir) + + +# MSVC redistributable file list. +msvc_redist = [ + "concrt140.dll", + "msvcp140.dll", + "vcamp140.dll", + "vccorlib140.dll", + "vcomp140.dll", + "vcruntime140.dll", + "vcruntime140_1.dll", + "msvcp140_1.dll", + "msvcp140_2.dll", + "msvcp140_codecvt_ids.dll" +] + + +def copy_msvc_redist_files(destination_dir): + in_coin = os.environ.get('COIN_LAUNCH_PARAMETERS', None) + if in_coin is None: + log.info("Qt dependency DLLs (MSVC redist) will not be copied.") + return # Make a directory where the files should be extracted. - if not os.path.exists(redist_target_path): - os.makedirs(redist_target_path) + if not destination_dir.exists(): + destination_dir.mkdir(parents=True) + + # Copy Qt dependency DLLs (MSVC) from PATH when building on Qt CI. + paths = os.environ["PATH"].split(os.pathsep) + for path in paths: + try: + for f in Path(path).glob("*140*.dll"): + if f.name in msvc_redist: + copyfile(f, Path(destination_dir) / f.name) + msvc_redist.remove(f.name) + if not msvc_redist: + break + except WindowsError: + continue + + if msvc_redist: + msg = "The following Qt dependency DLLs (MSVC redist) were not found: {msvc_redist}" + raise FileNotFoundError(msg) + +def copy_qt_dependency_dlls(_vars, destination_qt_dir, artifacts): # Extract Qt dependency dlls when building on Qt CI. in_coin = os.environ.get('COIN_LAUNCH_PARAMETERS', None) - if in_coin is not None: + if in_coin is None: + log.info("Qt dependency DLLs will not be downloaded and extracted.") + return + + with tempfile.TemporaryDirectory() as temp_path: redist_url = "https://download.qt.io/development_releases/prebuilt/vcredist/" zip_file = "pyside_qt_deps_64_2019.7z" if "{target_arch}".format(**_vars) == "32": zip_file = "pyside_qt_deps_32_2019.7z" try: - download_and_extract_7z(redist_url + zip_file, redist_target_path) + download_and_extract_7z(redist_url + zip_file, temp_path) except Exception as e: - print(f"Download failed: {type(e).__name__}: {e}") - print("download.qt.io is down, try with mirror") + log.warning(f"Download failed: {type(e).__name__}: {e}") + log.warning("download.qt.io is down, try with mirror") redist_url = "https://master.qt.io/development_releases/prebuilt/vcredist/" - download_and_extract_7z(redist_url + zip_file, redist_target_path) - else: - print("Qt dependency DLLs (MSVC redist) will not be downloaded and extracted.") - - copydir(redist_target_path, - "{st_build_dir}/{st_package_name}", - _filter=msvc_redist, recursive=False, _vars=_vars) + download_and_extract_7z(redist_url + zip_file, temp_path) + copydir(temp_path, destination_qt_dir, _filter=artifacts, recursive=False, _vars=_vars) -def copy_qt_artifacts(self, copy_pdbs, _vars): - built_modules = self.get_built_pyside_config(_vars)['built_modules'] +def copy_qt_artifacts(pyside_build, destination_qt_dir, copy_pdbs, _vars): + built_modules = pyside_build.get_built_pyside_config(_vars)['built_modules'] constrain_modules = None copy_plugins = True @@ -260,7 +275,6 @@ def copy_qt_artifacts(self, copy_pdbs, _vars): copy_translations = True copy_qt_conf = True copy_qt_permanent_artifacts = True - copy_msvc_redist = False copy_clang = False if config.is_internal_shiboken_generator_build(): @@ -270,13 +284,16 @@ def copy_qt_artifacts(self, copy_pdbs, _vars): copy_translations = False copy_qt_conf = False copy_qt_permanent_artifacts = False - copy_msvc_redist = True copy_clang = True # <qt>/bin/*.dll and Qt *.exe -> <setup>/{st_package_name} qt_artifacts_permanent = [ + "avcodec-60.dll", + "avformat-60.dll", + "avutil-58.dll", + "swresample-4.dll", + "swscale-7.dll", "opengl*.dll", - "d3d*.dll", "designer.exe", "linguist.exe", "lrelease.exe", @@ -290,30 +307,17 @@ def copy_qt_artifacts(self, copy_pdbs, _vars): "libEGL{}.dll", "libGLESv2{}.dll" ] - if self.qtinfo.build_type != 'debug_and_release': + if pyside_build.qtinfo.build_type != 'debug_and_release': egl_suffix = '*' - elif self.debug: + elif pyside_build.debug: egl_suffix = 'd' else: egl_suffix = '' qt_artifacts_egl = [a.format(egl_suffix) for a in qt_artifacts_egl] - artifacts = [] if copy_qt_permanent_artifacts: - artifacts += qt_artifacts_permanent - artifacts += qt_artifacts_egl - - if copy_msvc_redist: - # The target path has to be qt_bin_dir at the moment, - # because the extracted archive also contains the opengl32sw - # and the d3dcompiler dlls, which are copied not by this - # function, but by the copydir below. - copy_msvc_redist_files(_vars, "{qt_bin_dir}".format(**_vars)) - - if artifacts: - copydir("{qt_bin_dir}", - "{st_build_dir}/{st_package_name}", - _filter=artifacts, recursive=False, _vars=_vars) + artifacts = qt_artifacts_permanent + qt_artifacts_egl + copy_qt_dependency_dlls(_vars, destination_qt_dir, artifacts) # <qt>/bin/*.dll and Qt *.pdbs -> <setup>/{st_package_name} part two # File filter to copy only debug or only release files. @@ -333,11 +337,15 @@ def copy_qt_artifacts(self, copy_pdbs, _vars): # If qt is not a debug_and_release build, that means there # is only one set of shared libraries, so we can just copy # them. - if self.qtinfo.build_type != 'debug_and_release': + if pyside_build.qtinfo.build_type != 'debug_and_release': if filter_match(file_name, release): return True return False + # Setup Paths + file_name = Path(file_name) + file_full_path = Path(file_full_path) + # In debug_and_release case, choosing which files to copy # is more difficult. We want to copy only the files that # match the PySide6 build type. So if PySide6 is built in @@ -352,23 +360,24 @@ def copy_qt_artifacts(self, copy_pdbs, _vars): # file is a debug or release file. # e.g. ["Qt6Cored", ".dll"] - file_base_name, file_ext = os.path.splitext(file_name) + file_base_name = file_name.stem + file_ext = file_name.suffix # e.g. "/home/work/qt/qtbase/bin" - file_path_dir_name = os.path.dirname(file_full_path) + file_path_dir_name = file_full_path.parent # e.g. "Qt6Coredd" maybe_debug_name = f"{file_base_name}d" - if self.debug: + if pyside_build.debug: _filter = debug def predicate(path): - return not os.path.exists(path) + return not path.exists() else: _filter = release def predicate(path): - return os.path.exists(path) + return path.exists() # e.g. "/home/work/qt/qtbase/bin/Qt6Coredd.dll" - other_config_path = os.path.join(file_path_dir_name, maybe_debug_name + file_ext) + other_config_path = file_path_dir_name / (maybe_debug_name + file_ext) if (filter_match(file_name, _filter) and predicate(other_config_path)): return True @@ -376,15 +385,14 @@ def copy_qt_artifacts(self, copy_pdbs, _vars): qt_dll_filter = functools.partial(qt_build_config_filter, qt_dll_patterns) - copydir("{qt_bin_dir}", - "{st_build_dir}/{st_package_name}", + copydir("{qt_bin_dir}", destination_qt_dir, file_filter_function=qt_dll_filter, recursive=False, _vars=_vars) if copy_plugins: - is_pypy = "pypy" in self.build_classifiers + is_pypy = "pypy" in pyside_build.build_classifiers # <qt>/plugins/* -> <setup>/{st_package_name}/plugins - plugins_target = "{st_build_dir}/{st_package_name}/plugins" + plugins_target = f"{destination_qt_dir}/plugins" plugin_dll_patterns = ["*{}.dll"] pdb_pattern = "*{}.pdb" if copy_pdbs: @@ -402,8 +410,7 @@ def copy_qt_artifacts(self, copy_pdbs, _vars): if copy_translations: # <qt>/translations/* -> <setup>/{st_package_name}/translations - copydir("{qt_translations_dir}", - "{st_build_dir}/{st_package_name}/translations", + copydir("{qt_translations_dir}", f"{destination_qt_dir}/translations", _filter=["*.qm", "*.pak"], force=False, _vars=_vars) @@ -415,7 +422,7 @@ def copy_qt_artifacts(self, copy_pdbs, _vars): qml_ignore = [a.format('') for a in qml_ignore_patterns] # Copy all files that are not dlls and pdbs (.qml, qmldir). - copydir("{qt_qml_dir}", "{st_build_dir}/{st_package_name}/qml", + copydir("{qt_qml_dir}", f"{destination_qt_dir}/qml", ignore=qml_ignore, force=False, recursive=True, @@ -426,31 +433,29 @@ def copy_qt_artifacts(self, copy_pdbs, _vars): qml_dll_filter = functools.partial(qt_build_config_filter, qml_dll_patterns) # Copy all dlls (and possibly pdbs). - copydir("{qt_qml_dir}", "{st_build_dir}/{st_package_name}/qml", + copydir("{qt_qml_dir}", f"{destination_qt_dir}/qml", file_filter_function=qml_dll_filter, force=False, recursive=True, _vars=_vars) - if self.is_webengine_built(built_modules): - copydir("{qt_data_dir}/resources", - "{st_build_dir}/{st_package_name}/resources", + if pyside_build.is_webengine_built(built_modules): + copydir("{qt_data_dir}/resources", f"{destination_qt_dir}/resources", _filter=None, recursive=False, _vars=_vars) - _ext = "d" if self.debug else "" + _ext = "d" if pyside_build.debug else "" _filter = [f"QtWebEngineProcess{_ext}.exe"] - copydir("{qt_bin_dir}", - "{st_build_dir}/{st_package_name}", + copydir("{qt_bin_dir}", destination_qt_dir, _filter=_filter, recursive=False, _vars=_vars) if copy_qt_conf: # Copy the qt.conf file to prefix dir. copyfile(f"{{build_dir}}/{PYSIDE}/{{st_package_name}}/qt.conf", - "{st_build_dir}/{st_package_name}", + destination_qt_dir, _vars=_vars) if copy_clang: - self.prepare_standalone_clang(is_win=True) + pyside_build.prepare_standalone_clang(is_win=True) |