Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 


Quelle  util.configure   Sprache: unbekannt

 
Spracherkennung für: .configure vermutete Sprache: Unknown {[0] [0] [0]} [Methode: Schwerpunktbildung, einfache Gewichte, sechs Dimensionen]

# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*-
# vim: set filetype=python:
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.


@imports("sys")
def die(*args):
    "Print an error and terminate configure."
    log.error(*args)
    sys.exit(1)


@imports(_from="mozbuild.configure", _import="ConfigureError")
def configure_error(message):
    """Raise a programming error and terminate configure.
    Primarily for use in moz.configure templates to sanity check
    their inputs from moz.configure usage."""
    raise ConfigureError(message)


# A wrapper to obtain a process' output and return code.
# Returns a tuple (retcode, stdout, stderr).
@imports("os")
@imports("subprocess")
@imports(_from="mozbuild.shellutil", _import="quote")
@imports(_from="mozbuild.util", _import="system_encoding")
def get_cmd_output(*args, **kwargs):
    log.debug("Executing: `%s`", quote(*args))
    proc = subprocess.Popen(
        args,
        stdout=subprocess.PIPE,
        stderr=subprocess.PIPE,
        # On Python 2 on Windows, close_fds prevents the process from inheriting
        # stdout/stderr. Elsewhere, it simply prevents it from inheriting extra
        # file descriptors, which is what we want.
        close_fds=os.name != "nt",
        encoding=system_encoding,
        errors="replace",
        **kwargs,
    )
    stdout, stderr = proc.communicate()
    return proc.wait(), stdout, stderr


# A wrapper to obtain a process' output that returns the output generated
# by running the given command if it exits normally, and streams that
# output to log.debug and calls die or the given error callback if it
# does not.
@imports(_from="mozbuild.configure.util", _import="LineIO")
@imports(_from="mozbuild.shellutil", _import="quote")
def check_cmd_output(*args, **kwargs):
    onerror = kwargs.pop("onerror", None)

    with log.queue_debug():
        retcode, stdout, stderr = get_cmd_output(*args, **kwargs)
        if retcode == 0:
            with LineIO(lambda l: log.debug("| %s", l)) as o:
                o.write(stderr)
            return stdout

        log.debug("The command returned non-zero exit status %d.", retcode)
        for out, desc in ((stdout, "output"), (stderr, "error output")):
            if out:
                log.debug("Its %s was:", desc)
                with LineIO(lambda l: log.debug("| %s", l)) as o:
                    o.write(out)
        if onerror:
            return onerror()
        die("Command `%s` failed with exit status %d." % (quote(*args), retcode))


@imports("os")
def is_absolute_or_relative(path):
    if os.altsep and os.altsep in path:
        return True
    return os.sep in path


@imports(_import="mozpack.path", _as="mozpath")
def normsep(path):
    return mozpath.normsep(path)


@imports("ctypes")
@imports(_from="ctypes", _import="wintypes")
@imports(_from="mozbuild.configure.constants", _import="WindowsBinaryType")
def windows_binary_type(path):
    """Obtain the type of a binary on Windows.

    Returns WindowsBinaryType constant.
    """
    GetBinaryTypeW = ctypes.windll.kernel32.GetBinaryTypeW
    GetBinaryTypeW.argtypes = [wintypes.LPWSTR, ctypes.POINTER(wintypes.DWORD)]
    GetBinaryTypeW.restype = wintypes.BOOL

    bin_type = wintypes.DWORD()
    res = GetBinaryTypeW(path, ctypes.byref(bin_type))
    if not res:
        die("could not obtain binary type of %s" % path)

    if bin_type.value == 0:
        return WindowsBinaryType("win32")
    elif bin_type.value == 6:
        return WindowsBinaryType("win64")
    # If we see another binary type, something is likely horribly wrong.
    else:
        die("unsupported binary type on %s: %s" % (path, bin_type))


@imports("ctypes")
@imports(_from="ctypes", _import="wintypes")
def get_GetShortPathNameW():
    GetShortPathNameW = ctypes.windll.kernel32.GetShortPathNameW
    GetShortPathNameW.argtypes = [wintypes.LPCWSTR, wintypes.LPWSTR, wintypes.DWORD]
    GetShortPathNameW.restype = wintypes.DWORD
    return GetShortPathNameW


