def getPython2ExePath(): """ Find a way to call any Python2. Scons needs it.""" if python_version < 300: return sys.executable elif Utils.getOS() == "Windows": python_exe = _getPython2ExePathWindows() if python_exe is not None: return python_exe else: sys.exit("""\ Error, while Nuitka is fully Python3 compatible, it needs to find a Python2 executable under C:\\Python26 or C:\\Python27 to execute scons which is not yet Python3 compatible.""") candidate = Execution.getExecutablePath("python2.7") if candidate is None: candidate = Execution.getExecutablePath("python2.6") if candidate is None: candidate = Execution.getExecutablePath("python2") # Our weakest bet is that there is no "python3" named "python", but we # take it, as on some systems it's true. if candidate is None: candidate = "python" return candidate
def getPython2ExePath(): """ Find a way to call any Python2. Scons needs it.""" if python_version < 300: return sys.executable elif Utils.getOS() == "Windows": python_exe = _getPython2ExePathWindows() if python_exe is not None: return python_exe else: sys.exit("""\ Error, while Nuitka is fully Python3 compatible, it needs to find a Python2 executable under C:\\Python26 or C:\\Python27 to execute scons which is not yet Python3 compatible.""") candidate = Execution.getExecutablePath("python2.7") if candidate is None: candidate = Execution.getExecutablePath("python2.6") if candidate is None: candidate = Execution.getExecutablePath("python2") # Our weakest bet is that there is no "python3" named "python", but we # take it, as on some systems it's true. if candidate is None: candidate = "python" return candidate
def _getSconsBinaryCall(): """Return a way to execute Scons. Using potentially in-line copy if no system Scons is available or if we are on Windows, there it is mandatory. """ inline_path = os.path.join(_getSconsInlinePath(), "bin", "scons.py") if os.path.exists(inline_path): return [ _getPythonForSconsExePath(), "-W", "ignore", # Disable Python warnings in case of debug Python. getExternalUsePath(inline_path), ] else: scons_path = Execution.getExecutablePath("scons") if scons_path is not None: return [scons_path] else: Tracing.scons_logger.sysexit( "Error, the inline copy of scons is not present, nor a scons binary in the PATH." )
def getPylintBinaryPath(): # pylint: disable=global-statement global pylint_binary if pylint_binary is None: pylint_binary = Execution.getExecutablePath("pylint") return pylint_binary
def _wrapForDebugger(*args): gdb_path = Execution.getExecutablePath("gdb") if gdb_path is None: sys.exit("Error, no 'gdb' binary found in path.") args = (gdb_path, "gdb", "-ex=run", "-ex=where", "--args") + args return args
def _getPython2ExePath(): """ Find a way to call any Python2. Scons needs it as it doesn't support Python3. """ python_exe = Options.getPython2PathForScons() if python_exe is not None: return python_exe if python_version < 300: return sys.executable elif Utils.getOS() == "Windows": python_exe = _getPython2ExePathWindows() if python_exe is not None: return python_exe else: sys.exit("""\ Error, while Nuitka is fully Python3 compatible, it needs to find a Python2 executable under C:\\Python26 or C:\\Python27 to execute Scons utility which is used to build the C files to binary, and which is not yet Python3 compatible. You may provide it using option "--python2-for-scons=path_to_python.exe" in case it is not visible in registry, e.g. uninstalled AnaConda Python. """) candidate = Execution.getExecutablePath("python2.7") if candidate is None: candidate = Execution.getExecutablePath("python2.6") if candidate is None: candidate = Execution.getExecutablePath("python2") # Our weakest bet is that there is no "python3" named "python", but we # take it, as on some systems it's true. if candidate is None: candidate = "python" return candidate
def executeMain(binary_filename, clean_path): args = (binary_filename, binary_filename) if Options.shallRunInDebugger(): gdb_path = Execution.getExecutablePath("gdb") if gdb_path is None: sys.exit("Error, no 'gdb' binary found in path.") args = (gdb_path, "gdb", "-ex=run", "-ex=where", "--args", binary_filename) callExecPython(clean_path=clean_path, add_path=False, args=args)
def executeMain(binary_filename, clean_path): args = (binary_filename, binary_filename) if Options.shallRunInDebugger(): gdb_path = Execution.getExecutablePath("gdb") if gdb_path is None: sys.exit("Error, no 'gdb' binary found in path.") args = (gdb_path, "gdb", "-ex=run", "-ex=where", "--args", binary_filename) callExecPython(clean_path=clean_path, add_path=False, args=args)
def getSconsBinaryCall(): """ Return a way to execute Scons. Using potentially in-line copy if no system Scons is available or if we are on Windows. """ if Utils.getOS() != "Windows": scons_path = Execution.getExecutablePath("scons") if scons_path is not None: return [scons_path] return [ getPython2ExePath(), Utils.joinpath(getSconsInlinePath(), "bin", "scons.py") ]
def getSconsBinaryCall(): """ Return a way to execute Scons. Using potentially in-line copy if no system Scons is available or if we are on Windows. """ if Utils.getOS() != "Windows": scons_path = Execution.getExecutablePath("scons") if scons_path is not None: return [scons_path] return [ getPython2ExePath(), Utils.joinpath(getSconsInlinePath(), "bin", "scons.py") ]
def _getSconsBinaryCall(): """ Return a way to execute Scons. Using potentially in-line copy if no system Scons is available or if we are on Windows, there it is mandatory. """ if Utils.getOS() != "Windows": scons_path = Execution.getExecutablePath("scons") if scons_path is not None: return [scons_path] return [ _getPythonForSconsExePath(), os.path.join(_getSconsInlinePath(), "bin", "scons.py") ]
def _getSconsBinaryCall(): """ Return a way to execute Scons. Using potentially in-line copy if no system Scons is available or if we are on Windows, there it is mandatory. """ if Utils.getOS() != "Windows": scons_path = Execution.getExecutablePath("scons") if scons_path is not None: return [scons_path] return [ _getPythonForSconsExePath(), "-W", "ignore", # Disable Python warnings in case of debug Python. os.path.join(_getSconsInlinePath(), "bin", "scons.py"), ]
def _getPythonForSconsExePath(): """Find a way to call any Python that works for Scons. Scons needs it as it doesn't support all Python versions. """ python_exe = Options.getPythonPathForScons() if python_exe is not None: return python_exe if python_version < 0x300 and not Utils.isWin32Windows(): # Python 2.6 and 2.7 are fine for scons on all platforms, but not # on Windows due to clcache usage. return sys.executable elif python_version >= 0x350: # Python 3.5 or higher work on all platforms. return sys.executable elif Utils.isWin32Windows(): python_exe = _getPythonSconsExePathWindows() if python_exe is not None: return python_exe else: Tracing.scons_logger.sysexit( """\ Error, while Nuitka works with older Python, Scons does not, and therefore Nuitka needs to find a Python 3.5 or higher executable, so please install it. You may provide it using option "--python-for-scons=path_to_python.exe" in case it is not visible in registry, e.g. due to using uninstalled Anaconda Python. """ ) for version_candidate in ("2.7", "2.6", "3.5", "3.6", "3.7", "3.8", "3.9"): candidate = Execution.getExecutablePath("python" + version_candidate) if candidate is not None: return candidate # Lets be optimistic, this is most often going to be new enough or a # Python2 variant. return "python"
def _getPythonForSconsExePath(): """ Find a way to call any Python2. Scons needs it as it doesn't support Python3. """ python_exe = Options.getPythonPathForScons() if python_exe is not None: return python_exe if python_version < 300 or python_version >= 350: return sys.executable elif Utils.getOS() == "Windows": python_exe = _getPythonSconsExePathWindows() if python_exe is not None: return python_exe else: sys.exit( """\ Error, while Nuitka works with Python 3.3 and 3.4, scons does not, and Nuitka needs to find a Python executable 2.6/2.7 or 3.5 or higher. Simply under the C:\\PythonXY, e.g. C:\\Python27 to execute the scons utility which is used to build the C files to binary. You may provide it using option "--python-for-scons=path_to_python.exe" in case it is not visible in registry, e.g. due to using uninstalled AnaConda Python. """ ) for version_candidate in ("2.7", "2.6", "3.5", "3.6", "3.7", "3.8"): candidate = Execution.getExecutablePath("python" + version_candidate) if candidate is not None: return candidate # Lets be optimistic, this is most often going to be new enough or a # Python2 variant. return "python"
def _getPythonForSconsExePath(): """ Find a way to call any Python2. Scons needs it as it doesn't support Python3. """ python_exe = Options.getPythonPathForScons() if python_exe is not None: return python_exe if python_version < 300 or python_version >= 350: return sys.executable elif Utils.getOS() == "Windows": python_exe = _getPythonSconsExePathWindows() if python_exe is not None: return python_exe else: sys.exit( """\ Error, while Nuitka works with Python 3.2 to 3.4, scons does not, and Nuitka needs to find a Python executable 2.6/2.7 or 3.5 or higher. Simply under the C:\\PythonXY, e.g. C:\\Python27 to execute the scons utility which is used to build the C files to binary. You may provide it using option "--python-for-scons=path_to_python.exe" in case it is not visible in registry, e.g. due to using uninstalled AnaConda Python. """ ) for version_candidate in ("2.7", "2.6", "3.5", "3.6", "3.7"): candidate = Execution.getExecutablePath("python" + version_candidate) if candidate is not None: return candidate # Lets be optimistic, this is most often going to be new enough or a # Python2 variant. return "python"
# We support to execute with a specified version. intended_version = Options.getIntendedPythonVersion() if intended_version is None: intended_version = current_version # If it's a different version, we find it by guessing it, otherwise we use the # one previously used. if current_version != intended_version: if Utils.getOS() == "Windows": python_binary = Execution.getPythonExePathWindows( intended_version, Options.getIntendedPythonArch() ) else: python_binary = Execution.getExecutablePath("python" + intended_version) if python_binary is None: sys.exit( "Error, cannot find Python %s binary in PATH (%s)." % ( intended_version, os.environ.get("PATH", "") ) ) needs_reexec = True else: python_binary = sys.executable python_flags = Options.getPythonFlags()
def main(): # PyLint for Python3 thinks we import from ourselves if we really # import from package, pylint:disable=I0021,no-name-in-module # Also high complexity. # pylint: disable=too-many-branches,too-many-locals,too-many-statements if "NUITKA_BINARY_NAME" in os.environ: sys.argv[0] = os.environ["NUITKA_BINARY_NAME"] if "NUITKA_PYTHONPATH" in os.environ: # Restore the PYTHONPATH gained from the site module, that we chose not # to have imported. pylint: disable=eval-used sys.path = eval(os.environ["NUITKA_PYTHONPATH"]) del os.environ["NUITKA_PYTHONPATH"] else: # Remove path element added for being called via "__main__.py", this can # only lead to trouble, having e.g. a "distutils" in sys.path that comes # from "nuitka.distutils". sys.path = [ path_element for path_element in sys.path if os.path.dirname(os.path.abspath(__file__)) != path_element ] # For re-execution, we might not have done this. from nuitka import Options # isort:skip Options.parseArgs() from nuitka.utils import Utils, Execution # isort:skip import logging # isort:skip logging.basicConfig(format = "Nuitka:%(levelname)s:%(message)s") # We don't care, and these are triggered by run time calculations of "range" and # others, while on python2.7 they are disabled by default. warnings.simplefilter("ignore", DeprecationWarning) # We will run with the Python configuration as specified by the user, if it does # not match, we restart ourselves with matching configuration. needs_reexec = False current_version = "%d.%d" % (sys.version_info[0], sys.version_info[1]) # We support to execute with a specified version. intended_version = Options.getIntendedPythonVersion() if intended_version is None: intended_version = current_version # If it's a different version, we find it by guessing it, otherwise we use the # one previously used. if current_version != intended_version: if Utils.getOS() == "Windows": python_binary = Execution.getPythonExePathWindows( intended_version, Options.getIntendedPythonArch() ) else: python_binary = Execution.getExecutablePath("python" + intended_version) if python_binary is None: sys.exit( "Error, cannot find Python %s binary in PATH (%s)." % ( intended_version, os.environ.get("PATH", "") ) ) needs_reexec = True else: python_binary = sys.executable if sys.flags.no_site == 0: needs_reexec = True # The hash randomization totally changes the created source code created, # changing it every single time Nuitka is run. This kills any attempt at # caching it, and comparing generated source code. While the created binary # actually may still use it, during compilation we don't want to. So lets # disable it. if os.environ.get("PYTHONHASHSEED", "-1") != '0': needs_reexec = True # In case we need to re-execute. if needs_reexec: if not Options.isAllowedToReexecute(): sys.exit("Error, not allowed to re-execute, but that would be needed.") our_filename = sys.modules[__name__].__file__ # Workaround for --python-version which will choke on existing, but # not matching .pyc files. if current_version != intended_version: pyc_filename = our_filename[:-2] + ".pyc" if os.path.exists(pyc_filename): try: os.unlink(pyc_filename) except OSError: pass # Execute with full path as the process name, so it can find itself and its # libraries. args = [ python_binary, python_binary, "-S", our_filename, ] os.environ["NUITKA_BINARY_NAME"] = sys.modules["__main__"].__file__ if Options.is_nuitka_run: args.append("--run") # Same arguments as before. args += sys.argv[1:] + list(Options.getMainArgs()) if current_version == intended_version: os.environ["NUITKA_PYTHONPATH"] = repr( sys.path ) from nuitka.importing.PreloadedPackages import detectPreLoadedPackagePaths, detectPthImportedPackages os.environ["NUITKA_NAMESPACES"] = repr( detectPreLoadedPackagePaths() ) if "site" in sys.modules: os.environ["NUITKA_SITE_FILENAME"] = sys.modules["site"].__file__ os.environ["NUITKA_PTH_IMPORTED"] = repr(detectPthImportedPackages()) os.environ["NUITKA_SITE_FLAG"] = str(sys.flags.no_site) \ if "no_site" not in Options.getPythonFlags() \ else '1' os.environ["PYTHONHASHSEED"] = '0' Execution.callExec(args) if Options.isShowMemory(): from nuitka.utils import MemoryUsage MemoryUsage.startMemoryTracing() # Inform the user about potential issues. if current_version not in Options.getSupportedPythonVersions(): # Do not disturb run of automatic tests, detected from the presence of # that environment variable. if "PYTHON" not in os.environ: logging.warning( "The version '%s' is not currently supported. Expect problems.", current_version ) if "NUITKA_NAMESPACES" in os.environ: # Restore the detected name space packages, that were force loaded in # site.py, and will need a free pass later on. pylint: disable=eval-used from nuitka.importing.PreloadedPackages import setPreloadedPackagePaths setPreloadedPackagePaths(eval(os.environ["NUITKA_NAMESPACES"])) del os.environ["NUITKA_NAMESPACES"] if "NUITKA_PTH_IMPORTED" in os.environ: # Restore the packages that the ".pth" files asked to import. # pylint: disable=eval-used from nuitka.importing.PreloadedPackages import setPthImportedPackages setPthImportedPackages(eval(os.environ["NUITKA_PTH_IMPORTED"])) del os.environ["NUITKA_PTH_IMPORTED"] # Now the real main program of Nuitka can take over. from nuitka import MainControl # isort:skip MainControl.main() if Options.isShowMemory(): MemoryUsage.showMemoryTrace()