############################################################################# ## ## 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$ ## ############################################################################# import functools import os, re, sys from ..options import * from ..utils import copydir, copyfile, rmtree, makefile from ..utils import regenerate_qt_resources, filter_match from ..utils import download_and_extract_7z def prepare_packages_win32(self, 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: pdbs = ['*.pdb'] # /lib/site-packages/PySide2/* -> /PySide2 copydir( "{site_packages_dir}/PySide2", "{pyside_package_dir}/PySide2", vars=vars) built_modules = self.get_built_pyside_config(vars)['built_modules'] # /pyside2/PySide2/*.pdb -> /PySide2 copydir( "{build_dir}/pyside2/PySide2", "{pyside_package_dir}/PySide2", filter=pdbs, recursive=False, vars=vars) # /shiboken2/doc/html/* -> # /PySide2/docs/shiboken2 copydir( "{build_dir}/shiboken2/doc/html", "{pyside_package_dir}/PySide2/docs/shiboken2", force=False, vars=vars) # /lib/site-packages/shiboken2.pyd -> # /PySide2/shiboken2.pyd shiboken_module_name = 'shiboken2.pyd' shiboken_src_path = "{site_packages_dir}".format(**vars) maybe_shiboken_names = [f for f in os.listdir(shiboken_src_path) if re.match(r'shiboken.*\.pyd', f)] if maybe_shiboken_names: shiboken_module_name = maybe_shiboken_names[0] vars.update({'shiboken_module_name': shiboken_module_name}) copyfile( "{site_packages_dir}/{shiboken_module_name}", "{pyside_package_dir}/PySide2/{shiboken_module_name}", vars=vars) # @TODO: Fix this .pdb file not to overwrite release # {shibokengenerator}.pdb file. # Task-number: PYSIDE-615 copydir( "{build_dir}/shiboken2/shibokenmodule", "{pyside_package_dir}/PySide2", filter=pdbs, recursive=False, vars=vars) # /lib/site-packages/pyside2uic/* -> # /pyside2uic copydir( "{site_packages_dir}/pyside2uic", "{pyside_package_dir}/pyside2uic", force=False, vars=vars) if sys.version_info[0] > 2: rmtree("{pyside_package_dir}/pyside2uic/port_v2".format(**vars)) else: rmtree("{pyside_package_dir}/pyside2uic/port_v3".format(**vars)) # /bin/pyside2-uic -> PySide2/scripts/uic.py makefile( "{pyside_package_dir}/PySide2/scripts/__init__.py", vars=vars) copyfile( "{install_dir}/bin/pyside2-uic", "{pyside_package_dir}/PySide2/scripts/uic.py", force=False, vars=vars) # /bin/*.exe,*.dll,*.pdb -> PySide2/ copydir( "{install_dir}/bin/", "{pyside_package_dir}/PySide2", filter=["*.exe", "*.dll"], recursive=False, vars=vars) # @TODO: Fix this .pdb file not to overwrite release # {shibokenmodule}.pdb file. # Task-number: PYSIDE-615 copydir( "{build_dir}/shiboken2/generator", "{pyside_package_dir}/PySide2", filter=pdbs, recursive=False, vars=vars) # /lib/*.lib -> PySide2/ copydir( "{install_dir}/lib/", "{pyside_package_dir}/PySide2", filter=["*.lib"], recursive=False, vars=vars) # /share/PySide2/typesystems/* -> # /PySide2/typesystems copydir( "{install_dir}/share/PySide2/typesystems", "{pyside_package_dir}/PySide2/typesystems", vars=vars) # /include/* -> /PySide2/include copydir( "{install_dir}/include", "{pyside_package_dir}/PySide2/include", vars=vars) # /pyside2/PySide2/support/* -> # /PySide2/support/* copydir( "{build_dir}/pyside2/PySide2/support", "{pyside_package_dir}/PySide2/support", vars=vars) if not OPTION_NOEXAMPLES: # examples/* -> /PySide2/examples copydir(os.path.join(self.script_dir, "examples"), "{pyside_package_dir}/PySide2/examples", force=False, vars=vars) # Re-generate examples Qt resource files for Python 3 # compatibility if sys.version_info[0] == 3: examples_path = "{pyside_package_dir}/PySide2/examples".format( **vars) pyside_rcc_path = "{install_dir}/bin/pyside2-rcc".format( **vars) pyside_rcc_options = '-py3' regenerate_qt_resources(examples_path, pyside_rcc_path, pyside_rcc_options) # /* -> /PySide2/openssl copydir("{ssl_libs_dir}", "{pyside_package_dir}/PySide2/openssl", filter=[ "libeay32.dll", "ssleay32.dll"], force=False, vars=vars) # /bin/*.dll and Qt *.exe -> /PySide2 qt_artifacts_permanent = [ "opengl*.dll", "d3d*.dll", "designer.exe", "linguist.exe", "lrelease.exe", "lupdate.exe", "lconvert.exe", "qtdiag.exe" ] # MSVC redistributable msvc_redist = [ "concrt140.dll", "msvcp140.dll", "ucrtbase.dll", "vcamp140.dll", "vccorlib140.dll", "vcomp140.dll" , "vcruntime140.dll" ] # Choose which EGL library variants to copy. qt_artifacts_egl = [ "libEGL{}.dll", "libGLESv2{}.dll" ] if self.qtinfo.build_type != 'debug_and_release': egl_suffix = '*' elif self.debug: egl_suffix = 'd' else: egl_suffix = '' qt_artifacts_egl = [a.format(egl_suffix) for a in qt_artifacts_egl] qt_artifacts_permanent += qt_artifacts_egl qt_artifacts_permanent += msvc_redist # Extract Qt dependency dll's when building on Qt CI # There is no proper CI env variable, so using agent launch params in_coin = os.environ.get('COIN_LAUNCH_PARAMETERS', None) if in_coin is not None: redist_url = "http://download.qt.io/development_releases/prebuilt/vcredist//" zip_file = "pyside_qt_deps_64.7z" if "{target_arch}".format(**vars) == "32": zip_file = "pyside_qt_deps_32.7z" download_and_extract_7z(redist_url + zip_file, "{qt_bin_dir}".format(**vars)) copydir("{qt_bin_dir}", "{pyside_package_dir}/PySide2", filter=qt_artifacts_permanent, recursive=False, vars=vars) # /bin/*.dll and Qt *.pdbs -> /PySide2 part two # File filter to copy only debug or only release files. qt_dll_patterns = ["Qt5*{}.dll", "lib*{}.dll"] if copy_pdbs: qt_dll_patterns += ["Qt5*{}.pdb", "lib*{}.pdb"] def qt_build_config_filter(patterns, file_name, file_full_path): release = [a.format('') for a in patterns] debug = [a.format('d') for a in patterns] # 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 filter_match(file_name, release): return True return False # In debug_and_release case, choosing which files to copy # is more difficult. We want to copy only the files that # match the PySide2 build type. So if PySide2 is built in # debug mode, we want to copy only Qt debug libraries # (ending with "d.dll"). Or vice versa. The problem is that # some libraries have "d" as the last character of the # actual library name (for example Qt5Gamepad.dll and # Qt5Gamepadd.dll). So we can't just match a pattern ending # in "d". Instead we check if there exists a file with the # same name plus an additional "d" at the end, and using # that information we can judge if the currently processed # file is a debug or release file. # e.g. ["Qt5Cored", ".dll"] file_split = os.path.splitext(file_name) file_base_name = file_split[0] file_ext = file_split[1] # e.g. "/home/work/qt/qtbase/bin" file_path_dir_name = os.path.dirname(file_full_path) # e.g. "Qt5Coredd" maybe_debug_name = file_base_name + 'd' if self.debug: filter = debug def predicate(path): return not os.path.exists(path) else: filter = release def predicate(path): return os.path.exists(path) # e.g. "/home/work/qt/qtbase/bin/Qt5Coredd.dll" other_config_path = os.path.join(file_path_dir_name, maybe_debug_name + file_ext) if (filter_match(file_name, filter) and predicate(other_config_path)): return True return False qt_dll_filter = functools.partial(qt_build_config_filter, qt_dll_patterns) copydir("{qt_bin_dir}", "{pyside_package_dir}/PySide2", file_filter_function=qt_dll_filter, recursive=False, vars=vars) # /plugins/* -> /PySide2/plugins plugin_dll_patterns = ["*{}.dll"] pdb_pattern = "*{}.pdb" if copy_pdbs: plugin_dll_patterns += [pdb_pattern] plugin_dll_filter = functools.partial(qt_build_config_filter, plugin_dll_patterns) copydir("{qt_plugins_dir}", "{pyside_package_dir}/PySide2/plugins", file_filter_function=plugin_dll_filter, vars=vars) # /translations/* -> /PySide2/translations copydir("{qt_translations_dir}", "{pyside_package_dir}/PySide2/translations", filter=["*.qm", "*.pak"], force=False, vars=vars) # /qml/* -> /PySide2/qml qml_dll_patterns = ["*{}.dll"] qml_ignore_patterns = qml_dll_patterns + [pdb_pattern] 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}", "{pyside_package_dir}/PySide2/qml", ignore=qml_ignore, force=False, recursive=True, vars=vars) if copy_pdbs: qml_dll_patterns += [pdb_pattern] qml_dll_filter = functools.partial(qt_build_config_filter, qml_dll_patterns) # Copy all dlls (and possibly pdbs). copydir("{qt_qml_dir}", "{pyside_package_dir}/PySide2/qml", file_filter_function=qml_dll_filter, force=False, recursive=True, vars=vars) if self.is_webengine_built(built_modules): copydir("{qt_prefix_dir}/resources", "{pyside_package_dir}/PySide2/resources", filter=None, recursive=False, vars=vars) filter = 'QtWebEngineProcess{}.exe'.format( 'd' if self.debug else '') copydir("{qt_bin_dir}", "{pyside_package_dir}/PySide2", filter=[filter], recursive=False, vars=vars) # Copy the qt.conf file to prefix dir. copyfile( "{build_dir}/pyside2/PySide2/qt.conf", "{pyside_package_dir}/PySide2", vars=vars) self.prepare_standalone_clang(is_win=True) # pdb files for libshiboken and libpyside copydir( "{build_dir}/shiboken2/libshiboken", "{pyside_package_dir}/PySide2", filter=pdbs, recursive=False, vars=vars) copydir( "{build_dir}/pyside2/libpyside", "{pyside_package_dir}/PySide2", filter=pdbs, recursive=False, vars=vars)