@template
@imports("ctypes")
@imports("platform")
@imports(_from="mozbuild.shellutil", _import="quote")
def normalize_path():
    # Until the build system can properly handle programs that need quoting,
    # transform those paths into their short version on Windows (e.g.
    # c:\PROGRA~1...).
    if platform.system() == "Windows":
        GetShortPathNameW = get_GetShortPathNameW()

        def normalize_path(path):
            path = normsep(path)
            if quote(path) == path:
                return path
            size = 0
            while True:
                out = ctypes.create_unicode_buffer(size)
                needed = GetShortPathNameW(path, out, size)
                if size >= needed:
                    if " " in out.value:
                        die(
                            "GetShortPathName returned a long path name: `%s`. "
                            "Use `fsutil file setshortname' "
                            "to create a short name "
                            "for any components of this path "
                            "that have spaces.",
                            out.value,
                        )
                    return normsep(out.value)
                size = needed

    else:

        def normalize_path(path):
            return normsep(path)

    return normalize_path


normalize_path = normalize_path()


@template
@imports(_from="tempfile", _import="mkstemp")
@imports("os")
@imports(_from="contextlib", _import="contextmanager")
@imports(_from="__builtin__", _import="FileNotFoundError")
def make_create_temporary_file():
    @contextmanager
    def create_temporary_file(suffix):
        fd, path = mkstemp(prefix="conftest", suffix=suffix)
        os.close(fd)
        yield path
        try:
            os.remove(path)
        except FileNotFoundError:
            pass

    return create_temporary_file


create_temporary_file = make_create_temporary_file()


# Locates the given program using which, or returns the given path if it
# exists.
# The `paths` parameter may be passed to search the given paths instead of
# $PATH.
@imports("sys")
@imports(_from="os", _import="pathsep")
@imports(_from="os", _import="environ")
@imports(_from="mozfile", _import="which")
def find_program(file, paths=None, allow_spaces=False):
    def which_normalize(file, path, exts):
        path = which(file, path=path, exts=exts)
        if not path:
            return None
        if not allow_spaces:
            return normalize_path(path)
        return normsep(path)

    # The following snippet comes from `which` itself, with a slight
    # modification to use lowercase extensions, because it's confusing rustup
    # (on top of making results not really appealing to the eye).

    # Windows has the concept of a list of extensions (PATHEXT env var).
    if sys.platform.startswith("win"):
        exts = [e.lower() for e in environ.get("PATHEXT", "").split(pathsep)]
        # If '.exe' is not in exts then obviously this is Win9x and
        # or a bogus PATHEXT, then use a reasonable default.
        if ".exe" not in exts:
            exts = [".com", ".exe", ".bat"]
    else:
        exts = None

    if is_absolute_or_relative(file):
        return which_normalize(
            os.path.basename(file), path=os.path.dirname(file), exts=exts
        )

    if paths:
        if not isinstance(paths, (list, tuple)):
            die(
                "Paths provided to find_program must be a list of strings, " "not %r",
                paths,
            )
        paths = pathsep.join(paths)

    return which_normalize(file, path=paths, exts=exts)


@imports("os")
@imports(_from="mozbuild.configure.util", _import="LineIO")
@imports(_from="__builtin__", _import="open")
@imports(_import="subprocess")
def try_invoke_compiler(
    configure_cache, compiler, language, source, flags=None, onerror=None, wrapper=[]
):
    compiler_path = compiler[0]
    compiler = wrapper + compiler
    use_cache = configure_cache is not None

    if use_cache and compiler_path not in configure_cache.version_checked_compilers:
        try:
            version_info = subprocess.check_output(
                [compiler_path, "--version"],
                encoding="UTF-8",
            ).strip()
        except subprocess.CalledProcessError:
            # There's no sane way to use the cache without the version details, so
            # we need to avoid both reads from and writes to the cache.
            use_cache = False
            pass

        if use_cache:
            if version_info != configure_cache.setdefault(compiler_path, {}).get(
                "version"
            ):
                configure_cache[compiler_path].clear()

            configure_cache[compiler_path]["version"] = version_info
            configure_cache.version_checked_compilers.add(compiler_path)

    flags = flags or []

    if use_cache:
        key = " ".join(compiler) + language + source + (" ".join(flags) or "")

        if key in configure_cache[compiler_path]:
            return configure_cache[compiler_path][key]

    if not isinstance(flags, (list, tuple)):
        die("Flags provided to try_compile must be a list of strings, " "not %r", flags)

    suffix = {
        "C": ".c",
        "C++": ".cpp",
    }[language]

    with create_temporary_file(suffix=suffix) as path:
        bsource = source.encode("ascii", "replace")

        log.debug("Creating `%s` with content:", path)
        with LineIO(lambda l: log.debug("| %s", l)) as out:
            out.write(bsource)

        with open(path, "w") as fd:
            fd.write(source)

        cmd = compiler + [path] + list(flags)
        kwargs = {"onerror": onerror}
        val = check_cmd_output(*cmd, **kwargs)
        if use_cache:
            configure_cache[compiler_path][key] = val
        return val


