Exemple #1
0
def checkOnefileReadiness(assume_yes_for_downloads):
    if getOS() == "Linux":
        app_image_path = _getAppImageToolPath(
            for_operation=False, assume_yes_for_downloads=assume_yes_for_downloads
        )

        return app_image_path is not None
    else:
        return hasOnefileSupportedOS()
Exemple #2
0
def parseArgs():
    # singleton with many cases, pylint: disable=global-statement,too-many-branches,too-many-statements
    global is_nuitka_run, options, positional_args, extra_args, is_debug, is_nondebug, is_fullcompat

    is_nuitka_run, options, positional_args, extra_args = parseOptions(
        logger=Tracing.general)

    Tracing.is_quiet = options.quiet or int(os.environ.get(
        "NUITKA_QUIET", "0"))
    Tracing.use_progressbar = isExperimental("progress")

    if options.verbose_output:
        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

    if options.show_inclusion_output:
        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

    # Onefile implies standalone build.
    if options.is_onefile:
        options.is_standalone = 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.general.sysexit("""\
Error, conflicting options, cannot make standalone module, only executable.""")

        if getOS() == "NetBSD":
            Tracing.general.warning(
                "Standalone mode on NetBSD is not functional, due to $ORIGIN linkage not being supported."
            )

    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.general.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.general.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.scons_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.general.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.general.sysexit("Error, can only use one icon on Linux.")

    for icon_path in getIconPaths():
        if not os.path.exists(icon_path):
            Tracing.general.sysexit("Error, icon path %r does not exist." %
                                    icon_path)

        if getWindowsIconExecutablePath():
            Tracing.general.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.general.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.general.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.general.sysexit(
            "Error, product version must be a tuple of up to 4 integer values."
        )

    if file_version or product_version or getWindowsVersionInfoStrings():
        if not (file_version or product_version) and getWindowsCompanyName():
            Tracing.general.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.general.sysexit("Error, unsupported OS for onefile %r" %
                                getOS())

    if isOnefileMode() and os.name == "nt":
        if not getWindowsCompanyName() and not isWindowsOnefileTempDirMode():
            Tracing.general.sysexit(
                "Error, onefile on Windows requires company name and file or product version to be given or temp dir mode."
            )

    if options.recurse_none and options.recurse_all:
        Tracing.general.sysexit(
            "Conflicting options '--follow-imports' and '--nofollow-imports' given."
        )

    if getShallIncludePackageData() and not isStandaloneMode():
        Tracing.general.sysexit(
            "Error, package data files are only included in standalone or onefile mode."
        )

    for data_file in options.data_files:
        if "=" not in data_file:
            Tracing.general.sysexit(
                "Error, malformed data file description, must specify relative target path with =."
            )

        src, dst = data_file.split("=", 1)

        if os.path.isabs(dst):
            Tracing.general.sysexit(
                "Error, must specify relative target path for data file, not %r."
                % data_file)

        if not resolveShellPatternToFilenames(src):
            Tracing.general.sysexit("Error, %r does not match any files." %
                                    src)

    if options.data_files and not isStandaloneMode():
        Tracing.general.sysexit(
            "Error, data files are only included in standalone or onefile mode."
        )

    for pattern in getShallFollowExtraFilePatterns():
        if os.path.isdir(pattern):
            sys.exit(
                "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()
Exemple #3
0
def parseOptions():
    # There are freaking many options to honor,
    # pylint: disable=too-many-branches,too-many-statements

    parser = OptionParser()

    parser.add_option(
        "--skip-basic-tests",
        action="store_false",
        dest="basic_tests",
        default=True,
        help="""\
The basic tests, execute these to check if Nuitka is healthy.
Default is %default.""",
    )

    parser.add_option(
        "--skip-syntax-tests",
        action="store_false",
        dest="syntax_tests",
        default=True,
        help="""\
The syntax tests, execute these to check if Nuitka handles Syntax errors fine.
Default is %default.""",
    )

    parser.add_option(
        "--skip-program-tests",
        action="store_false",
        dest="program_tests",
        default=True,
        help="""\
The programs tests, execute these to check if Nuitka handles programs, e.g.
import recursions, etc. fine. Default is %default.""",
    )

    parser.add_option(
        "--skip-package-tests",
        action="store_false",
        dest="package_tests",
        default=True,
        help="""\
The packages tests, execute these to check if Nuitka handles packages, e.g.
import recursions, etc. fine. Default is %default.""",
    )

    parser.add_option(
        "--skip-plugins-tests",
        action="store_false",
        dest="plugin_tests",
        default=True,
        help="""\
The plugins tests, execute these to check if Nuitka handles its own plugin
interfaces, e.g. user plugins, etc. fine. Default is %default.""",
    )

    parser.add_option(
        "--skip-optimizations-tests",
        action="store_false",
        dest="optimization_tests",
        default=True,
        help="""\
The optimization tests, execute these to check if Nuitka does optimize certain
constructs fully away. Default is %default.""",
    )

    parser.add_option(
        "--skip-standalone-tests",
        action="store_false",
        dest="standalone_tests",
        default=getOS() != "NetBSD",
        help="""\
The standalone tests, execute these to check if Nuitka standalone mode, e.g.
not referring to outside, important 3rd library packages like PyQt fine.
Default is %default.""",
    )

    parser.add_option(
        "--skip-onefile-tests",
        action="store_false",
        dest="onefile_tests",
        default=hasOnefileSupportedOS(),
        help="""\
The onefile tests, execute these to check if Nuitka works in onefile mode, e.g.
not referring to outside, important 3rd library packages like PyQt fine.
Default is %default.""",
    )

    parser.add_option(
        "--skip-reflection-test",
        action="store_false",
        dest="reflection_test",
        default=True,
        help="""\
The reflection test compiles Nuitka with Nuitka, and then Nuitka with the
compile Nuitka and compares the outputs. Default is %default.""",
    )

    parser.add_option(
        "--skip-cpython26-tests",
        action="store_false",
        dest="cpython26",
        default=True,
        help="""\
The standard CPython2.6 test suite. Execute this for all corner cases to be
covered. With Python 2.7 this covers exception behavior quite well. Default
is %default.""",
    )

    parser.add_option(
        "--skip-cpython27-tests",
        action="store_false",
        dest="cpython27",
        default=True,
        help="""\
The standard CPython2.7 test suite. Execute this for all corner cases to be
covered. With Python 2.6 these are not run. Default is %default.""",
    )

    parser.add_option(
        "--skip-cpython32-tests",
        action="store_false",
        dest="cpython32",
        default=True,
        help="""\
The standard CPython3.2 test suite. Execute this for all corner cases to be
covered. With Python 2.6 these are not run. Default is %default.""",
    )

    parser.add_option(
        "--skip-cpython33-tests",
        action="store_false",
        dest="cpython33",
        default=True,
        help="""\
The standard CPython3.3 test suite. Execute this for all corner cases to be
covered. With Python 2.x these are not run. Default is %default.""",
    )

    parser.add_option(
        "--skip-cpython34-tests",
        action="store_false",
        dest="cpython34",
        default=True,
        help="""\
The standard CPython3.4 test suite. Execute this for all corner cases to be
covered. With Python 2.x these are not run. Default is %default.""",
    )

    parser.add_option(
        "--skip-cpython35-tests",
        action="store_false",
        dest="cpython35",
        default=True,
        help="""\
The standard CPython3.5 test suite. Execute this for all corner cases to be
covered. With Python 2.x these are not run. Default is %default.""",
    )

    parser.add_option(
        "--skip-cpython36-tests",
        action="store_false",
        dest="cpython36",
        default=True,
        help="""\
The standard CPython3.6 test suite. Execute this for all corner cases to be
covered. With Python 2.x these are not run. Default is %default.""",
    )

    parser.add_option(
        "--skip-cpython37-tests",
        action="store_false",
        dest="cpython37",
        default=True,
        help="""\
The standard CPython3.7 test suite. Execute this for all corner cases to be
covered. With Python 2.x these are not run. Default is %default.""",
    )

    parser.add_option(
        "--skip-cpython38-tests",
        action="store_false",
        dest="cpython38",
        default=True,
        help="""\
The standard CPython3.8 test suite. Execute this for all corner cases to be
covered. With Python 2.x these are not run. Default is %default.""",
    )

    parser.add_option(
        "--skip-cpython39-tests",
        action="store_false",
        dest="cpython39",
        default=True,
        help="""\
The standard CPython3.9 test suite. Execute this for all corner cases to be
covered. With Python 2.x these are not run. Default is %default.""",
    )

    parser.add_option(
        "--skip-other-cpython-tests",
        action="store_true",
        dest="cpython_no_other",
        default=False,
        help="""\
Do not execute any CPython test suite other than the one matching the running
Python. Default is %default.""",
    )

    parser.add_option(
        "--skip-all-cpython-tests",
        action="store_true",
        dest="cpython_none",
        default=False,
        help="""\
Do not execute any CPython test suite other than the one matching the running
Python. Default is %default.""",
    )

    parser.add_option(
        "--no-other-python",
        action="store_true",
        dest="no_other",
        default=False,
        help="""\
Do not use any other Python than the one running, even if available on
the system. Default is %default.""",
    )

    parser.add_option(
        "--no-python2.6",
        action="store_true",
        dest="no26",
        default=False,
        help="""\
Do not use Python2.6 even if available on the system. Default is %default.""",
    )

    parser.add_option(
        "--no-python2.7",
        action="store_true",
        dest="no27",
        default=False,
        help="""\
Do not use Python2.7 even if available on the system. Default is %default.""",
    )

    parser.add_option(
        "--no-python3.3",
        action="store_true",
        dest="no33",
        default=False,
        help="""\
Do not use Python3.3 even if available on the system. Default is %default.""",
    )

    parser.add_option(
        "--no-python3.4",
        action="store_true",
        dest="no34",
        default=False,
        help="""\
Do not use Python3.4 even if available on the system. Default is %default.""",
    )

    parser.add_option(
        "--no-python3.5",
        action="store_true",
        dest="no35",
        default=False,
        help="""\
Do not use Python3.5 even if available on the system. Default is %default.""",
    )

    parser.add_option(
        "--no-python3.6",
        action="store_true",
        dest="no36",
        default=False,
        help="""\
Do not use Python3.6 even if available on the system. Default is %default.""",
    )

    parser.add_option(
        "--no-python3.7",
        action="store_true",
        dest="no37",
        default=False,
        help="""\
Do not use Python3.7 even if available on the system. Default is %default.""",
    )

    parser.add_option(
        "--no-python3.8",
        action="store_true",
        dest="no38",
        default=False,
        help="""\
Do not use Python3.8 even if available on the system. Default is %default.""",
    )

    parser.add_option(
        "--no-python3.9",
        action="store_true",
        dest="no39",
        default=False,
        help="""\
Do not use Python3.9 even if available on the system. Default is %default.""",
    )

    parser.add_option(
        "--coverage",
        action="store_true",
        dest="coverage",
        default=False,
        help="""\
Make a coverage analysis, that does not really check. Default is %default.""",
    )

    parser.add_option(
        "--no-debug",
        action="store_false",
        dest="debug",
        default=True,
        help="""\
Make a coverage analysis, that does not really check. Default is %default.""",
    )

    parser.add_option(
        "--assume-yes-for-downloads",
        action="store_true",
        dest="assume_yes_for_downloads",
        default=False,
        help="""\
Allow Nuitka to download code if necessary, e.g. dependency walker on Windows. Default is %default.""",
    )

    parser.add_option(
        "--mingw64",
        action="store_true",
        dest="mingw64",
        default=False,
        help="""\
Enforce the use of MinGW64 on Windows. Defaults to off.""",
    )

    options, positional_args = parser.parse_args()

    if positional_args:
        parser.print_help()

        sys.exit("\nError, no positional argument allowed.")

    if options.no_other:
        if sys.version_info[0:2] != (2, 6):
            options.no26 = True
        if sys.version_info[0:2] != (2, 7):
            options.no27 = True
        if sys.version_info[0:2] != (3, 3):
            options.no33 = True
        if sys.version_info[0:2] != (3, 4):
            options.no34 = True
        if sys.version_info[0:2] != (3, 5):
            options.no35 = True
        if sys.version_info[0:2] != (3, 6):
            options.no36 = True
        if sys.version_info[0:2] != (3, 7):
            options.no37 = True
        if sys.version_info[0:2] != (3, 8):
            options.no38 = True
        if sys.version_info[0:2] != (3, 9):
            options.no39 = True

    if options.cpython_no_other:
        if sys.version_info[0:2] != (2, 6):
            options.cpython26 = False
        if sys.version_info[0:2] != (2, 7):
            options.cpython27 = False
        if sys.version_info[0:2] != (3, 2):
            options.cpython32 = False
        if sys.version_info[0:2] != (3, 3):
            options.cpython33 = False
        if sys.version_info[0:2] != (3, 4):
            options.cpython34 = False
        if sys.version_info[0:2] != (3, 5):
            options.cpython35 = False
        if sys.version_info[0:2] != (3, 6):
            options.cpython36 = False
        if sys.version_info[0:2] != (3, 7):
            options.cpython37 = False
        if sys.version_info[0:2] != (3, 8):
            options.cpython38 = False
        if sys.version_info[0:2] != (3, 9):
            options.cpython39 = False

    if options.cpython_none:
        options.cpython26 = False
        options.cpython27 = False
        options.cpython32 = False
        options.cpython33 = False
        options.cpython34 = False
        options.cpython35 = False
        options.cpython36 = False
        options.cpython37 = False
        options.cpython38 = False
        options.cpython39 = False

    if options.coverage and os.path.exists(".coverage"):
        os.unlink(".coverage")

    return options
Exemple #4
0
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)
Exemple #5
0
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()