def isSameModulePath(path1, path2): if Utils.basename(path1) == "__init__.py": path1 = Utils.dirname(path1) if Utils.basename(path2) == "__init__.py": path2 = Utils.dirname(path2) return Utils.abspath(path1) == Utils.abspath(path2)
def _detectedSourceFile(filename, module_name, result, is_late): if module_name in module_names: return if module_name == "collections.abc": _detectedSourceFile(filename=filename, module_name="_collections_abc", result=result, is_late=is_late) source_code = readSourceCodeFromFilename(filename) if Utils.python_version >= 300: filename = filename.decode("utf-8") if module_name == "site": source_code = """\ __file__ = (__nuitka_binary_dir + '%s%s') if '__nuitka_binary_dir' in dict(__builtins__ ) else '<frozen>';%s""" % ( os.path.sep, Utils.basename(filename), source_code) debug("Freezing module '%s' (from '%s').", module_name, filename) result.append( (module_name, marshal.dumps(compile(source_code, filename, "exec")), Utils.basename(filename) == "__init__.py", filename, is_late)) module_names.add(module_name)
def _detectedSourceFile(filename, module_name, result, user_provided): if module_name in module_names: return if module_name == "collections.abc": _detectedSourceFile(filename=filename, module_name="_collections_abc", result=result, user_provided=user_provided) source_code = readSourceCodeFromFilename(module_name, filename) if module_name == "site": if source_code.startswith("def ") or source_code.startswith("class "): source_code = '\n' + source_code source_code = """\ __file__ = (__nuitka_binary_dir + '%s%s') if '__nuitka_binary_dir' in dict(__builtins__ ) else '<frozen>';%s""" % ( os.path.sep, Utils.basename(filename), source_code) debug("Freezing module '%s' (from '%s').", module_name, filename) result.append( makeUncompiledPythonModule( module_name=module_name, bytecode=marshal.dumps(compile(source_code, filename, "exec")), is_package=Utils.basename(filename) == "__init__.py", filename=filename, user_provided=user_provided)) module_names.add(module_name)
def getResultBasepath(main_module): assert main_module.isCompiledPythonModule() if Options.isStandaloneMode(): return Utils.joinpath( getStandaloneDirectoryPath(main_module), Utils.basename(getTreeFilenameWithSuffix(main_module, "")) ) else: return Options.getOutputPath(path=Utils.basename(getTreeFilenameWithSuffix(main_module, "")))
def getResultBasepath(main_module): assert main_module.isCompiledPythonModule() if Options.isStandaloneMode(): return Utils.joinpath( getStandaloneDirectoryPath(main_module), Utils.basename(getTreeFilenameWithSuffix(main_module, ""))) else: return Options.getOutputPath( path=Utils.basename(getTreeFilenameWithSuffix(main_module, "")))
def _detectedSourceFile(filename, module_name, result, is_late): if module_name in module_names: return if module_name == "collections.abc": _detectedSourceFile( filename = filename, module_name = "_collections_abc", result = result, is_late = is_late ) source_code = readSourceCodeFromFilename(module_name, filename) if Utils.python_version >= 300: filename = filename.decode("utf-8") if module_name == "site": if source_code.startswith("def ") or source_code.startswith("class "): source_code = '\n' + source_code source_code = """\ __file__ = (__nuitka_binary_dir + '%s%s') if '__nuitka_binary_dir' in dict(__builtins__ ) else '<frozen>';%s""" % ( os.path.sep, Utils.basename(filename), source_code ) debug( "Freezing module '%s' (from '%s').", module_name, filename ) result.append( ( module_name, marshal.dumps( compile(source_code, filename, "exec") ), Utils.basename(filename) == "__init__.py", filename, is_late ) ) module_names.add(module_name)
def getSourceDirectoryPath(main_module): assert main_module.isCompiledPythonModule() return Options.getOutputPath( path = Utils.basename( getTreeFilenameWithSuffix(main_module, ".build") ) )
def normalizePackageName(module_name): # The "os.path" is strangely hacked into the "os" module, dispatching per # platform, we either cannot look into it, or we require that we resolve it # here correctly. if module_name == "os.path": module_name = Utils.basename(os.path.__name__) return module_name
def considerFilename(module_filename): module_filename = Utils.normpath(module_filename) if Utils.isDir(module_filename): module_filename = Utils.abspath(module_filename) module_name = Utils.basename(module_filename) module_relpath = Utils.relpath(module_filename) return module_filename, module_relpath, module_name elif module_filename.endswith(".py"): module_name = Utils.basename(module_filename)[:-3] module_relpath = Utils.relpath(module_filename) return module_filename, module_relpath, module_name else: return None
def getImportedModuleByPath(module_relpath): module_name = Utils.basename(module_relpath) if module_name.endswith(".py"): module_name = module_name[:-3] key = module_relpath, module_name return imported_modules[key]
def getImportedModuleByPath(module_relpath): module_name = Utils.basename(module_relpath) if module_name.endswith(".py"): module_name = module_name[:-3] key = module_relpath, module_name return imported_modules[ key ]
def __init__(self, name, package_name, source_ref): NodeBase.__init__(self, source_ref=source_ref) PythonModuleMixin.__init__(self, name=name, package_name=package_name) assert Utils.basename(source_ref.getFilename()) != "<frozen>" # That is too likely a bug. assert name != "__main__"
def _detectedSourceFile(filename, module_name, result, user_provided): if module_name in module_names: return if module_name == "collections.abc": _detectedSourceFile( filename = filename, module_name = "_collections_abc", result = result, user_provided = user_provided ) source_code = readSourceCodeFromFilename(module_name, filename) if module_name == "site": if source_code.startswith("def ") or source_code.startswith("class "): source_code = '\n' + source_code source_code = """\ __file__ = (__nuitka_binary_dir + '%s%s') if '__nuitka_binary_dir' in dict(__builtins__ ) else '<frozen>';%s""" % ( os.path.sep, Utils.basename(filename), source_code ) debug( "Freezing module '%s' (from '%s').", module_name, filename ) result.append( makeUncompiledPythonModule( module_name = module_name, bytecode = marshal.dumps( compile(source_code, filename, "exec") ), is_package = Utils.basename(filename) == "__init__.py", filename = filename, user_provided = user_provided ) ) module_names.add(module_name)
def _detectBinaryPathDLLsLinuxBSD(binary_filename): # Ask "ldd" about the libraries being used by the created binary, these # are the ones that interest us. result = set() process = subprocess.Popen( args = [ "ldd", binary_filename ], stdout = subprocess.PIPE, stderr = subprocess.PIPE ) stdout, _stderr = process.communicate() for line in stdout.split(b"\n"): if not line: continue if b"=>" not in line: continue part = line.split(b" => ", 2)[1] if b"(" in part: filename = part[:part.rfind(b"(")-1] else: filename = part if not filename: continue if python_version >= 300: filename = filename.decode("utf-8") # Sometimes might use stuff not found. if filename == "not found": continue # Do not include kernel specific libraries. if Utils.basename(filename).startswith( ( "libc.so.", "libpthread.so.", "libm.so.", "libdl.so." ) ): continue result.add(filename) return result
def considerFilename(module_filename, module_package): assert module_package is None or \ ( type(module_package) is str and module_package != "" ) module_filename = Utils.normpath(module_filename) if Utils.isDir(module_filename): module_filename = Utils.abspath(module_filename) module_name = Utils.basename(module_filename) module_relpath = Utils.relpath(module_filename) return module_filename, module_relpath, module_name elif module_filename.endswith(".py"): module_name = Utils.basename(module_filename)[:-3] module_relpath = Utils.relpath(module_filename) return module_filename, module_relpath, module_name else: return None
def getModuleNameAndKindFromFilename(module_filename): if Utils.isDir(module_filename): module_name = Utils.basename(module_filename) module_kind = "py" elif module_filename.endswith(".py"): module_name = Utils.basename(module_filename)[:-3] module_kind = "py" else: for suffix, _mode, kind in imp.get_suffixes(): if kind != imp.C_EXTENSION: continue if module_filename.endswith(suffix): module_name = Utils.basename(module_filename)[:-len(suffix)] module_kind = "shlib" break else: module_kind = None module_name = None return module_name, module_kind
def getRunTimeFilename(self): reference_mode = Options.getFileReferenceMode() if reference_mode == "original": return self.getCompileTimeFilename() elif reference_mode == "frozen": return "<frozen %s>" % self.getFullName() else: filename = self.getCompileTimeFilename() full_name = self.getFullName() result = Utils.basename(filename) current = filename levels = full_name.count('.') if self.isCompiledPythonPackage(): levels += 1 for _i in range(levels): current = Utils.dirname(current) result = Utils.joinpath(Utils.basename(current), result) return result
def _normalizeModuleFilename(filename): if python_version >= 300: filename = filename.replace("__pycache__", "") suffix = ".cpython-%d.pyc" % (python_version // 10) if filename.endswith(suffix): filename = filename[:-len(suffix)] + ".py" else: if filename.endswith(".pyc"): filename = filename[:-3] + ".py" if Utils.basename(filename) == "__init__.py": filename = Utils.dirname(filename) return filename
def __init__(self, name, package_name, source_ref): NodeBase.__init__(self, source_ref=source_ref) PythonModuleMixin.__init__(self, name=name, package_name=package_name) # That would be a mistake we just made. assert Utils.basename(source_ref.getFilename()) != "<frozen>" # That is too likely a bug. assert name != "__main__" # Duplicates should be avoided by us caching elsewhere before creating # the object. assert self.getFullName( ) not in self.avoid_duplicates, self.getFullName() self.avoid_duplicates.add(self.getFullName())
def __init__(self, name, package_name, source_ref): NodeBase.__init__( self, source_ref = source_ref ) PythonModuleMixin.__init__( self, name = name, package_name = package_name ) assert Utils.basename(source_ref.getFilename()) != "<frozen>" # That is too likely a bug. assert name != "__main__"
def addImportedModule(imported_module): module_filename = Utils.relpath(imported_module.getFilename()) if Utils.basename(module_filename) == "__init__.py": module_filename = Utils.dirname(module_filename) key = (module_filename, imported_module.getFullName()) if key in imported_modules: assert imported_module is imported_modules[key], key else: Plugins.onModuleDiscovered(imported_module) imported_modules[key] = imported_module imported_by_name[imported_module.getFullName()] = imported_module # We don't expect that to happen. assert not imported_module.isMainModule()
def addImportedModule(imported_module): module_filename = Utils.relpath(imported_module.getFilename()) if Utils.basename(module_filename) == "__init__.py": module_filename = Utils.dirname(module_filename) key = ( module_filename, imported_module.getFullName() ) if key in imported_modules: assert imported_module is imported_modules[key], key else: Plugins.onModuleDiscovered(imported_module) imported_modules[key] = imported_module imported_by_name[imported_module.getFullName()] = imported_module # We don't expect that to happen. assert not imported_module.isMainModule()
def __init__(self, name, package_name, source_ref): NodeBase.__init__( self, source_ref = source_ref ) PythonModuleMixin.__init__( self, name = name, package_name = package_name ) # That would be a mistake we just made. assert Utils.basename(source_ref.getFilename()) != "<frozen>" # That is too likely a bug. assert name != "__main__" # Duplicates should be avoided by us caching elsewhere before creating # the object. assert self.getFullName() not in self.avoid_duplicates, self.getFullName() self.avoid_duplicates.add(self.getFullName())
""" Options module """ version_string = """\ Nuitka V0.5.12 Copyright (C) 2015 Kay Hayen.""" import logging import re import sys from optparse import SUPPRESS_HELP, OptionGroup, OptionParser from nuitka.utils import Utils # Indicator if we were called as "nuitka-run" in which case we assume some # other defaults and work a bit different with parameters. is_nuitka_run = Utils.basename(sys.argv[0]).lower().startswith("nuitka-run") def getVersion(): return version_string.split()[1][1:] def getYear(): return int(version_string.split()[4]) if not is_nuitka_run: usage = "usage: %prog [--module] [--execute] [options] main_module.py" else: usage = "usage: %prog [options] main_module.py" parser = OptionParser( usage = usage, version = getVersion()
def getDependsExePath(): """ Return the path of depends.exe (for Windows). Will prompt the user to download if not already cached in AppData directory for Nuitka. """ if Utils.getArchitecture() == "x86": depends_url = "http://dependencywalker.com/depends22_x86.zip" else: depends_url = "http://dependencywalker.com/depends22_x64.zip" if "APPDATA" not in os.environ: sys.exit("Error, standalone mode cannot find 'APPDATA' environment.") nuitka_app_dir = Utils.joinpath(os.environ["APPDATA"], "nuitka") if not Utils.isDir(nuitka_app_dir): Utils.makePath(nuitka_app_dir) nuitka_depends_zip = Utils.joinpath( nuitka_app_dir, Utils.basename(depends_url) ) if not Utils.isFile(nuitka_depends_zip): Tracing.printLine("""\ Nuitka will make use of Dependency Walker (http://dependencywalker.com) tool to analyze the dependencies of Python extension modules. Is it OK to download and put it in APPDATA (no installer needed, cached, one time question).""") reply = raw_input("Proceed and download? [Yes]/No ") if reply.lower() in ("no", 'n'): sys.exit("Nuitka does not work in --standalone on Windows without.") info("Downloading '%s'" % depends_url) urlretrieve( depends_url, nuitka_depends_zip ) nuitka_depends_dir = Utils.joinpath( nuitka_app_dir, Utils.getArchitecture() ) if not Utils.isDir(nuitka_depends_dir): os.makedirs(nuitka_depends_dir) depends_exe = os.path.join( nuitka_depends_dir, "depends.exe" ) if not Utils.isFile(depends_exe): info("Extracting to '%s'" % depends_exe) import zipfile try: depends_zip = zipfile.ZipFile(nuitka_depends_zip) depends_zip.extractall(nuitka_depends_dir) except Exception: # Catching anything zip throws, pylint:disable=W0703 info("Problem with the downloaded zip file, deleting it.") Utils.deleteFile(depends_exe, must_exist = False) Utils.deleteFile(nuitka_depends_zip, must_exist = True) sys.exit( "Error, need '%s' as extracted from '%s'." % ( depends_exe, depends_url ) ) assert Utils.isFile(depends_exe) return depends_exe
def getStandardLibraryPaths(): """ Get the standard library paths. """ # Using the function object to cache its result, avoiding global variable # usage. if not hasattr(getStandardLibraryPaths, "result"): os_filename = os.__file__ if os_filename.endswith(".pyc"): os_filename = os_filename[:-1] os_path = Utils.normcase(Utils.dirname(os_filename)) stdlib_paths = set([os_path]) # Happens for virtualenv situation, some modules will come from the link # this points to. if Utils.isLink(os_filename): os_filename = Utils.readLink(os_filename) stdlib_paths.add(Utils.normcase(Utils.dirname(os_filename))) # Another possibility is "orig-prefix.txt" file near the os.py, which # points to the original install. orig_prefix_filename = Utils.joinpath(os_path, "orig-prefix.txt") if Utils.isFile(orig_prefix_filename): # Scan upwards, until we find a "bin" folder, with "activate" to # locate the structural path to be added. We do not know for sure # if there is a sub-directory under "lib" to use or not. So we try # to detect it. search = os_path lib_part = "" while os.path.splitdrive(search)[1] not in (os.path.sep, ""): if Utils.isFile(Utils.joinpath(search,"bin/activate")) or \ Utils.isFile(Utils.joinpath(search,"scripts/activate")): break lib_part = Utils.joinpath(Utils.basename(search), lib_part) search = Utils.dirname(search) assert search and lib_part stdlib_paths.add( Utils.normcase( Utils.joinpath( open(orig_prefix_filename).read(), lib_part, ) ) ) # And yet another possibility, for MacOS Homebrew created virtualenv # at least is a link ".Python", which points to the original install. python_link_filename = Utils.joinpath(os_path, "..", ".Python") if Utils.isLink(python_link_filename): stdlib_paths.add( Utils.normcase( Utils.joinpath( Utils.readLink(python_link_filename), "lib" ) ) ) getStandardLibraryPaths.result = [ Utils.normcase(stdlib_path) for stdlib_path in stdlib_paths ] return getStandardLibraryPaths.result
def decideModuleTree(filename, package, is_shlib, is_top, is_main): # Many variables, branches, due to the many cases, pylint: disable=R0912,R0915 assert package is None or type(package) is str assert filename is not None if is_main and Utils.isDir(filename): source_filename = Utils.joinpath(filename, "__main__.py") if not Utils.isFile(source_filename): sys.stderr.write("%s: can't find '__main__' module in '%s'\n" % (Utils.basename(sys.argv[0]), filename)) sys.exit(2) filename = source_filename main_added = True else: main_added = False if Utils.isFile(filename): source_filename = filename source_ref = SourceCodeReferences.fromFilename(filename=filename, ) if is_main: module_name = "__main__" else: module_name = Utils.basename(filename) if module_name.endswith(".py"): module_name = module_name[:-3] if is_shlib: module_name = module_name.split('.')[0] if '.' in module_name: sys.stderr.write( "Error, '%s' is not a proper python module name.\n" % (module_name)) sys.exit(2) if is_shlib: result = PythonShlibModule(name=module_name, package_name=package, source_ref=source_ref) elif is_main: result = PythonMainModule(main_added=main_added, source_ref=source_ref) else: if package is not None: full_name = package + "." + module_name else: full_name = module_name decision = Plugins.decideCompilation(full_name, source_ref) if decision == "compiled": result = CompiledPythonModule(name=module_name, package_name=package, source_ref=source_ref) else: source_code = readSourceCodeFromFilename(module_name, filename) source_code = Plugins.onFrozenModuleSourceCode( module_name=full_name, is_package=False, source_code=source_code) bytecode = compile(source_code, filename, "exec") bytecode = Plugins.onFrozenModuleBytecode( module_name=module_name, is_package=False, bytecode=bytecode) result = UncompiledPythonModule(name=module_name, package_name=package, bytecode=bytecode, filename=filename, user_provided=True, technical=False, source_ref=source_ref) # Don't read it anymore. source_filename = None elif Importing.isPackageDir(filename): if is_top: package_name = Utils.splitpath(filename)[-1] else: package_name = Utils.basename(filename) source_filename = Utils.joinpath(filename, "__init__.py") if not Utils.isFile(source_filename): source_ref, result = createNamespacePackage( package_name=package_name, module_relpath=filename) source_filename = None else: source_ref = SourceCodeReferences.fromFilename( filename=Utils.abspath(source_filename), ) if package is not None: full_name = package + "." + package_name else: full_name = package_name decision = Plugins.decideCompilation(full_name, source_ref) if decision == "compiled": result = CompiledPythonPackage(name=package_name, package_name=package, source_ref=source_ref) else: bytecode = compile(source_code, filename, "exec") bytecode = Plugins.onFrozenModuleBytecode( module_name=module_name, is_package=False, bytecode=bytecode) result = UncompiledPythonPackage(name=module_name, package_name=package, bytecode=bytecode, filename=filename, user_provided=True, technical=False, source_ref=source_ref) # Don't read it anymore. source_filename = None else: sys.stderr.write("%s: can't open file '%s'.\n" % (Utils.basename(sys.argv[0]), filename)) sys.exit(2) if not Options.shallHaveStatementLines(): source_ref = source_ref.atInternal() return result, source_ref, source_filename
def runScons(main_module, quiet): # Scons gets transported many details, that we express as variables, and # have checks for them, leading to many branches, pylint: disable=R0912 python_version_str = "%d.%d" % (sys.version_info[0], sys.version_info[1]) if hasattr(sys, "abiflags"): if Options.isPythonDebug() or \ hasattr(sys, "getobjects"): if sys.abiflags.startswith('d'): python_version_str += sys.abiflags else: python_version_str += 'd' + sys.abiflags else: python_version_str += sys.abiflags def asBoolStr(value): return "true" if value else "false" options = { "name" : Utils.basename( getTreeFilenameWithSuffix(main_module, "") ), "result_name" : getResultBasepath(main_module), "source_dir" : getSourceDirectoryPath(main_module), "debug_mode" : asBoolStr(Options.isDebug()), "python_debug" : asBoolStr(Options.isPythonDebug()), "unstripped_mode" : asBoolStr(Options.isUnstripped()), "module_mode" : asBoolStr(Options.shallMakeModule()), "optimize_mode" : asBoolStr(Options.isOptimize()), "full_compat" : asBoolStr(Options.isFullCompat()), "experimental" : asBoolStr(Options.isExperimental()), "trace_mode" : asBoolStr(Options.shallTraceExecution()), "python_version" : python_version_str, "target_arch" : Utils.getArchitecture(), "python_prefix" : sys.prefix, "nuitka_src" : SconsInterface.getSconsDataPath(), "module_count" : "%d" % ( len(ModuleRegistry.getDoneUserModules()) + 1 ) } # Ask Scons to cache on Windows, except where the directory is thrown # away. On non-Windows you can should use ccache instead. if not Options.isRemoveBuildDir() and Utils.getOS() == "Windows": options["cache_mode"] = "true" if Options.isLto(): options["lto_mode"] = "true" if Options.shallDisableConsoleWindow(): options["win_disable_console"] = "true" if Options.isStandaloneMode(): options["standalone_mode"] = "true" if not Options.isStandaloneMode() and \ not Options.shallMakeModule() and \ isUninstalledPython(): options["uninstalled_python"] = "true" if ModuleRegistry.getUncompiledModules(): options["frozen_modules"] = str( len(ModuleRegistry.getUncompiledModules()) ) if Options.isShowScons(): options["show_scons"] = "true" if Options.isMingw(): options["mingw_mode"] = "true" if Options.getMsvcVersion(): msvc_version = Options.getMsvcVersion() msvc_version = msvc_version.replace("exp", "Exp") if '.' not in msvc_version: msvc_version += ".0" options["msvc_version"] = msvc_version if Options.isClang(): options["clang_mode"] = "true" if Options.getIconPath(): options["icon_path"] = Options.getIconPath() if Options.isProfile(): options["profile_mode"] = "true" return SconsInterface.runScons(options, quiet), options
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_dir} 32BitSysDir 16BitSysDir OSDir AppPath SxS """.format(original_dir = "UserDir %s" % original_dir 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 Utils.isFile(dll_filename), dll_filename dll_name = Utils.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( Utils.normcase(Utils.abspath(dll_filename)) ) Utils.deleteFile(binary_filename + ".depends", must_exist = True) Utils.deleteFile(binary_filename + ".dwp", must_exist = True) return result
def getStandardLibraryPaths(): """ Get the standard library paths. """ # Using the function object to cache its result, avoiding global variable # usage. if not hasattr(getStandardLibraryPaths, "result"): os_filename = os.__file__ if os_filename.endswith(".pyc"): os_filename = os_filename[:-1] os_path = Utils.normcase(Utils.dirname(os_filename)) stdlib_paths = set([os_path]) # Happens for virtualenv situation, some modules will come from the link # this points to. if Utils.isLink(os_filename): os_filename = Utils.readLink(os_filename) stdlib_paths.add(Utils.normcase(Utils.dirname(os_filename))) # Another possibility is "orig-prefix.txt" file near the os.py, which # points to the original install. orig_prefix_filename = Utils.joinpath(os_path, "orig-prefix.txt") if Utils.isFile(orig_prefix_filename): # Scan upwards, until we find a "bin" folder, with "activate" to # locate the structural path to be added. We do not know for sure # if there is a sub-directory under "lib" to use or not. So we try # to detect it. search = os_path lib_part = "" while os.path.splitdrive(search)[1] not in (os.path.sep, ""): if Utils.isFile(Utils.joinpath(search,"bin/activate")) or \ Utils.isFile(Utils.joinpath(search,"scripts/activate")): break lib_part = Utils.joinpath(Utils.basename(search), lib_part) search = Utils.dirname(search) assert search and lib_part stdlib_paths.add( Utils.normcase( Utils.joinpath( open(orig_prefix_filename).read(), lib_part, ))) # And yet another possibility, for MacOS Homebrew created virtualenv # at least is a link ".Python", which points to the original install. python_link_filename = Utils.joinpath(os_path, "..", ".Python") if Utils.isLink(python_link_filename): stdlib_paths.add( Utils.normcase( Utils.joinpath(Utils.readLink(python_link_filename), "lib"))) getStandardLibraryPaths.result = [ Utils.normcase(stdlib_path) for stdlib_path in stdlib_paths ] return getStandardLibraryPaths.result
def _detectBinaryPathDLLsWindows(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 32BitSysDir 16BitSysDir OSDir AppPath SxS """) 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 for line in open(binary_filename + ".depends"): if "| Module Dependency Tree |" in line: inside = 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] assert Utils.isFile(dll_filename), dll_filename # The executable itself is of course exempted. if Utils.normcase(dll_filename) == \ Utils.normcase(Utils.abspath(binary_filename)): continue dll_name = Utils.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", "DCOMP.DLL", "DPAPI.DLL", "DSPARSE.DLL", "FECLIENT.DLL", "FIREWALLAPI.DLL", "FLTLIB.DLL", "MRMCORER.DLL", "MSVCRT.DLL", "NINPUT.DLL", "NTASN1.DLL", "PCACLI.DLL", "RTWORKQ.DLL", "SECHOST.DLL", "SETTINGSYNCPOLICY.DLL", "SHCORE.DLL", "TBS.DLL", "TWINAPI.DLL", "TWINAPI.APPCORE.DLL", "VIRTDISK.DLL", "WEBSOCKET.DLL", "WEVTAPI.DLL", "WINMMBASE.DLL", "WMICLNT.DLL"): continue result.add( Utils.normcase(Utils.abspath(dll_filename)) ) Utils.deleteFile(binary_filename + ".depends", must_exist = True) Utils.deleteFile(binary_filename + ".dwp", must_exist = True) return result
def getDependsExePath(): """ Return the path of depends.exe (for Windows). Will prompt the user to download if not already cached in AppData directory for Nuitka. """ if Utils.getArchitecture() == "x86": depends_url = "http://dependencywalker.com/depends22_x86.zip" else: depends_url = "http://dependencywalker.com/depends22_x64.zip" if "APPDATA" not in os.environ: sys.exit("Error, standalone mode cannot find 'APPDATA' environment.") nuitka_app_dir = Utils.joinpath(os.environ["APPDATA"], "nuitka") if not Utils.isDir(nuitka_app_dir): Utils.makePath(nuitka_app_dir) nuitka_depends_zip = Utils.joinpath(nuitka_app_dir, Utils.basename(depends_url)) if not Utils.isFile(nuitka_depends_zip): Tracing.printLine("""\ Nuitka will make use of Dependency Walker (http://dependencywalker.com) tool to analyze the dependencies of Python extension modules. Is it OK to download and put it in APPDATA (no installer needed, cached, one time question).""") reply = raw_input("Proceed and download? [Yes]/No ") if reply.lower() in ("no", 'n'): sys.exit( "Nuitka does not work in --standalone on Windows without.") info("Downloading '%s'" % depends_url) urlretrieve(depends_url, nuitka_depends_zip) nuitka_depends_dir = Utils.joinpath(nuitka_app_dir, Utils.getArchitecture()) if not Utils.isDir(nuitka_depends_dir): os.makedirs(nuitka_depends_dir) depends_exe = os.path.join(nuitka_depends_dir, "depends.exe") if not Utils.isFile(depends_exe): info("Extracting to '%s'" % depends_exe) import zipfile try: depends_zip = zipfile.ZipFile(nuitka_depends_zip) depends_zip.extractall(nuitka_depends_dir) except Exception: # Catching anything zip throws, pylint:disable=W0703 info("Problem with the downloaded zip file, deleting it.") Utils.deleteFile(depends_exe, must_exist=False) Utils.deleteFile(nuitka_depends_zip, must_exist=True) sys.exit("Error, need '%s' as extracted from '%s'." % (depends_exe, depends_url)) assert Utils.isFile(depends_exe) return depends_exe
def decideModuleTree(filename, package, is_shlib, is_top, is_main): # Many variables, branches, due to the many cases, pylint: disable=R0912 assert package is None or type(package) is str assert filename is not None if is_main and Utils.isDir(filename): source_filename = Utils.joinpath(filename, "__main__.py") if not Utils.isFile(source_filename): sys.stderr.write( "%s: can't find '__main__' module in '%s'\n" % ( Utils.basename(sys.argv[0]), filename ) ) sys.exit(2) filename = source_filename main_added = True else: main_added = False if Utils.isFile(filename): source_filename = filename source_ref = SourceCodeReferences.fromFilename( filename = filename, ) if is_main: module_name = "__main__" else: module_name = Utils.basename(filename) if module_name.endswith(".py"): module_name = module_name[:-3] if is_shlib: module_name = module_name.split('.')[0] if '.' in module_name: sys.stderr.write( "Error, '%s' is not a proper python module name.\n" % ( module_name ) ) sys.exit(2) if is_shlib: result = PythonShlibModule( name = module_name, package_name = package, source_ref = source_ref ) elif is_main: result = PythonMainModule( main_added = main_added, source_ref = source_ref ) else: result = PythonModule( name = module_name, package_name = package, source_ref = source_ref ) elif Importing.isPackageDir(filename): if is_top: package_name = Utils.splitpath(filename)[-1] else: package_name = Utils.basename(filename) source_filename = Utils.joinpath(filename, "__init__.py") if not Utils.isFile(source_filename): source_ref, result = createNamespacePackage( package_name = package_name, module_relpath = filename ) source_filename = None else: source_ref = SourceCodeReferences.fromFilename( filename = Utils.abspath(source_filename), ) result = PythonPackage( name = package_name, package_name = package, source_ref = source_ref ) else: sys.stderr.write( "%s: can't open file '%s'.\n" % ( Utils.basename(sys.argv[0]), filename ) ) sys.exit(2) if not Options.shallHaveStatementLines(): source_ref = source_ref.atInternal() return result, source_ref, source_filename
def _consider(self, constraint_collection, module_filename, module_package): assert module_package is None or \ (type(module_package) is str and module_package != "") module_filename = Utils.normpath(module_filename) if Utils.isDir(module_filename): module_name = Utils.basename(module_filename) module_kind = "py" elif module_filename.endswith(".py"): module_name = Utils.basename(module_filename)[:-3] module_kind = "py" elif module_filename.endswith(".so"): module_kind = "shlib" module_name = Utils.basename(module_filename)[:-3] elif module_filename.endswith(".pyd"): module_kind = "shlib" module_name = Utils.basename(module_filename)[:-4] else: module_kind = None module_name = None if module_kind is not None: decision, reason = decideRecursion( module_filename = module_filename, module_name = module_name, module_package = module_package, module_kind = module_kind ) if decision: module_relpath = Utils.relpath(module_filename) imported_module, added_flag = recurseTo( module_package = module_package, module_filename = module_filename, module_relpath = module_relpath, module_kind = module_kind, reason = reason ) if added_flag: constraint_collection.signalChange( "new_code", imported_module.getSourceReference(), "Recursed to module." ) return imported_module elif decision is None and module_kind == "py": if module_package is None: module_fullpath = module_name else: module_fullpath = module_package + '.' + module_name if module_filename not in self._warned_about and \ module_fullpath not in getModuleWhiteList(): self._warned_about.add(module_filename) warning( """\ Not recursing to '%(full_path)s' (%(filename)s), please specify \ --recurse-none (do not warn), \ --recurse-all (recurse to all), \ --recurse-not-to=%(full_path)s (ignore it), \ --recurse-to=%(full_path)s (recurse to it) to change.""" % { "full_path" : module_fullpath, "filename" : module_filename } )
def _consider(self, constraint_collection, module_filename, module_package): assert module_package is None or \ (type(module_package) is str and module_package != "") module_filename = Utils.normpath(module_filename) if Utils.isDir(module_filename): module_name = Utils.basename(module_filename) module_kind = "py" elif module_filename.endswith(".py"): module_name = Utils.basename(module_filename)[:-3] module_kind = "py" elif module_filename.endswith(".so"): module_kind = "shlib" module_name = Utils.basename(module_filename)[:-3] elif module_filename.endswith(".pyd"): module_kind = "shlib" module_name = Utils.basename(module_filename)[:-4] else: module_kind = None module_name = None if module_kind is not None: decision, reason = decideRecursion(module_filename=module_filename, module_name=module_name, module_package=module_package, module_kind=module_kind) if decision: module_relpath = Utils.relpath(module_filename) imported_module, added_flag = recurseTo( module_package=module_package, module_filename=module_filename, module_relpath=module_relpath, module_kind=module_kind, reason=reason) if added_flag: constraint_collection.signalChange( "new_code", imported_module.getSourceReference(), "Recursed to module.") return imported_module elif decision is None and module_kind == "py": if module_package is None: module_fullpath = module_name else: module_fullpath = module_package + '.' + module_name if module_filename not in self._warned_about and \ module_fullpath not in getModuleWhiteList(): self._warned_about.add(module_filename) warning("""\ Not recursing to '%(full_path)s' (%(filename)s), please specify \ --recurse-none (do not warn), \ --recurse-all (recurse to all), \ --recurse-not-to=%(full_path)s (ignore it), \ --recurse-to=%(full_path)s (recurse to it) to change.""" % { "full_path": module_fullpath, "filename": module_filename })
def decideModuleTree(filename, package, is_shlib, is_top, is_main): # Many variables, branches, due to the many cases, pylint: disable=R0912,R0915 assert package is None or type(package) is str assert filename is not None if is_main and Utils.isDir(filename): source_filename = Utils.joinpath(filename, "__main__.py") if not Utils.isFile(source_filename): sys.stderr.write( "%s: can't find '__main__' module in '%s'\n" % ( Utils.basename(sys.argv[0]), filename ) ) sys.exit(2) filename = source_filename main_added = True else: main_added = False if Utils.isFile(filename): source_filename = filename source_ref = SourceCodeReferences.fromFilename( filename = filename, ) if is_main: module_name = "__main__" else: module_name = Utils.basename(filename) if module_name.endswith(".py"): module_name = module_name[:-3] if is_shlib: module_name = module_name.split('.')[0] if '.' in module_name: sys.stderr.write( "Error, '%s' is not a proper python module name.\n" % ( module_name ) ) sys.exit(2) if is_shlib: result = PythonShlibModule( name = module_name, package_name = package, source_ref = source_ref ) elif is_main: result = PythonMainModule( main_added = main_added, source_ref = source_ref ) else: if package is not None: full_name = package + "." + module_name else: full_name = module_name decision = Plugins.decideCompilation(full_name, source_ref) if decision == "compiled": result = CompiledPythonModule( name = module_name, package_name = package, source_ref = source_ref ) else: source_code = readSourceCodeFromFilename(module_name, filename) source_code = Plugins.onFrozenModuleSourceCode( module_name = full_name, is_package = False, source_code = source_code ) bytecode = compile(source_code, filename, "exec") bytecode = Plugins.onFrozenModuleBytecode( module_name = module_name, is_package = False, bytecode = bytecode ) result = UncompiledPythonModule( name = module_name, package_name = package, bytecode = bytecode, filename = filename, user_provided = True, technical = False, source_ref = source_ref ) # Don't read it anymore. source_filename = None elif Importing.isPackageDir(filename): if is_top: package_name = Utils.splitpath(filename)[-1] else: package_name = Utils.basename(filename) source_filename = Utils.joinpath(filename, "__init__.py") if not Utils.isFile(source_filename): source_ref, result = createNamespacePackage( package_name = package_name, module_relpath = filename ) source_filename = None else: source_ref = SourceCodeReferences.fromFilename( filename = Utils.abspath(source_filename), ) if package is not None: full_name = package + "." + package_name else: full_name = package_name decision = Plugins.decideCompilation(full_name, source_ref) if decision == "compiled": result = CompiledPythonPackage( name = package_name, package_name = package, source_ref = source_ref ) else: bytecode = compile(source_code, filename, "exec") bytecode = Plugins.onFrozenModuleBytecode( module_name = module_name, is_package = False, bytecode = bytecode ) result = UncompiledPythonPackage( name = module_name, package_name = package, bytecode = bytecode, filename = filename, user_provided = True, technical = False, source_ref = source_ref ) # Don't read it anymore. source_filename = None else: sys.stderr.write( "%s: can't open file '%s'.\n" % ( Utils.basename(sys.argv[0]), filename ) ) sys.exit(2) if not Options.shallHaveStatementLines(): source_ref = source_ref.atInternal() return result, source_ref, source_filename
def getStandaloneDirectoryPath(main_module): return Options.getOutputPath( path = Utils.basename( getTreeFilenameWithSuffix(main_module, ".dist") ) )
def copyUsedDLLs(dist_dir, standalone_entry_points): # This is terribly complex, because we check the list of used DLLs # trying to avoid duplicates, and detecting errors with them not # being binary identical, so we can report them. And then of course # we also need to handle OS specifics, pylint: disable=R0912 dll_map = [] used_dlls = detectUsedDLLs(standalone_entry_points) for dll_filename1, sources1 in tuple(iterItems(used_dlls)): for dll_filename2, sources2 in tuple(iterItems(used_dlls)): if dll_filename1 == dll_filename2: continue # Colliding basenames are an issue to us. if Utils.basename(dll_filename1) != Utils.basename(dll_filename2): continue # May already have been removed earlier if dll_filename1 not in used_dlls: continue if dll_filename2 not in used_dlls: continue dll_name = Utils.basename(dll_filename1) if Options.isShowInclusion(): info( """Colliding DLL names for %s, checking identity of \ '%s' <-> '%s'.""" % ( dll_name, dll_filename1, dll_filename2, ) ) # Check that if a DLL has the same name, if it's identical, # happens at least for OSC and Fedora 20. import filecmp if filecmp.cmp(dll_filename1, dll_filename2): del used_dlls[dll_filename2] continue # So we have conflicting DLLs, in which case we do not proceed. sys.exit( """Error, conflicting DLLs for '%s'. %s used by: %s different from %s used by %s""" % ( dll_name, dll_filename1, "\n ".join(sources1), dll_filename2, "\n ".join(sources2) ) ) for dll_filename, sources in iterItems(used_dlls): dll_name = Utils.basename(dll_filename) target_path = Utils.joinpath( dist_dir, dll_name ) shutil.copy( dll_filename, target_path ) dll_map.append( (dll_filename, dll_name) ) if Options.isShowInclusion(): info( "Included used shared library '%s' (used by %s)." % ( dll_filename, ", ".join(sources) ) ) if Utils.getOS() == "Darwin": # For MacOS, the binary and the DLLs needs to be changed to reflect # the relative DLL location in the ".dist" folder. for standalone_entry_point in standalone_entry_points: fixupBinaryDLLPaths( binary_filename = standalone_entry_point[1], is_exe = standalone_entry_point is standalone_entry_points[0], dll_map = dll_map ) for _original_path, dll_filename in dll_map: fixupBinaryDLLPaths( binary_filename = Utils.joinpath( dist_dir, dll_filename ), is_exe = False, dll_map = dll_map ) if Utils.getOS() == "Linux": # For Linux, the "rpath" of libraries may be an issue and must be # removed. for _original_path, dll_filename in dll_map: removeSharedLibraryRPATH( Utils.joinpath(dist_dir, dll_filename) ) for standalone_entry_point in standalone_entry_points[1:]: removeSharedLibraryRPATH( standalone_entry_point[1] )
def copyUsedDLLs(dist_dir, standalone_entry_points): # This is terribly complex, because we check the list of used DLLs # trying to avoid duplicates, and detecting errors with them not # being binary identical, so we can report them. And then of course # we also need to handle OS specifics, pylint: disable=R0912 dll_map = [] used_dlls = detectUsedDLLs(standalone_entry_points) for dll_filename1, sources1 in tuple(iterItems(used_dlls)): for dll_filename2, sources2 in tuple(iterItems(used_dlls)): if dll_filename1 == dll_filename2: continue # Colliding basenames are an issue to us. if Utils.basename(dll_filename1) != Utils.basename(dll_filename2): continue # May already have been removed earlier if dll_filename1 not in used_dlls: continue if dll_filename2 not in used_dlls: continue dll_name = Utils.basename(dll_filename1) if Options.isShowInclusion(): info( """Colliding DLL names for %s, checking identity of \ '%s' <-> '%s'.""" % ( dll_name, dll_filename1, dll_filename2, ) ) # Check that if a DLL has the same name, if it's identical, # happens at least for OSC and Fedora 20. import filecmp if filecmp.cmp(dll_filename1, dll_filename2): del used_dlls[dll_filename2] continue # So we have conflicting DLLs, in which case we do not proceed. sys.exit( """Error, conflicting DLLs for '%s'. %s used by: %s different from %s used by %s""" % ( dll_name, dll_filename1, "\n ".join(sources1), dll_filename2, "\n ".join(sources2) ) ) for dll_filename, sources in iterItems(used_dlls): dll_name = Utils.basename(dll_filename) target_path = Utils.joinpath( dist_dir, dll_name ) shutil.copy( dll_filename, target_path ) dll_map.append( (dll_filename, dll_name) ) if Options.isShowInclusion(): info( "Included used shared library '%s' (used by %s)." % ( dll_filename, ", ".join(sources) ) ) if Utils.getOS() == "Darwin": # For MacOS, the binary and the DLLs needs to be changed to reflect # the relative DLL location in the ".dist" folder. for standalone_entry_point in standalone_entry_points: fixupBinaryDLLPaths( binary_filename = standalone_entry_point[0], is_exe = standalone_entry_point is standalone_entry_points[0], dll_map = dll_map ) for _original_path, dll_filename in dll_map: fixupBinaryDLLPaths( binary_filename = Utils.joinpath( dist_dir, dll_filename ), is_exe = False, dll_map = dll_map ) if Utils.getOS() == "Linux": # For Linux, the "rpath" of libraries may be an issue and must be # removed. for _original_path, dll_filename in dll_map: removeSharedLibraryRPATH( Utils.joinpath(dist_dir, dll_filename) ) for standalone_entry_point in standalone_entry_points[1:]: removeSharedLibraryRPATH( standalone_entry_point[0] )