def unique_list(l):
    result = []
    for i in l:
        if l not in result:
            result.append(i)
    return result


# Get values out of the Windows registry. This function can only be called on
# Windows.
# The `pattern` argument is a string starting with HKEY_ and giving the full
# "path" of the registry key to get the value for, with backslash separators.
# The string can contains wildcards ('*').
# The result of this functions is an enumerator yielding tuples for each
# match. Each of these tuples contains the key name matching wildcards
# followed by the value.
#
# The `get_32_and_64_bit` argument is a boolean, if True then it will return the
# values from the 32-bit and 64-bit registry views. This defaults to False,
# which will return the view depending on the bitness of python.
#
# Examples:
#   get_registry_values(r'HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\'
#                       r'Windows Kits\Installed Roots\KitsRoot*')
#   yields e.g.:
#     ('KitsRoot81', r'C:\Program Files (x86)\Windows Kits\8.1\')
#     ('KitsRoot10', r'C:\Program Files (x86)\Windows Kits\10\')
#
#   get_registry_values(r'HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\'
#                       r'Windows Kits\Installed Roots\KitsRoot8.1')
#   yields e.g.:
#     (r'C:\Program Files (x86)\Windows Kits\8.1\',)
#
#   get_registry_values(r'HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\'
#                       r'Windows Kits\Installed Roots\KitsRoot8.1',
#                       get_32_and_64_bit=True)
#   yields e.g.:
#     (r'C:\Program Files (x86)\Windows Kits\8.1\',)
#     (r'C:\Program Files\Windows Kits\8.1\',)
#
#   get_registry_values(r'HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\'
#                       r'Windows Kits\*\KitsRoot*')
#   yields e.g.:
#     ('Installed Roots', 'KitsRoot81',
#      r'C:\Program Files (x86)\Windows Kits\8.1\')
#     ('Installed Roots', 'KitsRoot10',
#      r'C:\Program Files (x86)\Windows Kits\10\')
#
#   get_registry_values(r'HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\'
#                       r'VisualStudio\VC\*\x86\*\Compiler')
#   yields e.g.:
#     ('19.0', 'arm', r'C:\...\amd64_arm\cl.exe')
#     ('19.0', 'x64', r'C:\...\amd64\cl.exe')
#     ('19.0', 'x86', r'C:\...\amd64_x86\cl.exe')
@imports(_import="winreg")
@imports(_from="__builtin__", _import="WindowsError")
@imports(_from="fnmatch", _import="fnmatch")
def get_registry_values(pattern, get_32_and_64_bit=False):
    def enum_helper(func, key):
        i = 0
        while True:
            try:
                yield func(key, i)
            except WindowsError:
                break
            i += 1

    def get_keys(key, pattern, access_mask):
        try:
            s = winreg.OpenKey(key, "\\".join(pattern[:-1]), 0, access_mask)
        except WindowsError:
            return
        for k in enum_helper(winreg.EnumKey, s):
            if fnmatch(k, pattern[-1]):
                try:
                    yield k, winreg.OpenKey(s, k, 0, access_mask)
                except WindowsError:
                    pass

    def get_values(key, pattern, access_mask):
        try:
            s = winreg.OpenKey(key, "\\".join(pattern[:-1]), 0, access_mask)
        except WindowsError:
            return
        for k, v, t in enum_helper(winreg.EnumValue, s):
            if fnmatch(k, pattern[-1]):
                yield k, v

    def split_pattern(pattern):
        subpattern = []
        for p in pattern:
            subpattern.append(p)
            if "*" in p:
                yield subpattern
                subpattern = []
        if subpattern:
            yield subpattern

    def get_all_values(keys, pattern, access_mask):
        for i, p in enumerate(pattern):
            next_keys = []
            for base_key in keys:
                matches = base_key[:-1]
                base_key = base_key[-1]
                if i == len(pattern) - 1:
                    want_name = "*" in p[-1]
                    for name, value in get_values(base_key, p, access_mask):
                        yield matches + ((name, value) if want_name else (value,))
                else:
                    for name, k in get_keys(base_key, p, access_mask):
                        next_keys.append(matches + (name, k))
            keys = next_keys

    pattern = pattern.split("\\")
    assert pattern[0].startswith("HKEY_")
    keys = [(getattr(winreg, pattern[0]),)]
    pattern = list(split_pattern(pattern[1:]))
    if get_32_and_64_bit:
        for match in get_all_values(
            keys, pattern, winreg.KEY_READ | winreg.KEY_WOW64_32KEY
        ):
            yield match
        for match in get_all_values(
            keys, pattern, winreg.KEY_READ | winreg.KEY_WOW64_64KEY
        ):
            yield match
    else:
        for match in get_all_values(keys, pattern, winreg.KEY_READ):
            yield match


