Ejemplo n.º 1
0
def _getPythonFlavor():
    # return driven, pylint: disable=too-many-return-statements

    if isNuitkaPython():
        return "Nuitka Python"
    elif isAnacondaPython():
        return "Anaconda Python"
    elif isWinPython():
        return "WinPython"
    elif isDebianPackagePython():
        return "Debian Python"
    elif isHomebrewPython():
        return "Homebrew Python"
    elif isApplePython():
        return "Apple Python"
    elif isPyenvPython():
        return "pyenv"
    elif isPosixWindows():
        return "MSYS2 Posix"
    elif isMSYS2MingwPython():
        return "MSYS2 MinGW"
    elif isCPythonOfficialPackage():
        return "CPython Official"
    else:
        return "Unknown"
Ejemplo n.º 2
0
def _shallUseStaticLibPython():
    # return driven, pylint: disable=too-many-return-statements

    if shallMakeModule():
        return False, "not used in module mode"

    if options.static_libpython == "auto":
        # Nuitka-Python is good to to static linking.
        if isNuitkaPython():
            return True, "Nuitka-Python is broken."

        # Debian packages with are usable if the OS is new enough
        from nuitka.utils.StaticLibraries import (
            isDebianSuitableForStaticLinking, )

        if (isDebianBasedLinux() and isDebianPackagePython()
                and isDebianSuitableForStaticLinking()
                and not isPythonDebug()):
            return True, "Nuitka on Debian-Python needs package '%s' installed." % (
                "python2-dev" if str is bytes else "python3-dev")

        if isMSYS2MingwPython():
            return True, "Nuitka on MSYS2 needs package 'python-devel' installed."

        # For Anaconda default to trying static lib python library, which
        # normally is just not available or if it is even unusable.
        if isAnacondaPython() and not isMacOS() and not isWin32Windows():
            return True, "Nuitka on Anaconda needs package 'libpython' installed."

        if isPyenvPython():
            return True, "Nuitka on pyenv should not use '--enable-shared'."

    return options.static_libpython == "yes", None
Ejemplo n.º 3
0
def _getSystemStaticLibPythonPath():
    # Return driven function with many cases, pylint: disable=too-many-branches,too-many-return-statements

    sys_prefix = getSystemPrefixPath()
    python_abi_version = python_version_str + getPythonABI()

    if isNuitkaPython():
        # Nuitka Python has this.
        if isWin32Windows():
            return os.path.join(
                sys_prefix,
                "libs",
                "python" + python_abi_version.replace(".", "") + ".lib",
            )
        else:
            return os.path.join(
                sys_prefix,
                "lib",
                "libpython" + python_abi_version + ".a",
            )

    if isWin32Windows():
        candidates = [
            # Anaconda has this.
            os.path.join(
                sys_prefix,
                "libs",
                "libpython" + python_abi_version.replace(".", "") + ".dll.a",
            ),
            # MSYS2 mingw64 Python has this.
            os.path.join(
                sys_prefix,
                "lib",
                "libpython" + python_abi_version + ".dll.a",
            ),
        ]

        for candidate in candidates:
            if os.path.exists(candidate):
                return candidate
    else:
        candidate = os.path.join(
            sys_prefix, "lib", "libpython" + python_abi_version + ".a"
        )

        if os.path.exists(candidate):
            return candidate

        # For Python2 this works. TODO: Figure out Debian and Python3.
        if (
            python_version < 0x300
            and isDebianPackagePython()
            and isDebianSuitableForStaticLinking()
        ):
            candidate = locateStaticLinkLibrary("python" + python_abi_version)
        else:
            candidate = None

        if candidate is not None and os.path.exists(candidate):
            # Also check libz, can be missing
            if not locateStaticLinkLibrary("z"):
                general.warning(
                    "Error, missing libz-dev installation needed for static lib-python."
                )

            return candidate

        # This is not necessarily only for Python3 on Debian, but maybe others as well,
        # but that's what's been tested.
        if python_version >= 0x300 and isDebianPackagePython() and isDebianBasedLinux():
            try:
                import sysconfig

                candidate = os.path.join(
                    sysconfig.get_config_var("LIBPL"),
                    "libpython" + python_abi_version + "-pic.a",
                )

                if os.path.exists(candidate):
                    return candidate

            except ImportError:
                # Cannot detect this properly for Python 2.6, but we don't care much
                # about that anyway.
                pass

    return None
