def onEnterNode(self, node): try: self._onEnterNode(node) except Exception: Tracing.printError("Problem with %r at %s" % (node, node.getSourceReference().getAsString())) raise
def createModuleTree(module, source_ref, source_code, is_main): if Options.isShowProgress(): memory_watch = Utils.MemoryWatch() try: module_body = buildParseTree(provider=module, source_code=source_code, source_ref=source_ref, is_module=True, is_main=is_main) except RuntimeError as e: if "maximum recursion depth" in e.args[0]: raise CodeTooComplexCode(module.getFullName(), module.getCompileTimeFilename()) raise if module_body.isStatementsFrame(): module_body = makeStatementsSequenceFromStatement( statement=module_body, ) module.setBody(module_body) completeVariableClosures(module) if Options.isShowProgress(): memory_watch.finish() Tracing.printLine("Memory usage changed loading module '%s': %s" % (module.getFullName(), memory_watch.asStr()))
def createModuleTree(module, source_ref, source_code, is_main): if Options.isShowProgress(): memory_watch = Utils.MemoryWatch() try: module_body = buildParseTree( provider=module, source_code=source_code, source_ref=source_ref, is_module=True, is_main=is_main ) except RuntimeError as e: if "maximum recursion depth" in e.args[0]: raise CodeTooComplexCode(module.getFullName(), module.getCompileTimeFilename()) raise if module_body.isStatementsFrame(): module_body = makeStatementsSequenceFromStatement(statement=module_body) module.setBody(module_body) completeVariableClosures(module) if Options.isShowProgress(): memory_watch.finish() Tracing.printLine("Memory usage changed loading module '%s': %s" % (module.getFullName(), memory_watch.asStr()))
def runScons(options, quiet): with _setupSconsEnvironment(): if Options.shallCompileWithoutBuildDirectory(): # Make sure we become non-local, by changing all paths to be # absolute, but ones that can be resolved by any program # externally, as the Python of Scons may not be good at unicode. options = copy.deepcopy(options) source_dir = options["source_dir"] options["source_dir"] = "." options["result_name"] = getExternalUsePath( options["result_name"], only_dirname=True ) options["nuitka_src"] = getExternalUsePath(options["nuitka_src"]) if "result_exe" in options: options["result_exe"] = getExternalUsePath( options["result_exe"], only_dirname=True ) if "icon_path" in options: options["icon_path"] = getExternalUsePath( options["icon_path"], only_dirname=True ) else: source_dir = None scons_command = _buildSconsCommand(quiet, options) if Options.isShowScons(): Tracing.printLine("Scons command:", " ".join(scons_command)) Tracing.flushStdout() return subprocess.call(scons_command, shell=False, cwd=source_dir) == 0
def createModuleTree(module, source_ref, source_filename, is_main): if Options.isShowProgress(): memory_watch = Utils.MemoryWatch() source_code = readSourceCodeFromFilename( source_filename ) module_body = buildParseTree( provider = module, source_code = source_code, source_ref = source_ref, is_module = True, is_main = is_main ) module.setBody( module_body ) completeVariableClosures( module ) if Options.isShowProgress(): memory_watch.finish() Tracing.printLine( "Memory usage changed loading module '%s': %s" % ( module.getFullName(), memory_watch.asStr() ) )
def dump(xml): value = toString(xml).rstrip() if Utils.python_version >= 300: value = value.decode("utf-8") Tracing.printLine(value)
def createModuleTree(module, source_ref, source_code, is_main): if Options.isShowProgress(): memory_watch = Utils.MemoryWatch() module_body = buildParseTree( provider = module, source_code = source_code, source_ref = source_ref, is_module = True, is_main = is_main ) if module_body.isStatementsFrame(): module_body = makeStatementsSequenceFromStatement( statement = module_body, ) module.setBody(module_body) completeVariableClosures(module) if Options.isShowProgress(): memory_watch.finish() Tracing.printLine( "Memory usage changed loading module '%s': %s" % ( module.getFullName(), memory_watch.asStr() ) )
def runScons( options, quiet ): # For the scons file to find the static C++ files and include path. The scons file is # unable to use __file__ for the task. os.environ[ "NUITKA_SCONS" ] = getSconsDataPath() if os.name == "nt": # On Windows this Scons variable must be set by us. os.environ[ "SCONS_LIB_DIR" ] = Utils.joinpath( getSconsInlinePath(), "lib", "scons-2.0.1" ) # Also, for MinGW we can avoid the user having to add the path if he used the # default path or installed it on the same drive by appending to the PATH variable # before executing scons. os.environ[ "PATH" ] += r";\MinGW\bin;C:\MinGW\bin" scons_command = """%(python)s %(binary)s %(quiet)s -f %(scons_file)s --jobs %(job_limit)d %(options)s""" % { "python" : sys.executable if Utils.python_version < 300 else "python", "binary" : getSconsBinaryPath(), "quiet" : "--quiet" if quiet else "", "scons_file" : Utils.joinpath( getSconsDataPath(), "SingleExe.scons" ), "job_limit" : Options.getJobLimit(), "options" : " ".join( "%s=%s" % ( key, value ) for key, value in options.items() ) } if Options.isShowScons(): Tracing.printLine( "Scons command:", scons_command ) return 0 == os.system( scons_command )
def createModuleTree(module, source_ref, source_filename, is_main): if Options.isShowProgress(): memory_watch = Utils.MemoryWatch() source_code = readSourceCodeFromFilename(source_filename) module_body = buildParseTree( provider = module, source_code = source_code, source_ref = source_ref, is_module = True, is_main = is_main ) module.setBody( module_body ) completeVariableClosures(module) if Options.isShowProgress(): memory_watch.finish() Tracing.printLine( "Memory usage changed loading module '%s': %s" % ( module.getFullName(), memory_watch.asStr() ) )
def runScons(options, quiet): with setupSconsEnvironment(): scons_command = buildSconsCommand(quiet, options) if Options.isShowScons(): Tracing.printLine("Scons command:", ' '.join(scons_command)) return subprocess.call(scons_command, shell = False) == 0
def runScons(options, quiet): with setupSconsEnvironment(): scons_command = buildSconsCommand(quiet, options) if Options.isShowScons(): Tracing.printLine("Scons command:", ' '.join(scons_command)) return subprocess.call(scons_command, shell=False) == 0
def onEnterNode(self, node): try: self._onEnterNode(node) except Exception: Tracing.printError( "Problem with %r at %s" % (node, node.getSourceReference().getAsString()) ) raise
def runScons(options, quiet): # For the scons file to find the static C++ files and include path. The # scons file is unable to use __file__ for the task. os.environ["NUITKA_SCONS"] = getSconsDataPath() if Utils.getOS() == "Windows": # On Windows this Scons variable must be set by us. os.environ["SCONS_LIB_DIR"] = Utils.joinpath( getSconsInlinePath(), "lib", "scons-2.3.0" ) # Also, for MinGW we can avoid the user having to add the path if he # used the default path or installed it on the same drive by appending # to the PATH variable before executing scons. os.environ["PATH"] += r";\MinGW\bin;C:\MinGW\bin" scons_command = getSconsBinaryCall() if quiet: scons_command.append("--quiet") scons_command += [ # The scons file "-f", Utils.joinpath(getSconsDataPath(), "SingleExe.scons"), # Parallel compilation. "--jobs", str(Options.getJobLimit()), # Do not warn about deprecations of Scons "--warn=no-deprecated", # Don't load "site_scons" at all. "--no-site-dir", ] if Options.isShowScons(): scons_command.append("--debug=explain") # Option values to provide to scons. for key, value in options.items(): scons_command += [key + "=" + value] if Options.isShowScons(): Tracing.printLine("Scons command:", " ".join(scons_command)) return 0 == subprocess.call(scons_command)
def runScons(options, quiet): # For the scons file to find the static C++ files and include path. The scons file is # unable to use __file__ for the task. os.environ["NUITKA_SCONS"] = getSconsDataPath() if os.name == "nt": # On Windows this Scons variable must be set by us. os.environ["SCONS_LIB_DIR"] = Utils.joinpath(getSconsInlinePath(), "lib", "scons-2.0.1") # Also, for MinGW we can avoid the user having to add the path if he used the # default path or installed it on the same drive by appending to the PATH variable # before executing scons. os.environ["PATH"] += r";\MinGW\bin;C:\MinGW\bin" # Scons is Python2 only, so we need to make the system find a suitable Python binary. if Utils.python_version < 300: python_exe = sys.executable elif os.name == "nt": if os.path.exists(r"c:\Python27\python.exe"): python_exe = r"c:\Python27\python.exe" elif os.path.exists(r"c:\Python26\python.exe"): python_exe = r"c:\Python26\python.exe" else: sys.exit( """Error, need to find Python2 executable under C:\\Python26 or \ C:\\Python27 to execute scons which is not Python3 compatible.""") else: python_exe = "python" scons_command = """%(python)s %(binary)s %(quiet)s --warn=no-deprecated -f %(scons_file)s --jobs %(job_limit)d %(options)s""" % { "python": python_exe, "binary": getSconsBinaryPath(), "quiet": "--quiet" if quiet else "", "scons_file": Utils.joinpath(getSconsDataPath(), "SingleExe.scons"), "job_limit": Options.getJobLimit(), "options": " ".join("%s=%s" % (key, value) for key, value in options.items()) } if Options.isShowScons(): Tracing.printLine("Scons command:", scons_command) return 0 == os.system(scons_command)
def onStatement(self, statement): try: assert statement.isStatement(), statement new_statement, change_tags, change_desc = \ statement.computeStatement(self) # print new_statement, change_tags, change_desc if new_statement is not statement: self.signalChange(change_tags, statement.getSourceReference(), change_desc) return new_statement except Exception: Tracing.printError("Problem with statement at %s:" % statement.getSourceReference().getAsString()) raise
def runScons(options, quiet): # For the scons file to find the static C++ files and include path. The # scons file is unable to use __file__ for the task. os.environ["NUITKA_SCONS"] = getSconsDataPath() if Utils.getOS() == "Windows": # On Windows this Scons variable must be set by us. os.environ["SCONS_LIB_DIR"] = Utils.joinpath( getSconsInlinePath(), "lib", "scons-2.3.2" ) scons_command = getSconsBinaryCall() if quiet: scons_command.append("--quiet") scons_command += [ # The scons file "-f", Utils.joinpath(getSconsDataPath(), "SingleExe.scons"), # Parallel compilation. "--jobs", str(Options.getJobLimit()), # Do not warn about deprecations of Scons "--warn=no-deprecated", # Don't load "site_scons" at all. "--no-site-dir", ] if Options.isShowScons(): scons_command.append("--debug=explain") # Option values to provide to scons. for key, value in options.items(): scons_command += [key + "=" + value] if Options.isShowScons(): Tracing.printLine("Scons command:", " ".join(scons_command)) return 0 == subprocess.call(scons_command, shell = False)
def runScons(options, quiet, scons_filename): with _setupSconsEnvironment(): if Options.shallCompileWithoutBuildDirectory(): # Make sure we become non-local, by changing all paths to be # absolute, but ones that can be resolved by any program # externally, as the Python of Scons may not be good at unicode. options = copy.deepcopy(options) source_dir = options["source_dir"] options["source_dir"] = "." options["result_name"] = getExternalUsePath(options["result_name"], only_dirname=True) options["nuitka_src"] = getExternalUsePath(options["nuitka_src"]) if "result_exe" in options: options["result_exe"] = getExternalUsePath( options["result_exe"], only_dirname=True) if "compiled_exe" in options: options["compiled_exe"] = getExternalUsePath( options["compiled_exe"], only_dirname=True) else: source_dir = None scons_command = _buildSconsCommand(quiet=quiet, options=options, scons_filename=scons_filename) if Options.isShowScons(): Tracing.printLine("Scons command:", " ".join(scons_command)) Tracing.flushStandardOutputs() # Call scons, make sure to pass on quiet setting. with Execution.withEnvironmentVarOverridden( "NUITKA_QUIET", "1" if Tracing.is_quiet else "0"): result = subprocess.call(scons_command, shell=False, cwd=source_dir) flushSconsReports() if result == 0: checkCachingSuccess(source_dir or options["source_dir"]) return result == 0
def fromXML(provider, xml, source_ref=None): assert xml.tag == "node", xml kind, node_class, args, source_ref = extractKindAndArgsFromXML( xml, source_ref) if "constant" in args: # TODO: Try and reduce/avoid this, use marshal and/or pickle from a file # global stream instead. For now, this will do. pylint: disable=eval-used args["constant"] = eval(args["constant"]) if kind in ( "ExpressionFunctionBody", "PythonMainModule", "PythonCompiledModule", "PythonCompiledPackage", "PythonInternalModule", ): delayed = node_class.named_children if "code_flags" in args: args["future_spec"] = fromFlags(args["code_flags"]) else: delayed = () for child in xml: assert child.tag == "role", child.tag child_name = child.attrib["name"] # Might want to want until provider is updated with some # children. In these cases, we pass the XML node, rather # than a Nuitka node. if child_name not in delayed: args[child_name] = makeChild(provider, child, source_ref) else: args[child_name] = child try: return node_class.fromXML(provider=provider, source_ref=source_ref, **args) except (TypeError, AttributeError): Tracing.printLine(node_class, args, source_ref) raise
def runScons( options, quiet ): # For the scons file to find the static C++ files and include path. The scons file is # unable to use __file__ for the task. os.environ[ "NUITKA_SCONS" ] = getSconsDataPath() if os.name == "nt": # On Windows this Scons variable must be set by us. os.environ[ "SCONS_LIB_DIR" ] = Utils.joinpath( getSconsInlinePath(), "lib", "scons-2.0.1" ) # Also, for MinGW we can avoid the user having to add the path if he used the # default path or installed it on the same drive by appending to the PATH variable # before executing scons. os.environ[ "PATH" ] += r";\MinGW\bin;C:\MinGW\bin" # Scons is Python2 only, so we need to make the system find a suitable Python binary. if Utils.python_version < 300: python_exe = sys.executable elif os.name == "nt": if os.path.exists( r"c:\Python27\python.exe" ): python_exe = r"c:\Python27\python.exe" elif os.path.exists( r"c:\Python26\python.exe" ): python_exe = r"c:\Python26\python.exe" else: sys.exit( """Error, need to find Python2 executable under C:\\Python26 or \ C:\\Python27 to execute scons which is not Python3 compatible.""" ) else: python_exe = "python" scons_command = """%(python)s %(binary)s %(quiet)s --warn=no-deprecated -f %(scons_file)s --jobs %(job_limit)d %(options)s""" % { "python" : python_exe, "binary" : getSconsBinaryPath(), "quiet" : "--quiet" if quiet else "", "scons_file" : Utils.joinpath( getSconsDataPath(), "SingleExe.scons" ), "job_limit" : Options.getJobLimit(), "options" : " ".join( "%s=%s" % ( key, value ) for key, value in options.items() ) } if Options.isShowScons(): Tracing.printLine( "Scons command:", scons_command ) return 0 == os.system( scons_command )
def dumpActiveTraces(self): Tracing.printSeparator() Tracing.printLine("Active are:") for variable, _version in sorted(self.variable_actives.iteritems()): self.getVariableCurrentTrace(variable).dump() Tracing.printSeparator()
def onStatement(self, statement): try: assert statement.isStatement(), statement new_statement, change_tags, change_desc = statement.computeStatement(self) # print new_statement, change_tags, change_desc if new_statement is not statement: self.signalChange( change_tags, statement.getSourceReference(), change_desc ) return new_statement except Exception: Tracing.printError( "Problem with statement at %s:\n-> %s" % ( statement.source_ref.getAsString(), readSourceLine(statement.source_ref), ) ) raise
def dump(self, level=0): Tracing.printIndented(level, self) Tracing.printSeparator(level) for visitable in self.getVisitableNodes(): visitable.dump(level + 1) Tracing.printSeparator(level)
def dump(self, level = 0): Tracing.printIndented(level, self) Tracing.printSeparator(level) for visitable in self.getVisitableNodes(): visitable.dump(level + 1) Tracing.printSeparator(level)
def parseArgs(will_reexec): # singleton with many cases checking the options right away. # pylint: disable=global-statement,too-many-branches,too-many-locals,too-many-statements global is_nuitka_run, options, positional_args, extra_args, is_debug, is_nondebug, is_fullcompat if os.name == "nt": # Windows store Python's don't allow looking at the python, catch that. try: with open(sys.executable): pass except OSError: Tracing.general.sysexit( "Error, the Python from Windows store is not supported, check the User Manual of Nuitka ." ) is_nuitka_run, options, positional_args, extra_args = parseOptions( logger=Tracing.options_logger) if options.quiet or int(os.environ.get("NUITKA_QUIET", "0")): Tracing.setQuiet() if not will_reexec and not shallDumpBuiltTreeXML(): Tracing.options_logger.info("Used command line options: %s" % " ".join(sys.argv[1:])) if options.progress_bar and not will_reexec: Progress.enableProgressBar() if options.verbose_output and not will_reexec: Tracing.optimization_logger.setFileHandle( # Can only have unbuffered binary IO in Python3, therefore not disabling buffering here. open(options.verbose_output, "w")) options.verbose = True Tracing.optimization_logger.is_quiet = not options.verbose if options.show_inclusion_output and not will_reexec: Tracing.inclusion_logger.setFileHandle( # Can only have unbuffered binary IO in Python3, therefore not disabling buffering here. open(options.show_inclusion_output, "w")) options.show_inclusion = True Tracing.progress_logger.is_quiet = not options.show_progress # Onefile implies standalone build. if options.is_onefile: options.is_standalone = True # Provide a tempdir spec implies onefile tempdir. if options.windows_onefile_tempdir_spec: options.is_windows_onefile_tempdir = True # Standalone mode implies an executable, not importing "site" module, which is # only for this machine, recursing to all modules, and even including the # standard library. if options.is_standalone: if not options.executable: Tracing.options_logger.sysexit("""\ Error, conflicting options, cannot make standalone module, only executable. Modules are supposed to be imported to an existing Python installation, therefore it makes no sense to include a Python runtime.""") for any_case_module in getShallFollowModules(): if any_case_module.startswith("."): bad = True else: for char in "/\\:": if char in any_case_module: bad = True break else: bad = False if bad: Tracing.options_logger.sysexit("""\ Error, '--follow-import-to' takes only module names, not directory path '%s'.""" % any_case_module) for no_case_module in getShallFollowInNoCase(): if no_case_module.startswith("."): bad = True else: for char in "/\\:": if char in no_case_module: bad = True break else: bad = False if bad: Tracing.options_logger.sysexit("""\ Error, '--nofollow-import-to' takes only module names, not directory path '%s'.""" % no_case_module) scons_python = getPythonPathForScons() if scons_python is not None and not os.path.isfile(scons_python): Tracing.options_logger.sysexit( "Error, no such Python binary %r, should be full path." % scons_python) if options.output_filename is not None and (isStandaloneMode() or shallMakeModule()): Tracing.options_logger.sysexit("""\ Error, can only specify output filename for acceleration mode, not for module mode where filenames are mandatory, and not for standalone where there is a sane default used inside the dist folder.""") if getOS() == "Linux": if len(getIconPaths()) > 1: Tracing.options_logger.sysexit( "Error, can only use one icon on Linux.") for icon_path in getIconPaths(): if "#" in icon_path and isWin32Windows(): icon_path, icon_index = icon_path.rsplit("#", 1) if not icon_index.isdigit() or int(icon_index) < 0: Tracing.options_logger.sysexit( "Error, icon number in %r not valid." % (icon_path + "#" + icon_index)) if not os.path.exists(icon_path): Tracing.options_logger.sysexit( "Error, icon path %r does not exist." % icon_path) if getWindowsIconExecutablePath(): Tracing.options_logger.sysexit( "Error, can only use icons from template executable or from icon files, but not both." ) icon_exe_path = getWindowsIconExecutablePath() if icon_exe_path is not None and not os.path.exists(icon_exe_path): Tracing.options_logger.sysexit("Error, icon path %r does not exist." % icon_exe_path) try: file_version = getWindowsFileVersion() except Exception: # Catch all the things, don't want any interface, pylint: disable=broad-except Tracing.options_logger.sysexit( "Error, file version must be a tuple of up to 4 integer values.") try: product_version = getWindowsProductVersion() except Exception: # Catch all the things, don't want any interface, pylint: disable=broad-except Tracing.options_logger.sysexit( "Error, product version must be a tuple of up to 4 integer values." ) if getWindowsCompanyName() == "": Tracing.options_logger.sysexit( """Error, empty string is not an acceptable company name.""") if getWindowsProductName() == "": Tracing.options_logger.sysexit( """Error, empty string is not an acceptable product name.""") if file_version or product_version or getWindowsVersionInfoStrings(): if not (file_version or product_version) and getWindowsCompanyName(): Tracing.options_logger.sysexit( "Error, company name and file or product version need to be given when any version information is given." ) if isOnefileMode() and not hasOnefileSupportedOS(): Tracing.options_logger.sysexit("Error, unsupported OS for onefile %r" % getOS()) if isOnefileMode() and os.name == "nt": if not getWindowsCompanyName() and not isWindowsOnefileTempDirMode(): Tracing.options_logger.sysexit( """Error, onefile on Windows needs more options. It requires either company name and product version to be given or the selection of onefile temp directory mode. Check --help output.""") if options.recurse_none and options.recurse_all: Tracing.options_logger.sysexit( "Conflicting options '--follow-imports' and '--nofollow-imports' given." ) if getShallIncludePackageData() and not isStandaloneMode(): Tracing.options_logger.sysexit( "Error, package data files are only included in standalone or onefile mode." ) for module_pattern in getShallIncludePackageData(): if (module_pattern.startswith("-") or "/" in module_pattern or "\\" in module_pattern): Tracing.options_logger.sysexit( "Error, '--include-package-data' needs module name or pattern as an argument, not %r." % module_pattern) for module_pattern in getShallFollowModules(): if (module_pattern.startswith("-") or "/" in module_pattern or "\\" in module_pattern): Tracing.options_logger.sysexit( "Error, '--follow-import-to' options needs module name or pattern as an argument, not %r." % module_pattern) for module_pattern in getShallFollowInNoCase(): if (module_pattern.startswith("-") or "/" in module_pattern or "\\" in module_pattern): Tracing.options_logger.sysexit( "Error, '--nofollow-import-to' options needs module name or pattern as an argument, not %r." % module_pattern) for data_file in options.data_files: if "=" not in data_file: Tracing.options_logger.sysexit( "Error, malformed data file description, must specify relative target path with =." ) src, dst = data_file.split("=", 1) if os.path.isabs(dst): Tracing.options_logger.sysexit( "Error, must specify relative target path for data file, not %r." % data_file) if not resolveShellPatternToFilenames(src): Tracing.options_logger.sysexit( "Error, %r does not match any files." % src) for data_dir in options.data_dirs: if "=" not in data_dir: Tracing.options_logger.sysexit( "Error, malformed data dir description, must specify relative target path with '=' separating it." ) src, dst = data_dir.split("=", 1) if os.path.isabs(dst): Tracing.options_logger.sysexit( "Error, must specify relative target path for data dir, not %r as in %r." % (dst, data_dir)) if not os.path.isdir(src): Tracing.options_logger.sysexit( "Error, must specify existing source data directory, not %r as in %r." % (dst, data_dir)) if (options.data_files or options.data_dirs) and not isStandaloneMode(): Tracing.options_logger.sysexit( "Error, data files are only included in standalone or onefile mode." ) for pattern in getShallFollowExtraFilePatterns(): if os.path.isdir(pattern): Tracing.options_logger.sysexit( "Error, pattern %r given to '--include-plugin-files' cannot be a directory name." % pattern) is_debug = _isDebug() is_nondebug = not is_debug is_fullcompat = _isFullCompat()
def getCachedDownload( url, binary, flatten, is_arch_specific, specificity, message, reject, assume_yes_for_downloads, ): # Many branches to deal with, pylint: disable=too-many-branches,too-many-statements nuitka_app_dir = getAppDir() nuitka_app_dir = os.path.join(nuitka_app_dir, os.path.basename(binary).replace(".exe", "")) if is_arch_specific: nuitka_app_dir = os.path.join(nuitka_app_dir, is_arch_specific) if specificity: nuitka_app_dir = os.path.join(nuitka_app_dir, specificity) download_path = os.path.join(nuitka_app_dir, os.path.basename(url)) exe_path = os.path.join(nuitka_app_dir, binary) makePath(nuitka_app_dir) if not os.path.isfile(download_path) and not os.path.isfile(exe_path): if assume_yes_for_downloads: reply = "y" else: Tracing.printLine("""\ %s Is it OK to download and put it in '%s'. No installer needed, cached, one time question. Proceed and download? [Yes]/No """ % (message, nuitka_app_dir)) Tracing.flushStandardOutputs() try: reply = raw_input() except EOFError: reply = "no" if reply.lower() in ("no", "n"): if reject is not None: Tracing.general.sysexit(reject) else: Tracing.general.info("Downloading '%s'." % url) try: urlretrieve(url, download_path) except Exception: # Any kind of error, pylint: disable=broad-except try: urlretrieve(url.replace("https://", "http://"), download_path) except Exception: # Any kind of error, pylint: disable=broad-except Tracing.general.sysexit( "Failed to download '%s'. Contents should manually be copied to '%s'." % (url, download_path)) if not os.path.isfile(exe_path) and os.path.isfile(download_path): Tracing.general.info("Extracting to '%s'" % exe_path) import zipfile try: # Not all Python versions support using it as a context manager, pylint: disable=consider-using-with zip_file = zipfile.ZipFile(download_path) for zip_info in zip_file.infolist(): if zip_info.filename[-1] == "/": continue if flatten: zip_info.filename = os.path.basename(zip_info.filename) zip_file.extract(zip_info, nuitka_app_dir) except Exception: # Catching anything zip throws, pylint: disable=broad-except Tracing.general.info( "Problem with the downloaded zip file, deleting it.") deleteFile(binary, must_exist=False) deleteFile(download_path, must_exist=True) Tracing.general.sysexit("Error, need %r as extracted from %r." % (binary, url)) # Check success here, and make sure it's executable. if os.path.isfile(exe_path): addFileExecutablePermission(exe_path) else: if reject: Tracing.general.sysexit(reject) exe_path = None return exe_path
def _detectImports(command, is_late): # print(command) # Print statements for stuff to show, the modules loaded. if Utils.python_version >= 300: command += '\nimport sys\nprint("\\n".join(sorted("import " + module.__name__ + " # sourcefile " + ' \ 'module.__file__ for module in sys.modules.values() if hasattr(module, "__file__") and ' \ 'module.__file__ != "<frozen>")), file = sys.stderr)' # do not read it, pylint: disable=C0301 import tempfile with tempfile.NamedTemporaryFile(delete=False) as tmp: if Utils.python_version >= 300: command = command.encode('ascii') tmp.write(command) tmp.flush() process = subprocess.Popen( args = [sys.executable, "-s", "-S", "-v", tmp.name], stdout = subprocess.PIPE, stderr = subprocess.PIPE, ) _stdout, stderr = process.communicate() # Don't let errors here go unnoticed. if process.returncode != 0: warning("There is a problem with detecting imports, CPython said:") for line in stderr.split(b"\n"): Tracing.printLine(line) sys.exit("Error, please report the issue with above output.") result = [] debug("Detecting imports:") # bug of PyLint, pylint: disable=E1103 for line in stderr.replace(b"\r", b"").split(b"\n"): if line.startswith(b"import "): # print(line) parts = line.split(b" # ", 2) module_name = parts[0].split(b" ", 2)[1] origin = parts[1].split()[0] if Utils.python_version >= 300: module_name = module_name.decode("utf-8") if origin == b"precompiled": # This is a ".pyc" file that was imported, even before we have a # chance to do anything, we need to preserve it. filename = parts[1][len(b"precompiled from "):] _detectedPrecompiledFile( filename = filename, module_name = module_name, result = result, is_late = is_late ) elif origin == b"sourcefile": filename = parts[1][len(b"sourcefile "):] if filename.endswith(b".py"): _detectedSourceFile( filename = filename, module_name = module_name, result = result, is_late = is_late ) elif not filename.endswith(b"<frozen>"): _detectedShlibFile( filename = filename, module_name = module_name ) elif origin == b"dynamically": # Shared library in early load, happens on RPM based systems and # or self compiled Python installations. filename = parts[1][len(b"dynamically loaded from "):] _detectedShlibFile( filename = filename, module_name = module_name ) return result
def _detectImports(command, user_provided, technical): # This is pretty complicated stuff, with variants to deal with. # pylint: disable=R0912,R0914,R0915 # Print statements for stuff to show, the modules loaded. if python_version >= 300: command += '\nimport sys\nprint("\\n".join(sorted("import " + module.__name__ + " # sourcefile " + ' \ 'module.__file__ for module in sys.modules.values() if hasattr(module, "__file__") and ' \ 'module.__file__ != "<frozen>")), file = sys.stderr)' # do not read it reduced_path = [ path_element for path_element in sys.path if not Utils.areSamePaths( path_element, '.' ) if not Utils.areSamePaths( path_element, Utils.dirname(sys.modules["__main__"].__file__) ) ] # Make sure the right import path (the one Nuitka binary is running with) # is used. command = ("import sys; sys.path = %s;" % repr(reduced_path)) + command import tempfile tmp_file, tmp_filename = tempfile.mkstemp() try: if python_version >= 300: command = command.encode("ascii") os.write(tmp_file, command) os.close(tmp_file) process = subprocess.Popen( args = [sys.executable, "-s", "-S", "-v", tmp_filename], stdout = subprocess.PIPE, stderr = subprocess.PIPE, ) _stdout, stderr = process.communicate() finally: os.unlink(tmp_filename) # Don't let errors here go unnoticed. if process.returncode != 0: warning("There is a problem with detecting imports, CPython said:") for line in stderr.split(b"\n"): Tracing.printLine(line) sys.exit("Error, please report the issue with above output.") result = [] debug("Detecting imports:") for line in stderr.replace(b"\r", b"").split(b"\n"): if line.startswith(b"import "): # print(line) parts = line.split(b" # ", 2) module_name = parts[0].split(b" ", 2)[1] origin = parts[1].split()[0] if python_version >= 300: module_name = module_name.decode("utf-8") if origin == b"precompiled": # This is a ".pyc" file that was imported, even before we have a # chance to do anything, we need to preserve it. filename = parts[1][len(b"precompiled from "):] if python_version >= 300: filename = filename.decode("utf-8") # Do not leave standard library when freezing. if not isStandardLibraryPath(filename): continue _detectedPrecompiledFile( filename = filename, module_name = module_name, result = result, user_provided = user_provided, technical = technical ) elif origin == b"sourcefile": filename = parts[1][len(b"sourcefile "):] if python_version >= 300: filename = filename.decode("utf-8") # Do not leave standard library when freezing. if not isStandardLibraryPath(filename): continue if filename.endswith(".py"): _detectedSourceFile( filename = filename, module_name = module_name, result = result, user_provided = user_provided, technical = technical ) elif not filename.endswith("<frozen>"): # Python3 started lying in "__name__" for the "_decimal" # calls itself "decimal", which then is wrong and also # clashes with "decimal" proper if python_version >= 300: if module_name == "decimal": module_name = "_decimal" _detectedShlibFile( filename = filename, module_name = module_name ) elif origin == b"dynamically": # Shared library in early load, happens on RPM based systems and # or self compiled Python installations. filename = parts[1][len(b"dynamically loaded from "):] if python_version >= 300: filename = filename.decode("utf-8") # Do not leave standard library when freezing. if not isStandardLibraryPath(filename): continue _detectedShlibFile( filename = filename, module_name = module_name ) return result
def runScons(options, quiet): # For the scons file to find the static C++ files and include path. The # scons file is unable to use __file__ for the task. os.environ["NUITKA_SCONS"] = getSconsDataPath() if Utils.getOS() == "Windows": # On Windows this Scons variable must be set by us. os.environ["SCONS_LIB_DIR"] = Utils.joinpath(getSconsInlinePath(), "lib", "scons-2.3.2") scons_command = getSconsBinaryCall() if quiet: scons_command.append("--quiet") scons_command += [ # The scons file "-f", Utils.joinpath(getSconsDataPath(), "SingleExe.scons"), # Parallel compilation. "--jobs", str(Options.getJobLimit()), # Do not warn about deprecation from Scons "--warn=no-deprecated", # Don't load "site_scons" at all. "--no-site-dir", ] if Options.isShowScons(): scons_command.append("--debug=explain") # Option values to provide to scons. Find these in the caller. for key, value in options.items(): scons_command += [key + '=' + value] if Options.isShowScons(): Tracing.printLine("Scons command:", ' '.join(scons_command)) # Remove environment variables that can only harm if we have to switch # major Python versions, these cannot help Python2 to execute scons, this # is a bit of noise, but helpful, pylint: disable=R0912 if Utils.python_version >= 300: if "PYTHONPATH" in os.environ: old_pythonpath = os.environ["PYTHONPATH"] del os.environ["PYTHONPATH"] else: old_pythonpath = None if "PYTHONHOME" in os.environ: old_pythonhome = os.environ["PYTHONHOME"] del os.environ["PYTHONHOME"] else: old_pythonhome = None result = 0 == subprocess.call(scons_command, shell=False) if Utils.python_version >= 300: if old_pythonpath is not None: os.environ["PYTHONPATH"] = old_pythonpath if old_pythonhome is not None: os.environ["PYTHONHOME"] = old_pythonhome 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 = os.path.join(os.environ["APPDATA"], "nuitka") if not Utils.isDir(nuitka_app_dir): os.makedirs(nuitka_app_dir) nuitka_depends_zip = os.path.join( nuitka_app_dir, os.path.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 = os.path.join( 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 parseArgs(): """Parse the command line arguments :meta private: """ # singleton with many cases checking the options right away. # pylint: disable=global-statement,too-many-branches,too-many-locals,too-many-statements global is_nuitka_run, options, positional_args, extra_args, is_debug, is_nondebug global is_fullcompat, is_report_missing, is_verbose if os.name == "nt": # Windows store Python's don't allow looking at the python, catch that. try: with openTextFile(sys.executable, "rb"): pass except OSError: Tracing.general.sysexit( "Error, the Python from Windows store is not supported, check the User Manual of Nuitka ." ) is_nuitka_run, options, positional_args, extra_args = parseOptions( logger=Tracing.options_logger) is_debug = _isDebug() is_nondebug = not is_debug is_fullcompat = _isFullCompat() # TODO: Have dedicated option for it. is_report_missing = is_debug if options.quiet or int(os.environ.get("NUITKA_QUIET", "0")): Tracing.setQuiet() if not shallDumpBuiltTreeXML(): Tracing.options_logger.info("Used command line options: %s" % " ".join(sys.argv[1:])) if os.environ.get("NUITKA_REEXECUTION") and not isAllowedToReexecute(): Tracing.general.sysexit( "Error, not allowed to re-execute, but that has happened.") if options.progress_bar: Progress.enableProgressBar() if options.verbose_output: Tracing.optimization_logger.setFileHandle( # Can only have unbuffered binary IO in Python3, therefore not disabling buffering here. openTextFile(options.verbose_output, "w", encoding="utf8")) options.verbose = True is_verbose = options.verbose Tracing.optimization_logger.is_quiet = not options.verbose if options.show_inclusion_output: Tracing.inclusion_logger.setFileHandle( # Can only have unbuffered binary IO in Python3, therefore not disabling buffering here. openTextFile(options.show_inclusion_output, "w", encoding="utf8")) options.show_inclusion = True Tracing.progress_logger.is_quiet = not options.show_progress # Onefile implies standalone build. if options.is_onefile: options.is_standalone = True # Standalone implies no_site build if options.is_standalone: options.python_flags.insert(0, "no_site") # Provide a tempdir spec implies onefile tempdir, even on Linux. if options.onefile_tempdir_spec: options.is_onefile_tempdir = True if os.path.normpath(options.onefile_tempdir_spec) == ".": Tracing.options_logger.sysexit("""\ Error, using '.' as a value for '--onefile-tempdir-spec' is not supported, you cannot unpack the onefile payload into the same directory as the binary, as that would overwrite it and cause locking issues as well.""") if options.onefile_tempdir_spec.count("%") % 2 != 0: Tracing.options_logger.warning( """Unmatched '%%' is suspicious for '--onefile-tempdir-spec' and may not do what you want it to do: '%s'""" % options.onefile_tempdir_spec) if options.onefile_tempdir_spec.count("%") == 0: Tracing.options_logger.warning( """Not using any variables for '--onefile-tempdir-spec' should only be done if your program absolutely needs to be in the same path always: '%s'""" % options.onefile_tempdir_spec) if os.path.isabs(options.onefile_tempdir_spec): Tracing.options_logger.warning( """Using an absolute path should be avoided unless you are targeting a very well known environment: '%s'""" % options.onefile_tempdir_spec) elif relpath(options.onefile_tempdir_spec): Tracing.options_logger.warning( """Using an relative path above the executable should be avoided unless you are targeting a very well known environment: '%s'""" % options.onefile_tempdir_spec) # Standalone mode implies an executable, not importing "site" module, which is # only for this machine, recursing to all modules, and even including the # standard library. if options.is_standalone: if options.module_mode: Tracing.options_logger.sysexit("""\ Error, conflicting options, cannot make standalone module, only executable. Modules are supposed to be imported to an existing Python installation, therefore it makes no sense to include a Python runtime.""") for any_case_module in getShallFollowModules(): if any_case_module.startswith("."): bad = True else: for char in "/\\:": if char in any_case_module: bad = True break else: bad = False if bad: Tracing.options_logger.sysexit("""\ Error, '--follow-import-to' takes only module names or patterns, not directory path '%s'.""" % any_case_module) for no_case_module in getShallFollowInNoCase(): if no_case_module.startswith("."): bad = True else: for char in "/\\:": if char in no_case_module: bad = True break else: bad = False if bad: Tracing.options_logger.sysexit("""\ Error, '--nofollow-import-to' takes only module names or patterns, not directory path '%s'.""" % no_case_module) scons_python = getPythonPathForScons() if scons_python is not None and not os.path.isfile(scons_python): Tracing.options_logger.sysexit( "Error, no such Python binary %r, should be full path." % scons_python) if options.output_filename is not None and ( (isStandaloneMode() and not isOnefileMode()) or shallMakeModule()): Tracing.options_logger.sysexit("""\ Error, may only specify output filename for acceleration and onefile mode, but not for module mode where filenames are mandatory, and not for standalone where there is a sane default used inside the dist folder.""") if isLinux(): if len(getIconPaths()) > 1: Tracing.options_logger.sysexit( "Error, can only use one icon file on Linux.") if isMacOS(): if len(getIconPaths()) > 1: Tracing.options_logger.sysexit( "Error, can only use one icon file on macOS.") for icon_path in getIconPaths(): if "#" in icon_path and isWin32Windows(): icon_path, icon_index = icon_path.rsplit("#", 1) if not icon_index.isdigit() or int(icon_index) < 0: Tracing.options_logger.sysexit( "Error, icon number in %r not valid." % (icon_path + "#" + icon_index)) if not os.path.exists(icon_path): Tracing.options_logger.sysexit( "Error, icon path %r does not exist." % icon_path) if getWindowsIconExecutablePath(): Tracing.options_logger.sysexit( "Error, can only use icons from template executable or from icon files, but not both." ) icon_exe_path = getWindowsIconExecutablePath() if icon_exe_path is not None and not os.path.exists(icon_exe_path): Tracing.options_logger.sysexit("Error, icon path %r does not exist." % icon_exe_path) try: file_version = getWindowsFileVersion() except Exception: # Catch all the things, don't want any interface, pylint: disable=broad-except Tracing.options_logger.sysexit( "Error, file version must be a tuple of up to 4 integer values.") try: product_version = getWindowsProductVersion() except Exception: # Catch all the things, don't want any interface, pylint: disable=broad-except Tracing.options_logger.sysexit( "Error, product version must be a tuple of up to 4 integer values." ) if getWindowsCompanyName() == "": Tracing.options_logger.sysexit( """Error, empty string is not an acceptable company name.""") if getWindowsProductName() == "": Tracing.options_logger.sysexit( """Error, empty string is not an acceptable product name.""") splash_screen_filename = getWindowsSplashScreen() if splash_screen_filename is not None: if not os.path.isfile(splash_screen_filename): Tracing.options_logger.sysexit( "Error, specified splash screen image '%s' does not exist." % splash_screen_filename) if file_version or product_version or getWindowsVersionInfoStrings(): if not (file_version or product_version) and getWindowsCompanyName(): Tracing.options_logger.sysexit( "Error, company name and file or product version need to be given when any version information is given." ) if isOnefileMode() and not hasOnefileSupportedOS(): Tracing.options_logger.sysexit("Error, unsupported OS for onefile %r" % getOS()) if options.follow_none and options.follow_all: Tracing.options_logger.sysexit( "Conflicting options '--follow-imports' and '--nofollow-imports' given." ) for module_pattern in getShallIncludePackageData(): if (module_pattern.startswith("-") or "/" in module_pattern or "\\" in module_pattern): Tracing.options_logger.sysexit( "Error, '--include-package-data' needs module name or pattern as an argument, not %r." % module_pattern) for module_pattern in getShallFollowModules(): if (module_pattern.startswith("-") or "/" in module_pattern or "\\" in module_pattern): Tracing.options_logger.sysexit( "Error, '--follow-import-to' options needs module name or pattern as an argument, not %r." % module_pattern) for module_pattern in getShallFollowInNoCase(): if (module_pattern.startswith("-") or "/" in module_pattern or "\\" in module_pattern): Tracing.options_logger.sysexit( "Error, '--nofollow-import-to' options needs module name or pattern as an argument, not %r." % module_pattern) for data_file in options.data_files: if "=" not in data_file: Tracing.options_logger.sysexit( "Error, malformed data file description, must specify relative target path separated with '='." ) if data_file.count("=") == 1: src, dst = data_file.split("=", 1) filenames = resolveShellPatternToFilenames(src) if len(filenames) > 1 and not dst.endswith(("/", os.path.sep)): Tracing.options_logger.sysexit( "Error, pattern '%s' matches more than one file, but target has no trailing slash, not a directory." % src) else: src, dst, pattern = data_file.split("=", 2) filenames = resolveShellPatternToFilenames( os.path.join(src, pattern)) if not filenames: Tracing.options_logger.sysexit( "Error, '%s' does not match any files." % src) if os.path.isabs(dst): Tracing.options_logger.sysexit( "Error, must specify relative target path for data file, not absolute path '%s'." % data_file) for data_dir in options.data_dirs: if "=" not in data_dir: Tracing.options_logger.sysexit( "Error, malformed data dir description, must specify relative target path with '=' separating it." ) src, dst = data_dir.split("=", 1) if os.path.isabs(dst): Tracing.options_logger.sysexit( "Error, must specify relative target path for data dir, not %r as in %r." % (dst, data_dir)) if not os.path.isdir(src): Tracing.options_logger.sysexit( "Error, must specify existing source data directory, not %r as in %r." % (dst, data_dir)) for pattern in getShallFollowExtraFilePatterns(): if os.path.isdir(pattern): Tracing.options_logger.sysexit( "Error, pattern %r given to '--include-plugin-files' cannot be a directory name." % pattern) if options.static_libpython == "yes" and getSystemStaticLibPythonPath( ) is None: Tracing.options_logger.sysexit( "Error, static libpython is not found or not supported for this Python installation." ) if shallUseStaticLibPython() and getSystemStaticLibPythonPath() is None: Tracing.options_logger.sysexit( """Error, usable static libpython is not found for this Python installation. You \ might be missing required packages. Disable with --static-libpython=no" if you don't \ want to install it.""") if isApplePython(): if isStandaloneMode(): Tracing.options_logger.sysexit( "Error, for standalone mode, Apple Python from macOS is not supported, use e.g. CPython instead." ) if str is bytes: Tracing.options_logger.sysexit( "Error, Apple Python 2.7 from macOS is not usable as per Apple decision, use e.g. CPython 2.7 instead." ) if isStandaloneMode() and isLinux( ) and getExecutablePath("patchelf") is None: Tracing.options_logger.sysexit( "Error, standalone mode on Linux requires 'patchelf' to be installed. Use 'apt/dnf/yum install patchelf' first." ) pgo_executable = getPgoExecutable() if pgo_executable and not isPathExecutable(pgo_executable): Tracing.options_logger.sysexit( "Error, path '%s' to binary to use for PGO is not executable." % pgo_executable)
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" nuitka_app_dir = getAppDir() nuitka_depends_dir = os.path.join(nuitka_app_dir, Utils.getArchitecture()) nuitka_depends_zip = os.path.join(nuitka_depends_dir, os.path.basename(depends_url)) depends_exe = os.path.join(nuitka_depends_dir, "depends.exe") makePath(nuitka_depends_dir) if not os.path.isfile(nuitka_depends_zip) and not os.path.isfile( depends_exe): if assumeYesForDownloads(): reply = "y" else: 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 "%s". No installer needed, cached, one time question. Proceed and download? [Yes]/No """ % (nuitka_app_dir)) Tracing.flushStdout() reply = raw_input() if reply.lower() in ("no", "n"): sys.exit( "Nuitka does not work in --standalone on Windows without.") info("Downloading '%s'" % depends_url) try: urlretrieve(depends_url, nuitka_depends_zip) except Exception: # Any kind of error, pylint: disable=broad-except sys.exit("""Failed to download '%s'.\ Contents should manually be extracted to '%s'.""" % (depends_url, nuitka_depends_dir)) if not os.path.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=broad-except info("Problem with the downloaded zip file, deleting it.") deleteFile(depends_exe, must_exist=False) deleteFile(nuitka_depends_zip, must_exist=True) sys.exit("Error, need '%s' as extracted from '%s'." % (depends_exe, depends_url)) assert os.path.isfile(depends_exe) return depends_exe
def _detectImports(command, is_late): # This is pretty complicated stuff, with variants to deal with. # pylint: disable=R0912 # Print statements for stuff to show, the modules loaded. if Utils.python_version >= 300: command += '\nimport sys\nprint("\\n".join(sorted("import " + module.__name__ + " # sourcefile " + ' \ 'module.__file__ for module in sys.modules.values() if hasattr(module, "__file__") and ' \ 'module.__file__ != "<frozen>")), file = sys.stderr)' # do not read it # Make sure the right import path (the one Nuitka binary is running with) # is used. command = ("import sys; sys.path = %s;" % repr(sys.path)) + command import tempfile tmp_file, tmp_filename = tempfile.mkstemp() try: if Utils.python_version >= 300: command = command.encode('ascii') os.write(tmp_file, command) os.close(tmp_file) process = subprocess.Popen( args=[sys.executable, "-s", "-S", "-v", tmp_filename], stdout=subprocess.PIPE, stderr=subprocess.PIPE, ) _stdout, stderr = process.communicate() finally: os.unlink(tmp_filename) # Don't let errors here go unnoticed. if process.returncode != 0: warning("There is a problem with detecting imports, CPython said:") for line in stderr.split(b"\n"): Tracing.printLine(line) sys.exit("Error, please report the issue with above output.") result = [] debug("Detecting imports:") for line in stderr.replace(b"\r", b"").split(b"\n"): if line.startswith(b"import "): # print(line) parts = line.split(b" # ", 2) module_name = parts[0].split(b" ", 2)[1] origin = parts[1].split()[0] if Utils.python_version >= 300: module_name = module_name.decode("utf-8") if origin == b"precompiled": # This is a ".pyc" file that was imported, even before we have a # chance to do anything, we need to preserve it. filename = parts[1][len(b"precompiled from "):] _detectedPrecompiledFile(filename=filename, module_name=module_name, result=result, is_late=is_late) elif origin == b"sourcefile": filename = parts[1][len(b"sourcefile "):] if filename.endswith(b".py"): _detectedSourceFile(filename=filename, module_name=module_name, result=result, is_late=is_late) elif not filename.endswith(b"<frozen>"): _detectedShlibFile(filename=filename, module_name=module_name) elif origin == b"dynamically": # Shared library in early load, happens on RPM based systems and # or self compiled Python installations. filename = parts[1][len(b"dynamically loaded from "):] _detectedShlibFile(filename=filename, module_name=module_name) return result
def runScons(options, quiet): # For the scons file to find the static C++ files and include path. The # scons file is unable to use __file__ for the task. os.environ["NUITKA_SCONS"] = getSconsDataPath() if Utils.getOS() == "Windows": # On Windows this Scons variable must be set by us. os.environ["SCONS_LIB_DIR"] = Utils.joinpath( getSconsInlinePath(), "lib", "scons-2.3.2" ) scons_command = getSconsBinaryCall() if quiet: scons_command.append("--quiet") scons_command += [ # The scons file "-f", Utils.joinpath(getSconsDataPath(), "SingleExe.scons"), # Parallel compilation. "--jobs", str(Options.getJobLimit()), # Do not warn about deprecation from Scons "--warn=no-deprecated", # Don't load "site_scons" at all. "--no-site-dir", ] if Options.isShowScons(): scons_command.append("--debug=explain") # Option values to provide to scons. Find these in the caller. for key, value in options.items(): scons_command += [key + '=' + value] if Options.isShowScons(): Tracing.printLine("Scons command:", ' '.join(scons_command)) # Remove environment variables that can only harm if we have to switch # major Python versions, these cannot help Python2 to execute scons, this # is a bit of noise, but helpful, pylint: disable=R0912 if Utils.python_version >= 300: if "PYTHONPATH" in os.environ: old_pythonpath = os.environ["PYTHONPATH"] del os.environ["PYTHONPATH"] else: old_pythonpath = None if "PYTHONHOME" in os.environ: old_pythonhome = os.environ["PYTHONHOME"] del os.environ["PYTHONHOME"] else: old_pythonhome = None result = 0 == subprocess.call(scons_command, shell = False) if Utils.python_version >= 300: if old_pythonpath is not None: os.environ["PYTHONPATH"] = old_pythonpath if old_pythonhome is not None: os.environ["PYTHONHOME"] = old_pythonhome return result
def _detectImports(command, is_late): # This is pretty complicated stuff, with variants to deal with. # pylint: disable=R0912,R0914 # Print statements for stuff to show, the modules loaded. if Utils.python_version >= 300: command += '\nimport sys\nprint("\\n".join(sorted("import " + module.__name__ + " # sourcefile " + ' \ 'module.__file__ for module in sys.modules.values() if hasattr(module, "__file__") and ' \ 'module.__file__ != "<frozen>")), file = sys.stderr)' # do not read it reduced_path = [ path_element for path_element in sys.path if not Utils.areSamePaths( path_element, '.' ) if not Utils.areSamePaths( path_element, Utils.dirname(sys.modules["__main__"].__file__) ) ] # Make sure the right import path (the one Nuitka binary is running with) # is used. command = ("import sys; sys.path = %s;" % repr(reduced_path)) + command import tempfile tmp_file, tmp_filename = tempfile.mkstemp() try: if Utils.python_version >= 300: command = command.encode("ascii") os.write(tmp_file, command) os.close(tmp_file) process = subprocess.Popen( args = [sys.executable, "-s", "-S", "-v", tmp_filename], stdout = subprocess.PIPE, stderr = subprocess.PIPE, ) _stdout, stderr = process.communicate() finally: os.unlink(tmp_filename) # Don't let errors here go unnoticed. if process.returncode != 0: warning("There is a problem with detecting imports, CPython said:") for line in stderr.split(b"\n"): Tracing.printLine(line) sys.exit("Error, please report the issue with above output.") result = [] debug("Detecting imports:") for line in stderr.replace(b"\r", b"").split(b"\n"): if line.startswith(b"import "): # print(line) parts = line.split(b" # ", 2) module_name = parts[0].split(b" ", 2)[1] origin = parts[1].split()[0] if Utils.python_version >= 300: module_name = module_name.decode("utf-8") if origin == b"precompiled": # This is a ".pyc" file that was imported, even before we have a # chance to do anything, we need to preserve it. filename = parts[1][len(b"precompiled from "):] _detectedPrecompiledFile( filename = filename, module_name = module_name, result = result, is_late = is_late ) elif origin == b"sourcefile": filename = parts[1][len(b"sourcefile "):] if filename.endswith(b".py"): _detectedSourceFile( filename = filename, module_name = module_name, result = result, is_late = is_late ) elif not filename.endswith(b"<frozen>"): _detectedShlibFile( filename = filename, module_name = module_name ) elif origin == b"dynamically": # Shared library in early load, happens on RPM based systems and # or self compiled Python installations. filename = parts[1][len(b"dynamically loaded from "):] _detectedShlibFile( filename = filename, module_name = module_name ) return result
def dumpTraces(self): Tracing.printSeparator() self.parent.dumpTraces() Tracing.printSeparator()
def _detectImports(command, is_late): # print(command) # Print statements for stuff to show, the modules loaded. if Utils.python_version >= 300: command += '\nimport sys\nprint("\\n".join(sorted("import " + module.__name__ + " # sourcefile " + ' \ 'module.__file__ for module in sys.modules.values() if hasattr(module, "__file__") and ' \ 'module.__file__ != "<frozen>")), file = sys.stderr)' # do not read it, pylint: disable=C0301 import tempfile with tempfile.NamedTemporaryFile(delete=False) as tmp: if Utils.python_version >= 300: command = command.encode('ascii') tmp.write(command) tmp.flush() process = subprocess.Popen( args=[sys.executable, "-s", "-S", "-v", tmp.name], stdout=subprocess.PIPE, stderr=subprocess.PIPE, ) _stdout, stderr = process.communicate() # Don't let errors here go unnoticed. if process.returncode != 0: warning("There is a problem with detecting imports, CPython said:") for line in stderr.split(b"\n"): Tracing.printLine(line) sys.exit("Error, please report the issue with above output.") result = [] debug("Detecting imports:") # bug of PyLint, pylint: disable=E1103 for line in stderr.replace(b"\r", b"").split(b"\n"): if line.startswith(b"import "): # print(line) parts = line.split(b" # ", 2) module_name = parts[0].split(b" ", 2)[1] origin = parts[1].split()[0] if Utils.python_version >= 300: module_name = module_name.decode("utf-8") if origin == b"precompiled": # This is a ".pyc" file that was imported, even before we have a # chance to do anything, we need to preserve it. filename = parts[1][len(b"precompiled from "):] _detectedPrecompiledFile(filename=filename, module_name=module_name, result=result, is_late=is_late) elif origin == b"sourcefile": filename = parts[1][len(b"sourcefile "):] if filename.endswith(b".py"): _detectedSourceFile(filename=filename, module_name=module_name, result=result, is_late=is_late) elif not filename.endswith(b"<frozen>"): _detectedShlibFile(filename=filename, module_name=module_name) elif origin == b"dynamically": # Shared library in early load, happens on RPM based systems and # or self compiled Python installations. filename = parts[1][len(b"dynamically loaded from "):] _detectedShlibFile(filename=filename, module_name=module_name) 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 = os.path.join(os.environ["APPDATA"], "nuitka") if not os.path.isdir(nuitka_app_dir): makePath(nuitka_app_dir) nuitka_depends_zip = os.path.join(nuitka_app_dir, os.path.basename(depends_url)) if not os.path.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 = os.path.join(nuitka_app_dir, Utils.getArchitecture()) if not os.path.isdir(nuitka_depends_dir): os.makedirs(nuitka_depends_dir) depends_exe = os.path.join(nuitka_depends_dir, "depends.exe") if not os.path.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.") deleteFile(depends_exe, must_exist=False) deleteFile(nuitka_depends_zip, must_exist=True) sys.exit("Error, need '%s' as extracted from '%s'." % (depends_exe, depends_url)) assert os.path.isfile(depends_exe) return depends_exe
def dump(node): Tracing.printLine( ast.dump( node ) )
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" nuitka_app_dir = getAppDir() nuitka_depends_dir = os.path.join(nuitka_app_dir, Utils.getArchitecture()) nuitka_depends_zip = os.path.join(nuitka_depends_dir, os.path.basename(depends_url)) depends_exe = os.path.join(nuitka_depends_dir, "depends.exe") makePath(nuitka_depends_dir) if not os.path.isfile(nuitka_depends_zip) and not os.path.isfile(depends_exe): if assumeYesForDownloads(): reply = "y" else: 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 "%s". No installer needed, cached, one time question. Proceed and download? [Yes]/No """ % (nuitka_app_dir) ) Tracing.flushStdout() reply = raw_input() if reply.lower() in ("no", "n"): sys.exit("Nuitka does not work in --standalone on Windows without.") info("Downloading '%s'" % depends_url) try: urlretrieve(depends_url, nuitka_depends_zip) except Exception: # Any kind of error, pylint: disable=broad-except sys.exit( """Failed to download '%s'.\ Contents should manually be extracted to '%s'.""" % (depends_url, nuitka_depends_dir) ) if not os.path.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.") deleteFile(depends_exe, must_exist=False) deleteFile(nuitka_depends_zip, must_exist=True) sys.exit( "Error, need '%s' as extracted from '%s'." % (depends_exe, depends_url) ) assert os.path.isfile(depends_exe) return depends_exe
def dump(node): Tracing.printLine(ast.dump(node))