@imports(_from="mozbuild.configure.util", _import="Version", _as="_Version")
def Version(v):
    "A version number that can be compared usefully."
    return _Version(v)


# Denotes a deprecated option. Combines option() and @depends:
# @deprecated_option('--option')
# def option(value):
#     ...
# @deprecated_option() takes the same arguments as option(), except `help`.
# The function may handle the option like a typical @depends function would,
# but it is recommended it emits a deprecation error message suggesting an
# alternative option to use if there is one.
@template
def deprecated_option(*args, **kwargs):
    assert "help" not in kwargs
    kwargs["help"] = "Deprecated"
    opt = option(*args, **kwargs)
    kwargs = {k: v for k, v in kwargs.items() if k == "when"}

    def decorator(func):
        @depends(opt.option, **kwargs)
        def deprecated(value):
            if value.origin != "default":
                return func(value)

        return deprecated

    return decorator


# Turn an object into an object that can be used as an argument to @depends.
# The given object can be a literal value, a function that takes no argument,
# or, for convenience, a @depends function.
@template
@imports(_from="mozbuild.configure", _import="SandboxDependsFunction")
def dependable(obj):
    if isinstance(obj, SandboxDependsFunction):
        return obj
    return depends(when=True)(obj)


always = dependable(True)
never = dependable(False)


# Create a decorator that will only execute the body of a function
# if the passed function returns True when passed all positional
# arguments.
@template
def depends_tmpl(eval_args_fn, *args, **kwargs):
    if kwargs:
        assert len(kwargs) == 1
        when = kwargs["when"]
    else:
        when = None

    def decorator(func):
        @depends(*args, when=when)
        def wrapper(*args):
            if eval_args_fn(args):
                return func(*args)

        return wrapper

    return decorator


# Like @depends, but the decorated function is only called if one of the
# arguments it would be called with has a positive value (bool(value) is True)
@template
def depends_if(*args, **kwargs):
    return depends_tmpl(any, *args, **kwargs)


# Like @depends, but the decorated function is only called if all of the
# arguments it would be called with have a positive value.
@template
def depends_all(*args, **kwargs):
    return depends_tmpl(all, *args, **kwargs)


# A template providing a shorthand for setting a variable. The created
# option will only be settable with imply_option.
# It is expected that a project-specific moz.configure will call imply_option
# to set a value other than the default.
# If required, the set_as_define argument will additionally cause the variable
# to be set using set_define.
@template
def project_flag(env=None, set_as_define=False, **kwargs):
    if not env:
        configure_error("A project_flag must be passed a variable name to set.")

    if kwargs.get("nargs", 0) not in (0, 1):
        configure_error("A project_flag must be passed nargs={0,1}.")

    opt = option(env=env, possible_origins=("implied",), **kwargs)

    @depends(opt.option)
    def option_implementation(value):
        if value:
            if len(value) == 1:
                return value[0]
            elif len(value):
                return value
            return bool(value)

    set_config(env, option_implementation)
    if set_as_define:
        set_define(env, option_implementation)


@template
@imports(_from="mozbuild.configure.constants", _import="RaiseErrorOnUse")
def obsolete_config(name, *, replacement):
    set_config(name, RaiseErrorOnUse(f"{name} is obsolete. Use {replacement} instead."))


# Hacks related to old-configure
# ==============================


@dependable
def old_configure_assignments():
    return []


@template
def add_old_configure_assignment(var, value, when=None):
    var = dependable(var)
    value = dependable(value)

    @depends(old_configure_assignments, var, value, when=when)
    @imports(_from="mozbuild.shellutil", _import="quote")
    def add_assignment(assignments, var, value):
        if var is None or value is None:
            return
        if value is True:
            assignments.append((var, "1"))
        elif value is False:
            assignments.append((var, ""))
        else:
            if isinstance(value, (list, tuple)):
                value = quote(*value)
            assignments.append((var, str(value)))

[ Dauer der Verarbeitung: 0.42 Sekunden  ]

                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Software

     Produkte
     Quellcodebibliothek

Aktivitäten

     Artikel über Sicherheit
     Anleitung zur Aktivierung von SSL

Muße

     Gedichte
     Musik
     Bilder

Jenseits des Üblichen ....

Besucherstatistik

Besucherstatistik

Monitoring

Montastic status badge