Ejemplo n.º 4
0
def runSconsBackend(quiet):
    # Scons gets transported many details, that we express as variables, and
    # have checks for them, leading to many branches and statements,
    # pylint: disable=too-many-branches,too-many-statements

    asBoolStr = SconsInterface.asBoolStr

    options = {
        "result_name": OutputDirectories.getResultBasepath(onefile=False),
        "source_dir": OutputDirectories.getSourceDirectoryPath(),
        "nuitka_python": asBoolStr(isNuitkaPython()),
        "debug_mode": asBoolStr(Options.is_debug),
        "python_debug": asBoolStr(Options.isPythonDebug()),
        "module_mode": asBoolStr(Options.shallMakeModule()),
        "full_compat": asBoolStr(Options.is_fullcompat),
        "experimental": ",".join(Options.getExperimentalIndications()),
        "trace_mode": asBoolStr(Options.shallTraceExecution()),
        "python_version": python_version_str,
        "target_arch": getArchitecture(),
        "python_prefix": getDirectoryRealPath(getSystemPrefixPath()),
        "nuitka_src": SconsInterface.getSconsDataPath(),
        "module_count": "%d"
        % (
            1
            + len(ModuleRegistry.getDoneModules())
            + len(ModuleRegistry.getUncompiledNonTechnicalModules())
        ),
    }

    if Options.isLowMemory():
        options["low_memory"] = asBoolStr(True)

    if not Options.shallMakeModule():
        options["result_exe"] = OutputDirectories.getResultFullpath(onefile=False)

        main_module = ModuleRegistry.getRootTopModule()
        assert main_module.isMainModule()

        main_module_name = main_module.getFullName()
        if main_module_name != "__main__":
            options["main_module_name"] = main_module_name

    if Options.shallUseStaticLibPython():
        options["static_libpython"] = getSystemStaticLibPythonPath()

    if isDebianPackagePython():
        options["debian_python"] = asBoolStr(True)

    if isMSYS2MingwPython():
        options["msys2_mingw_python"] = asBoolStr(True)

    if isAnacondaPython():
        options["anaconda_python"] = asBoolStr(True)

    if isApplePython():
        options["apple_python"] = asBoolStr(True)

    if isPyenvPython():
        options["pyenv_python"] = asBoolStr(True)

    if Options.isStandaloneMode():
        options["standalone_mode"] = asBoolStr(True)

    if Options.isOnefileMode():
        options["onefile_mode"] = asBoolStr(True)

        if Options.isOnefileTempDirMode():
            options["onefile_temp_mode"] = asBoolStr(True)

    if Options.getForcedStdoutPath():
        options["forced_stdout_path"] = Options.getForcedStdoutPath()

    if Options.getForcedStderrPath():
        options["forced_stderr_path"] = Options.getForcedStderrPath()

    if Options.shallTreatUninstalledPython():
        options["uninstalled_python"] = asBoolStr(True)

    if ModuleRegistry.getUncompiledTechnicalModules():
        options["frozen_modules"] = str(
            len(ModuleRegistry.getUncompiledTechnicalModules())
        )

    if Options.isProfile():
        options["profile_mode"] = asBoolStr(True)

    if hasPythonFlagNoWarnings():
        options["no_python_warnings"] = asBoolStr(True)

    if hasPythonFlagNoAsserts():
        options["python_sysflag_optimize"] = asBoolStr(True)

    if python_version < 0x300 and sys.flags.py3k_warning:
        options["python_sysflag_py3k_warning"] = asBoolStr(True)

    if python_version < 0x300 and (
        sys.flags.division_warning or sys.flags.py3k_warning
    ):
        options["python_sysflag_division_warning"] = asBoolStr(True)

    if sys.flags.bytes_warning:
        options["python_sysflag_bytes_warning"] = asBoolStr(True)

    if int(os.environ.get("NUITKA_NOSITE_FLAG", Options.hasPythonFlagNoSite())):
        options["python_sysflag_no_site"] = asBoolStr(True)

    if Options.hasPythonFlagTraceImports():
        options["python_sysflag_verbose"] = asBoolStr(True)

    if Options.hasPythonFlagNoRandomization():
        options["python_sysflag_no_randomization"] = asBoolStr(True)

    if python_version < 0x300 and sys.flags.unicode:
        options["python_sysflag_unicode"] = asBoolStr(True)

    if python_version >= 0x370 and sys.flags.utf8_mode:
        options["python_sysflag_utf8"] = asBoolStr(True)

    if hasPythonFlagUnbuffered():
        options["python_sysflag_unbuffered"] = asBoolStr(True)

    abiflags = getPythonABI()
    if abiflags:
        options["abiflags"] = abiflags

    if Options.shallMakeModule():
        options["module_suffix"] = getSharedLibrarySuffix(preferred=True)

    SconsInterface.setCommonOptions(options)

    if Options.shallCreatePgoInput():
        options["pgo_mode"] = "python"

        result = SconsInterface.runScons(
            options=options, quiet=quiet, scons_filename="Backend.scons"
        )
        if not result:
            return result, options

        # Need to make it usable before executing it.
        executePostProcessing()
        _runPythonPgoBinary()

        return True, options

        # Need to restart compilation from scratch here.
    if Options.isPgoMode():
        # For C level PGO, we have a 2 pass system. TODO: Make it more global for onefile
        # and standalone mode proper support, which might need data files to be
        # there, which currently are not yet there, so it won't run.
        if Options.isPgoMode():
            options["pgo_mode"] = "generate"
            result = SconsInterface.runScons(
                options=options, quiet=quiet, scons_filename="Backend.scons"
            )

            if not result:
                return result, options

            # Need to make it usable before executing it.
            executePostProcessing()
            _runCPgoBinary()
            options["pgo_mode"] = "use"

    result = (
        SconsInterface.runScons(
            options=options, quiet=quiet, scons_filename="Backend.scons"
        ),
        options,
    )

    if options.get("pgo_mode") == "use" and _wasMsvcMode():
        _deleteMsvcPGOFiles(pgo_mode="use")

    return result