def getScanDirectories(package_name, original_dir): cache_key = package_name, original_dir if cache_key in _scan_dir_cache: return _scan_dir_cache[cache_key] scan_dirs = [sys.prefix] if package_name is not None: from nuitka.importing.Importing import findModule package_dir = findModule(None, package_name, None, 0, False)[1] if os.path.isdir(package_dir): scan_dirs.append(package_dir) scan_dirs.extend(getSubDirectories(package_dir)) if original_dir is not None: scan_dirs.append(original_dir) scan_dirs.extend(getSubDirectories(original_dir)) for path_dir in os.environ["PATH"].split(";"): if not os.path.isdir(path_dir): continue if areSamePaths(path_dir, os.path.join(os.environ["SYSTEMROOT"])): continue if areSamePaths(path_dir, os.path.join(os.environ["SYSTEMROOT"], "System32")): continue if areSamePaths(path_dir, os.path.join(os.environ["SYSTEMROOT"], "SysWOW64")): continue scan_dirs.append(path_dir) result = [] # Remove directories that hold no DLLs. for scan_dir in scan_dirs: sys.stdout.flush() # These are useless, but plenty. if os.path.basename(scan_dir) == "__pycache__": continue # No DLLs, no use. if not any(entry[1].lower().endswith(".dll") for entry in listDir(scan_dir)): continue result.append(scan_dir) _scan_dir_cache[cache_key] = result return result
def getScanDirectories(package_name, original_dir): # Many cases, pylint: disable=too-many-branches cache_key = package_name, original_dir if cache_key in _scan_dir_cache: return _scan_dir_cache[cache_key] scan_dirs = [sys.prefix] if package_name is not None: scan_dirs.extend(_getPackageSpecificDLLDirectories(package_name)) if original_dir is not None: scan_dirs.append(original_dir) scan_dirs.extend(getSubDirectories(original_dir)) if (Utils.isWin32Windows() and package_name is not None and package_name.isBelowNamespace("win32com")): pywin32_dir = getPyWin32Dir() if pywin32_dir is not None: scan_dirs.append(pywin32_dir) for path_dir in os.environ["PATH"].split(";"): if not os.path.isdir(path_dir): continue if areSamePaths(path_dir, os.path.join(os.environ["SYSTEMROOT"])): continue if areSamePaths(path_dir, os.path.join(os.environ["SYSTEMROOT"], "System32")): continue if areSamePaths(path_dir, os.path.join(os.environ["SYSTEMROOT"], "SysWOW64")): continue scan_dirs.append(path_dir) result = [] # Remove directories that hold no DLLs. for scan_dir in scan_dirs: sys.stdout.flush() # These are useless, but plenty. if os.path.basename(scan_dir) == "__pycache__": continue scan_dir = getDirectoryRealPath(scan_dir) # No DLLs, no use. if not any(entry[1].lower().endswith(".dll") for entry in listDir(scan_dir)): continue result.append(os.path.realpath(scan_dir)) _scan_dir_cache[cache_key] = result return result
def considerExtraDlls(self, dist_dir, module): full_name = module.getFullName() if full_name in ("PyQt4", "PyQt5"): qt_version = int(full_name[-1]) plugin_dir, = self.getPyQtPluginDirs(qt_version) target_plugin_dir = os.path.join( dist_dir, full_name, "qt-plugins" ) shutil.copytree( plugin_dir, target_plugin_dir ) plugin_options = self.getPluginOptions() if not plugin_options: plugin_options.append("all") if plugin_options == ["sensible"]: plugin_options = ["imageformats", "iconengines", "mediaservice", "printsupport"] info( "Copying '%s' Qt plug-ins to '%s'." % ( ','.join(plugin_options), target_plugin_dir ) ) if "all" not in plugin_options: for plugin_candidate in getSubDirectories(target_plugin_dir): if os.path.basename(plugin_candidate) not in plugin_options: removeDirectory(plugin_candidate, ignore_errors = False) for plugin_candidate in plugin_options: if not os.path.isdir(os.path.join(target_plugin_dir, plugin_candidate)): sys.exit("Error, no such Qt plugin family: %s" % plugin_candidate) return [ ( filename, os.path.join(target_plugin_dir, os.path.relpath(filename, plugin_dir)), full_name ) for filename in getFileList(plugin_dir) if not filename.endswith(".qml") if os.path.exists(os.path.join(target_plugin_dir, os.path.relpath(filename, plugin_dir))) ] return ()
def getPackageSpecificDLLDirectories(package_name): scan_dirs = OrderedSet() if package_name is not None: from nuitka.importing.Importing import findModule package_dir = findModule(None, package_name, None, 0, False)[1] if os.path.isdir(package_dir): scan_dirs.add(package_dir) scan_dirs.update( getSubDirectories(package_dir, ignore_dirs=("__pycache__", ))) scan_dirs.update(Plugins.getModuleSpecificDllPaths(package_name)) return scan_dirs
def _getPackageSpecificDLLDirectories(package_name): scan_dirs = OrderedSet() if package_name is not None: package_dir = locateModule(module_name=package_name, parent_package=None, level=0)[1] if os.path.isdir(package_dir): scan_dirs.add(package_dir) scan_dirs.update( getSubDirectories(package_dir, ignore_dirs=("__pycache__", ))) scan_dirs.update(Plugins.getModuleSpecificDllPaths(package_name)) return scan_dirs
def considerExtraDlls(self, dist_dir, module): # pylint: disable=too-many-branches,too-many-locals,too-many-statements full_name = module.getFullName() elements = full_name.split(".") plugin_dirs = None if elements[0] in ("PyQt4", "PyQt5"): qt_version = int(elements[0][-1]) plugin_dirs = self.getPyQtPluginDirs(qt_version) if full_name in ("PyQt4", "PyQt5"): if not plugin_dirs: sys.exit("Error, failed to detect %s plugin directories." % full_name) target_plugin_dir = os.path.join(dist_dir, full_name, "qt-plugins") plugin_options = set(self.qt_plugins.split(",")) if "sensible" in plugin_options: # Most used ones with low dependencies. plugin_options.update( tuple( family for family in ( "imageformats", "iconengines", "mediaservice", "printsupport", "platforms", ) if self.hasPluginFamily(plugin_dirs, family) ) ) plugin_options.remove("sensible") # Make sure the above didn't detect nothing, which would be # indicating the check to be bad. assert plugin_options self.info( "Copying Qt plug-ins '%s' to '%s'." % ( ",".join(sorted(x for x in plugin_options if x != "xml")), target_plugin_dir, ) ) for plugin_dir in plugin_dirs: copyTree(plugin_dir, target_plugin_dir) if "all" not in plugin_options: for plugin_candidate in getSubDirectories(target_plugin_dir): if os.path.basename(plugin_candidate) not in plugin_options: removeDirectory(plugin_candidate, ignore_errors=False) for plugin_candidate in plugin_options: if plugin_candidate == "qml": continue if not os.path.isdir( os.path.join(target_plugin_dir, plugin_candidate) ): sys.exit( "Error, no such Qt plugin family: %s" % plugin_candidate ) result = [ ( filename, os.path.join( target_plugin_dir, os.path.relpath(filename, plugin_dir) ), full_name, ) for plugin_dir in plugin_dirs for filename in getFileList(plugin_dir) if not filename.endswith(".qml") if os.path.exists( os.path.join( target_plugin_dir, os.path.relpath(filename, plugin_dir) ) ) ] if isWin32Windows(): # Those 2 vars will be used later, just saving some resources # by caching the files list qt_bin_files = sum( ( getFileList(qt_bin_dir) for qt_bin_dir in self._getQtBinDirs(plugin_dirs) ), [], ) self.info("Copying OpenSSL DLLs to %r." % dist_dir) for filename in qt_bin_files: basename = os.path.basename(filename).lower() if basename in ("libeay32.dll", "ssleay32.dll"): shutil.copy(filename, os.path.join(dist_dir, basename)) if "qml" in plugin_options or "all" in plugin_options: for plugin_dir in plugin_dirs: qml_plugin_dir = os.path.normpath( os.path.join(plugin_dir, "..", "qml") ) if os.path.exists(qml_plugin_dir): break else: sys.exit("Error, no such Qt plugin family: qml") qml_target_dir = os.path.normpath( os.path.join(target_plugin_dir, "..", "Qt", "qml") ) self.info("Copying Qt plug-ins 'xml' to '%s'." % (qml_target_dir)) copyTree(qml_plugin_dir, qml_target_dir) # We try to filter here, not for DLLs. result += [ ( filename, os.path.join( qml_target_dir, os.path.relpath(filename, qml_plugin_dir) ), full_name, ) for filename in getFileList(qml_plugin_dir) if not filename.endswith( ( ".qml", ".qmlc", ".qmltypes", ".js", ".jsc", ".png", ".ttf", ".metainfo", ) ) if not os.path.isdir(filename) if not os.path.basename(filename) == "qmldir" ] # Also copy required OpenGL DLLs on Windows if isWin32Windows(): opengl_dlls = ("libegl.dll", "libglesv2.dll", "opengl32sw.dll") self.info("Copying OpenGL DLLs to %r." % dist_dir) for filename in qt_bin_files: basename = os.path.basename(filename).lower() if basename in opengl_dlls or basename.startswith( "d3dcompiler_" ): shutil.copy(filename, os.path.join(dist_dir, basename)) return result elif full_name == "PyQt5.QtNetwork": if not isWin32Windows(): dll_path = locateDLL("crypto") if dll_path is None: dist_dll_path = os.path.join(dist_dir, os.path.basename(dll_path)) shutil.copy(dll_path, dist_dll_path) dll_path = locateDLL("ssl") if dll_path is not None: dist_dll_path = os.path.join(dist_dir, os.path.basename(dll_path)) shutil.copy(dll_path, dist_dll_path) elif ( full_name.startswith(("PyQt4.QtWebEngine", "PyQt5.QtWebEngine")) and not self.webengine_done ): self.webengine_done = True # prevent multiple copies self.info("Copying QtWebEngine components") plugin_parent = os.path.dirname(plugin_dirs[0]) if isWin32Windows(): bin_dir = os.path.join(plugin_parent, "bin") else: # TODO verify this for non-Windows! bin_dir = os.path.join(plugin_parent, "libexec") target_bin_dir = os.path.join(dist_dir) for f in os.listdir(bin_dir): if f.startswith("QtWebEngineProcess"): shutil.copy(os.path.join(bin_dir, f), target_bin_dir) resources_dir = os.path.join(plugin_parent, "resources") target_resources_dir = os.path.join(dist_dir) for f in os.listdir(resources_dir): shutil.copy(os.path.join(resources_dir, f), target_resources_dir) translations_dir = os.path.join(plugin_parent, "translations") pos = len(translations_dir) + 1 target_translations_dir = os.path.join( dist_dir, elements[0], "Qt", "translations" ) for f in getFileList(translations_dir): tar_f = os.path.join(target_translations_dir, f[pos:]) makePath(os.path.dirname(tar_f)) shutil.copyfile(f, tar_f) return ()
def _detectBinaryPathDLLsWindows(is_main_executable, source_dir, original_dir, binary_filename, package_name): # This is complex, as it also includes the caching mechanism # pylint: disable=too-many-locals result = set() cache_filename = _getCacheFilename(is_main_executable, source_dir, original_dir, binary_filename) if os.path.exists(cache_filename ) and not Options.shallNotUseDependsExeCachedResults(): for line in open(cache_filename): line = line.strip() result.add(line) return result # User query should only happen once if at all. with _withLock(): depends_exe = getDependsExePath() scan_dirs = [sys.prefix] if package_name is not None: from nuitka.importing.Importing import findModule package_dir = findModule(None, package_name, None, 0, False)[1] if os.path.isdir(package_dir): scan_dirs.append(package_dir) scan_dirs.extend(getSubDirectories(package_dir)) if original_dir is not None: scan_dirs.append(original_dir) scan_dirs.extend(getSubDirectories(original_dir)) with _withLock(): # The search order by default prefers the system directory, where a # wrong "PythonXX.dll" might be living. with open(binary_filename + ".dwp", 'w') as dwp_file: dwp_file.write( """\ KnownDLLs %(original_dirs)s SysPath 32BitSysDir 16BitSysDir OSDir AppPath SxS """ % { "original_dirs": '\n'.join("UserDir %s" % dirname for dirname in scan_dirs if not os.path.basename(dirname) == "__pycache__" if any(entry[1].lower().endswith(".dll") for entry in listDir(dirname))), }) # Starting the process while locked, so file handles are not duplicated. depends_exe_process = subprocess.Popen( (depends_exe, "-c", "-ot%s" % binary_filename + ".depends", "-d:%s" % binary_filename + ".dwp", "-f1", "-pa1", "-ps1", binary_filename)) # TODO: Exit code should be checked. depends_exe_process.wait() # Opening the result under lock, so it is not getting locked by new processes. with _withLock(): _parseDependsExeOutput(binary_filename + ".depends", result) deleteFile(binary_filename + ".depends", must_exist=True) deleteFile(binary_filename + ".dwp", must_exist=True) if not Options.shallNotStoreDependsExeCachedResults(): with open(cache_filename, 'w') as cache_file: for dll_filename in result: print(dll_filename, file=cache_file) return result
def considerExtraDlls(self, dist_dir, module): # pylint: disable=too-many-branches,too-many-locals,too-many-statements full_name = module.getFullName() if full_name == self.binding_name: if not self.getQtPluginDirs(): self.sysexit( "Error, failed to detect %r plugin directories." % self.binding_name ) target_plugin_dir = os.path.join(dist_dir, full_name.asPath(), "qt-plugins") self.info( "Copying Qt plug-ins '%s' to '%s'." % ( ",".join( sorted(x for x in self.getQtPluginsSelected() if x != "xml") ), target_plugin_dir, ) ) # TODO: Change this to filtering copyTree while it's doing it. for plugin_dir in self.getQtPluginDirs(): copyTree(plugin_dir, target_plugin_dir) if "all" not in self.getQtPluginsSelected(): for plugin_candidate in getSubDirectories(target_plugin_dir): if ( os.path.basename(plugin_candidate) not in self.getQtPluginsSelected() ): removeDirectory(plugin_candidate, ignore_errors=False) for plugin_candidate in self.getQtPluginsSelected(): if plugin_candidate == "qml": continue if not os.path.isdir( os.path.join(target_plugin_dir, plugin_candidate) ): self.sysexit( "Error, no such Qt plugin family: %s" % plugin_candidate ) result = self.findDLLs( full_name=full_name, target_plugin_dir=target_plugin_dir, ) if isWin32Windows(): # Those 2 vars will be used later, just saving some resources # by caching the files list qt_bin_files = sum( (getFileList(qt_bin_dir) for qt_bin_dir in self._getQtBinDirs()), [], ) self.info("Copying OpenSSL DLLs to %r." % dist_dir) for filename in qt_bin_files: basename = os.path.basename(filename).lower() if basename in ("libeay32.dll", "ssleay32.dll"): shutil.copy(filename, os.path.join(dist_dir, basename)) if ( "qml" in self.getQtPluginsSelected() or "all" in self.getQtPluginsSelected() ): result += self.copyQmlFiles( full_name=full_name, target_plugin_dir=target_plugin_dir, ) # Also copy required OpenGL DLLs on Windows if isWin32Windows(): opengl_dlls = ("libegl.dll", "libglesv2.dll", "opengl32sw.dll") self.info("Copying OpenGL DLLs to %r." % dist_dir) for filename in qt_bin_files: basename = os.path.basename(filename).lower() if basename in opengl_dlls or basename.startswith( "d3dcompiler_" ): shutil.copy(filename, os.path.join(dist_dir, basename)) return result elif full_name == self.binding_name + ".QtNetwork": if not isWin32Windows(): dll_path = locateDLL("crypto") if dll_path is not None: dist_dll_path = os.path.join(dist_dir, os.path.basename(dll_path)) shutil.copy(dll_path, dist_dll_path) dll_path = locateDLL("ssl") if dll_path is not None: dist_dll_path = os.path.join(dist_dir, os.path.basename(dll_path)) shutil.copy(dll_path, dist_dll_path) elif ( full_name in ( self.binding_name + ".QtWebEngine", self.binding_name + ".QtWebEngineCore", self.binding_name + ".QtWebEngineWidgets", ) and not self.webengine_done ): self.webengine_done = True # prevent multiple copies self.info("Copying QtWebEngine components") plugin_parent = os.path.dirname(self.getQtPluginDirs()[0]) if isWin32Windows(): bin_dir = os.path.join(plugin_parent, "bin") else: # TODO verify this for non-Windows! bin_dir = os.path.join(plugin_parent, "libexec") target_bin_dir = os.path.join(dist_dir) for f in os.listdir(bin_dir): if f.startswith("QtWebEngineProcess"): shutil.copy(os.path.join(bin_dir, f), target_bin_dir) resources_dir = os.path.join(plugin_parent, "resources") target_resources_dir = os.path.join(dist_dir) for f in os.listdir(resources_dir): shutil.copy(os.path.join(resources_dir, f), target_resources_dir) translations_dir = os.path.join(plugin_parent, "translations") pos = len(translations_dir) + 1 target_translations_dir = os.path.join( dist_dir, full_name.getTopLevelPackageName().asPath(), "Qt", "translations", ) for f in getFileList(translations_dir): tar_f = os.path.join(target_translations_dir, f[pos:]) makePath(os.path.dirname(tar_f)) shutil.copyfile(f, tar_f) return ()
def _detectBinaryPathDLLsWindowsPE(is_main_executable, source_dir, original_dir, binary_filename, package_name): # This is complex, as it also includes the caching mechanism # pylint: disable=too-many-branches,too-many-locals result = set() cache_filename = _getCacheFilename(is_main_executable, source_dir, original_dir, binary_filename) if (os.path.exists(cache_filename) and not Options.shallNotUseDependsExeCachedResults()): for line in getFileContentByLine(cache_filename): line = line.strip() result.add(line) return result scan_dirs = [sys.prefix] if package_name is not None: from nuitka.importing.Importing import findModule package_dir = findModule(None, package_name, None, 0, False)[1] if os.path.isdir(package_dir): scan_dirs.append(package_dir) scan_dirs.extend(getSubDirectories(package_dir)) if os.path.isdir(original_dir): scan_dirs.append(original_dir) scan_dirs.extend(getSubDirectories(original_dir)) if Options.isExperimental("use_pefile_fullrecurse"): try: scan_dirs.extend(getSubDirectories(get_python_lib())) except OSError: print( "Cannot recurse into site-packages for dependencies. Path not found." ) else: # Fix for missing pywin32 inclusion when using pythonwin library, no way to detect that automagically # Since there are more than one dependencies on pywintypes37.dll, let's include this anyway # In recursive mode, using dirname(original_dir) won't always work, hence get_python_lib try: scan_dirs.append(os.path.join(get_python_lib(), "pywin32_system32")) except OSError: pass # Add native system directory based on pe file architecture and os architecture # Python 32: system32 = syswow64 = 32 bits systemdirectory # Python 64: system32 = 64 bits systemdirectory, syswow64 = 32 bits systemdirectory binary_file_is_64bit = _isPE64(binary_filename) python_is_64bit = getArchitecture() == "x86_64" if binary_file_is_64bit is not python_is_64bit: print("Warning: Using Python x64=%s with x64=%s binary dependencies" % (binary_file_is_64bit, python_is_64bit)) if binary_file_is_64bit: # This is actually not useful as of today since we don't compile 32 bits on 64 bits if python_is_64bit: scan_dirs.append(os.path.join(os.environ["SYSTEMROOT"], "System32")) else: scan_dirs.append(os.path.join(os.environ["SYSTEMROOT"], "SysWOW64")) else: scan_dirs.append(os.path.join(os.environ["SYSTEMROOT"], "System32")) if Options.isExperimental("use_pefile_recurse"): # Recursive one level scanning of all .pyd and .dll in the original_dir too # This shall fix a massive list of missing dependencies that may come with included libraries which themselves # need to be scanned for inclusions for root, _, filenames in os.walk(original_dir): for optional_libary in filenames: if optional_libary.endswith( ".dll") or optional_libary.endswith(".pyd"): _parsePEFileOutput(os.path.join(root, optional_libary), scan_dirs, result) _parsePEFileOutput(binary_filename, scan_dirs, result) if not Options.shallNotStoreDependsExeCachedResults(): with open(cache_filename, "w") as cache_file: for dll_filename in result: print(dll_filename, file=cache_file) return result
def considerExtraDlls(self, dist_dir, module): full_name = module.getFullName() if full_name in ("PyQt4", "PyQt5"): qt_version = int(full_name[-1]) plugin_dir, = self.getPyQtPluginDirs(qt_version) target_plugin_dir = os.path.join(dist_dir, full_name, "qt-plugins") plugin_options = self.getPluginOptions() plugin_options = set(plugin_options) if not plugin_options: plugin_options.add("sensible") if "sensible" in plugin_options: # Most used ones with low dependencies. plugin_options.update( tuple( family for family in ( "imageformats", "iconengines", "mediaservice", "printsupport", ) if self.hasPluginFamily(plugin_dir, family) ) ) plugin_options.remove("sensible") # Make sure the above didn't detect nothing, which would be # indicating the check to be bad. assert plugin_options # Seems platforms is required on Windows. if os.name == "nt": plugin_options.add("platforms") info( "Copying Qt plug-ins '%s' to '%s'." % ( ",".join(sorted(x for x in plugin_options if x != "xml")), target_plugin_dir, ) ) shutil.copytree(plugin_dir, target_plugin_dir) if "all" not in plugin_options: for plugin_candidate in getSubDirectories(target_plugin_dir): if os.path.basename(plugin_candidate) not in plugin_options: removeDirectory(plugin_candidate, ignore_errors=False) for plugin_candidate in plugin_options: if plugin_candidate == "qml": continue if not os.path.isdir( os.path.join(target_plugin_dir, plugin_candidate) ): sys.exit( "Error, no such Qt plugin family: %s" % plugin_candidate ) result = [ ( filename, os.path.join( target_plugin_dir, os.path.relpath(filename, plugin_dir) ), full_name, ) for filename in getFileList(plugin_dir) if not filename.endswith(".qml") if os.path.exists( os.path.join( target_plugin_dir, os.path.relpath(filename, plugin_dir) ) ) ] if "qml" in plugin_options or "all" in plugin_options: qml_plugin_dir = os.path.normpath(os.path.join(plugin_dir, "..", "qml")) qml_target_dir = os.path.normpath( os.path.join(target_plugin_dir, "..", "Qt", "qml") ) info("Copying Qt plug-ins 'xml' to '%s'." % (qml_target_dir)) shutil.copytree(qml_plugin_dir, qml_target_dir) # We try to filter here, not for DLLs. result += [ ( filename, os.path.join( qml_target_dir, os.path.relpath(filename, qml_plugin_dir) ), full_name, ) for filename in getFileList(qml_plugin_dir) if not filename.endswith( ( ".qml", ".qmlc", ".qmltypes", ".js", ".jsc", ".png", ".ttf", ".metainfo", ) ) if not os.path.isdir(filename) if not os.path.basename(filename) == "qmldir" ] return result return ()
def _detectBinaryPathDLLsWindows(original_dir, binary_filename, package_name): result = set() depends_exe = getDependsExePath() # The search order by default prefers the system directory, where a # wrong "PythonXX.dll" might be living. with open(binary_filename + ".dwp", 'w') as dwp_file: dwp_file.write("""\ KnownDLLs SysPath AppDir {original_dirs} 32BitSysDir 16BitSysDir OSDir AppPath SxS """.format( original_dirs = ( '\n'.join( "UserDir %s" % dirname for dirname in [original_dir] + getSubDirectories(original_dir) if not os.path.basename(dirname) == "__pycache__" if any(entry[1].lower().endswith(".dll") for entry in listDir(dirname)) ) if original_dir is not None else "" ) ) ) subprocess.call( ( depends_exe, "-c", "-ot%s" % binary_filename + ".depends", "-d:%s" % binary_filename + ".dwp", "-f1", "-pa1", "-ps1", binary_filename ), env = _makeBinaryPathPathDLLSearchEnv(package_name), ) inside = False first = False for line in open(binary_filename + ".depends"): if "| Module Dependency Tree |" in line: inside = True first = True continue if not inside: continue if "| Module List |" in line: break if ']' not in line: continue # Skip missing DLLs, apparently not needed anyway. if '?' in line[:line.find(']')]: continue # Skip DLLs that failed to load, apparently not needed anyway. if 'E' in line[:line.find(']')]: continue dll_filename = line[line.find(']')+2:-1] # The executable itself is of course exempted. We cannot check its path # because depends.exe mistreats unicode paths. if first: first = False continue assert os.path.isfile(dll_filename), dll_filename dll_name = os.path.basename(dll_filename).upper() # Win API can be assumed. if dll_name.startswith("API-MS-WIN-") or \ dll_name.startswith("EXT-MS-WIN-"): continue if dll_name in ("SHELL32.DLL", "USER32.DLL", "KERNEL32.DLL", "NTDLL.DLL", "NETUTILS.DLL", "LOGONCLI.DLL", "GDI32.DLL", "RPCRT4.DLL", "ADVAPI32.DLL", "SSPICLI.DLL", "SECUR32.DLL", "KERNELBASE.DLL", "WINBRAND.DLL", "DSROLE.DLL", "DNSAPI.DLL", "SAMCLI.DLL", "WKSCLI.DLL", "SAMLIB.DLL", "WLDAP32.DLL", "NTDSAPI.DLL", "CRYPTBASE.DLL", "W32TOPL", "WS2_32.DLL", "SPPC.DLL", "MSSIGN32.DLL", "CERTCLI.DLL", "WEBSERVICES.DLL", "AUTHZ.DLL", "CERTENROLL.DLL", "VAULTCLI.DLL", "REGAPI.DLL", "BROWCLI.DLL", "WINNSI.DLL", "DHCPCSVC6.DLL", "PCWUM.DLL", "CLBCATQ.DLL", "IMAGEHLP.DLL", "MSASN1.DLL", "DBGHELP.DLL", "DEVOBJ.DLL", "DRVSTORE.DLL", "CABINET.DLL", "SCECLI.DLL", "SPINF.DLL", "SPFILEQ.DLL", "GPAPI.DLL", "NETJOIN.DLL", "W32TOPL.DLL", "NETBIOS.DLL", "DXGI.DLL", "DWRITE.DLL", "D3D11.DLL", "WLANAPI.DLL", "WLANUTIL.DLL", "ONEX.DLL", "EAPPPRXY.DLL", "MFPLAT.DLL", "AVRT.DLL", "ELSCORE.DLL", "INETCOMM.DLL", "MSOERT2.DLL", "IEUI.DLL", "MSCTF.DLL", "MSFEEDS.DLL", "UIAUTOMATIONCORE.DLL", "PSAPI.DLL", "EFSADU.DLL", "MFC42U.DLL", "ODBC32.DLL", "OLEDLG.DLL", "NETAPI32.DLL", "LINKINFO.DLL", "DUI70.DLL", "ADVPACK.DLL", "NTSHRUI.DLL", "WINSPOOL.DRV", "EFSUTIL.DLL", "WINSCARD.DLL", "SHDOCVW.DLL", "IEFRAME.DLL", "D2D1.DLL", "GDIPLUS.DLL", "OCCACHE.DLL", "IEADVPACK.DLL", "MLANG.DLL", "MSI.DLL", "MSHTML.DLL", "COMDLG32.DLL", "PRINTUI.DLL", "PUIAPI.DLL", "ACLUI.DLL", "WTSAPI32.DLL", "FMS.DLL", "DFSCLI.DLL", "HLINK.DLL", "MSRATING.DLL", "PRNTVPT.DLL", "IMGUTIL.DLL", "MSLS31.DLL", "VERSION.DLL", "NORMALIZ.DLL", "IERTUTIL.DLL", "WININET.DLL", "WINTRUST.DLL", "XMLLITE.DLL", "APPHELP.DLL", "PROPSYS.DLL", "RSTRTMGR.DLL", "NCRYPT.DLL", "BCRYPT.DLL", "MMDEVAPI.DLL", "MSILTCFG.DLL", "DEVMGR.DLL", "DEVRTL.DLL", "NEWDEV.DLL", "VPNIKEAPI.DLL", "WINHTTP.DLL", "WEBIO.DLL", "NSI.DLL", "DHCPCSVC.DLL", "CRYPTUI.DLL", "ESENT.DLL", "DAVHLPR.DLL", "CSCAPI.DLL", "ATL.DLL", "OLEAUT32.DLL", "SRVCLI.DLL", "RASDLG.DLL", "MPRAPI.DLL", "RTUTILS.DLL", "RASMAN.DLL", "MPRMSG.DLL", "SLC.DLL", "CRYPTSP.DLL", "RASAPI32.DLL", "TAPI32.DLL", "EAPPCFG.DLL", "NDFAPI.DLL", "WDI.DLL", "COMCTL32.DLL", "UXTHEME.DLL", "IMM32.DLL", "OLEACC.DLL", "WINMM.DLL", "WINDOWSCODECS.DLL", "DWMAPI.DLL", "DUSER.DLL", "PROFAPI.DLL", "URLMON.DLL", "SHLWAPI.DLL", "LPK.DLL", "USP10.DLL", "CFGMGR32.DLL", "MSIMG32.DLL", "POWRPROF.DLL", "SETUPAPI.DLL", "WINSTA.DLL", "CRYPT32.DLL", "IPHLPAPI.DLL", "MPR.DLL", "CREDUI.DLL", "NETPLWIZ.DLL", "OLE32.DLL", "ACTIVEDS.DLL", "ADSLDPC.DLL", "USERENV.DLL", "APPREPAPI.DLL", "BCP47LANGS.DLL", "BCRYPTPRIMITIVES.DLL", "CERTCA.DLL", "CHARTV.DLL", "COMBASE.DLL", "COML2.DLL", "DCOMP.DLL", "DPAPI.DLL", "DSPARSE.DLL", "FECLIENT.DLL", "FIREWALLAPI.DLL", "FLTLIB.DLL", "MRMCORER.DLL", "NTASN1.DLL", "SECHOST.DLL", "SETTINGSYNCPOLICY.DLL", "SHCORE.DLL", "TBS.DLL", "TWINAPI.APPCORE.DLL", "TWINAPI.DLL", "VIRTDISK.DLL", "WEBSOCKET.DLL", "WEVTAPI.DLL", "WINMMBASE.DLL", "WMICLNT.DLL"): continue result.add( os.path.normcase(os.path.abspath(dll_filename)) ) deleteFile(binary_filename + ".depends", must_exist = True) deleteFile(binary_filename + ".dwp", must_exist = True) return result
def considerExtraDlls(self, dist_dir, module): # pylint: disable=too-many-branches,too-many-locals full_name = module.getFullName() if full_name in ("PyQt4", "PyQt5"): qt_version = int(full_name[-1]) plugin_dirs = self.getPyQtPluginDirs(qt_version) if not plugin_dirs: sys.exit("Error, failed to detect %s plugin directories." % full_name) target_plugin_dir = os.path.join(dist_dir, full_name, "qt-plugins") plugin_options = self.getPluginOptions() plugin_options = set(plugin_options) # Default to using sensible plugins. if not plugin_options: plugin_options.add("sensible") if "sensible" in plugin_options: # Most used ones with low dependencies. plugin_options.update( tuple( family for family in ( "imageformats", "iconengines", "mediaservice", "printsupport", "platforms", ) if self.hasPluginFamily(plugin_dirs, family) ) ) plugin_options.remove("sensible") # Make sure the above didn't detect nothing, which would be # indicating the check to be bad. assert plugin_options info( "Copying Qt plug-ins '%s' to '%s'." % ( ",".join(sorted(x for x in plugin_options if x != "xml")), target_plugin_dir, ) ) for plugin_dir in plugin_dirs: copyTree(plugin_dir, target_plugin_dir) if "all" not in plugin_options: for plugin_candidate in getSubDirectories(target_plugin_dir): if os.path.basename(plugin_candidate) not in plugin_options: removeDirectory(plugin_candidate, ignore_errors=False) for plugin_candidate in plugin_options: if plugin_candidate == "qml": continue if not os.path.isdir( os.path.join(target_plugin_dir, plugin_candidate) ): sys.exit( "Error, no such Qt plugin family: %s" % plugin_candidate ) result = [ ( filename, os.path.join( target_plugin_dir, os.path.relpath(filename, plugin_dir) ), full_name, ) for plugin_dir in plugin_dirs for filename in getFileList(plugin_dir) if not filename.endswith(".qml") if os.path.exists( os.path.join( target_plugin_dir, os.path.relpath(filename, plugin_dir) ) ) ] if isWin32Windows(): # Those 2 vars will be used later, just saving some resources # by caching the files list qt_bin_files = sum( ( getFileList(qt_bin_dir) for qt_bin_dir in self._getQtBinDirs(plugin_dirs) ), [], ) info("Copying OpenSSL DLLs to %r" % (dist_dir,)) for filename in qt_bin_files: basename = os.path.basename(filename).lower() if basename in ("libeay32.dll", "ssleay32.dll"): shutil.copy(filename, os.path.join(dist_dir, basename)) if "qml" in plugin_options or "all" in plugin_options: for plugin_dir in plugin_dirs: qml_plugin_dir = os.path.normpath( os.path.join(plugin_dir, "..", "qml") ) if os.path.exists(qml_plugin_dir): break else: sys.exit("Error, no such Qt plugin family: qml") qml_target_dir = os.path.normpath( os.path.join(target_plugin_dir, "..", "Qt", "qml") ) info("Copying Qt plug-ins 'xml' to '%s'." % (qml_target_dir)) copyTree(qml_plugin_dir, qml_target_dir) # We try to filter here, not for DLLs. result += [ ( filename, os.path.join( qml_target_dir, os.path.relpath(filename, qml_plugin_dir) ), full_name, ) for filename in getFileList(qml_plugin_dir) if not filename.endswith( ( ".qml", ".qmlc", ".qmltypes", ".js", ".jsc", ".png", ".ttf", ".metainfo", ) ) if not os.path.isdir(filename) if not os.path.basename(filename) == "qmldir" ] # Also copy required OpenGL DLLs on Windows if isWin32Windows(): opengl_dlls = ("libegl.dll", "libglesv2.dll", "opengl32sw.dll") info("Copying OpenGL DLLs to %r" % (dist_dir,)) for filename in qt_bin_files: basename = os.path.basename(filename).lower() if basename in opengl_dlls or basename.startswith( "d3dcompiler_" ): shutil.copy(filename, os.path.join(dist_dir, basename)) return result return ()
def considerExtraDlls(self, dist_dir, module): # pylint: disable=too-many-branches,too-many-locals full_name = module.getFullName() if full_name in ("PyQt4", "PyQt5"): qt_version = int(full_name[-1]) plugin_dir, = self.getPyQtPluginDirs(qt_version) target_plugin_dir = os.path.join(dist_dir, full_name, "qt-plugins") plugin_options = self.getPluginOptions() plugin_options = set(plugin_options) if not plugin_options: plugin_options.add("sensible") if "sensible" in plugin_options: # Most used ones with low dependencies. plugin_options.update( tuple( family for family in ( "imageformats", "iconengines", "mediaservice", "printsupport", "platforms", ) if self.hasPluginFamily(plugin_dir, family) ) ) plugin_options.remove("sensible") # Make sure the above didn't detect nothing, which would be # indicating the check to be bad. assert plugin_options info( "Copying Qt plug-ins '%s' to '%s'." % ( ",".join(sorted(x for x in plugin_options if x != "xml")), target_plugin_dir, ) ) shutil.copytree(plugin_dir, target_plugin_dir) if "all" not in plugin_options: for plugin_candidate in getSubDirectories(target_plugin_dir): if os.path.basename(plugin_candidate) not in plugin_options: removeDirectory(plugin_candidate, ignore_errors=False) for plugin_candidate in plugin_options: if plugin_candidate == "qml": continue if not os.path.isdir( os.path.join(target_plugin_dir, plugin_candidate) ): sys.exit( "Error, no such Qt plugin family: %s" % plugin_candidate ) result = [ ( filename, os.path.join( target_plugin_dir, os.path.relpath(filename, plugin_dir) ), full_name, ) for filename in getFileList(plugin_dir) if not filename.endswith(".qml") if os.path.exists( os.path.join( target_plugin_dir, os.path.relpath(filename, plugin_dir) ) ) ] if os.name == "nt": # Those 2 vars will be used later, just saving some resources # by caching the files list qt_bin_dir = os.path.normpath(os.path.join(plugin_dir, "..", "bin")) qt_bin_files = getFileList(qt_bin_dir) info("Copying OpenSSL DLLs to %r" % (dist_dir,)) for filename in qt_bin_files: basename = os.path.basename(filename).lower() if basename in ("libeay32.dll", "ssleay32.dll"): shutil.copy(filename, os.path.join(dist_dir, basename)) if "qml" in plugin_options or "all" in plugin_options: qml_plugin_dir = os.path.normpath(os.path.join(plugin_dir, "..", "qml")) qml_target_dir = os.path.normpath( os.path.join(target_plugin_dir, "..", "Qt", "qml") ) info("Copying Qt plug-ins 'xml' to '%s'." % (qml_target_dir)) shutil.copytree(qml_plugin_dir, qml_target_dir) # We try to filter here, not for DLLs. result += [ ( filename, os.path.join( qml_target_dir, os.path.relpath(filename, qml_plugin_dir) ), full_name, ) for filename in getFileList(qml_plugin_dir) if not filename.endswith( ( ".qml", ".qmlc", ".qmltypes", ".js", ".jsc", ".png", ".ttf", ".metainfo", ) ) if not os.path.isdir(filename) if not os.path.basename(filename) == "qmldir" ] # Also copy required OpenGL DLLs on Windows if os.name == "nt": opengl_dlls = ("libegl.dll", "libglesv2.dll", "opengl32sw.dll") info("Copying OpenGL DLLs to %r" % (dist_dir,)) for filename in qt_bin_files: basename = os.path.basename(filename).lower() if basename in opengl_dlls or basename.startswith( "d3dcompiler_" ): shutil.copy(filename, os.path.join(dist_dir, basename)) return result return ()