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


Quelle  android.py   Sprache: 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/.

import errno
import json
import os
import stat
import subprocess
import sys
import time
from pathlib import Path
from typing import Optional, Union

import requests
from tqdm import tqdm

# We need the NDK version in multiple different places, and it's inconvenient
# to pass down the NDK version to all relevant places, so we have this global
# variable.
from mozboot.bootstrap import MOZCONFIG_SUGGESTION_TEMPLATE

NDK_VERSION = "r27c"
CMDLINE_TOOLS_VERSION_STRING = "17.0"
CMDLINE_TOOLS_VERSION = "12700392"

BUNDLETOOL_VERSION = "1.17.2"

# We expect the emulator AVD definitions to be platform agnostic
LINUX_X86_64_ANDROID_AVD = "linux64-android-avd-x86_64-repack"
LINUX_ARM_ANDROID_AVD = "linux64-android-avd-arm-repack"

MACOS_X86_64_ANDROID_AVD = "linux64-android-avd-x86_64-repack"
MACOS_ARM_ANDROID_AVD = "linux64-android-avd-arm-repack"
MACOS_ARM64_ANDROID_AVD = "linux64-android-avd-arm64-repack"

WINDOWS_X86_64_ANDROID_AVD = "linux64-android-avd-x86_64-repack"
WINDOWS_ARM_ANDROID_AVD = "linux64-android-avd-arm-repack"

AVD_MANIFEST_X86_64 = Path(__file__).resolve().parent / "android-avds/x86_64.json"
AVD_MANIFEST_ARM = Path(__file__).resolve().parent / "android-avds/arm.json"
AVD_MANIFEST_ARM64 = Path(__file__).resolve().parent / "android-avds/arm64.json"

JAVA_VERSION_MAJOR = "17"
JAVA_VERSION_MINOR = "0.13"
JAVA_VERSION_PATCH = "11"

ANDROID_NDK_EXISTS = """
Looks like you have the correct version of the Android NDK installed at:
%s
"""

ANDROID_SDK_EXISTS = """
Looks like you have the Android SDK installed at:
%s
We will install all required Android packages.
"""

ANDROID_SDK_TOO_OLD = """
Looks like you have an outdated Android SDK installed at:
%s
I can't update outdated Android SDKs to have the required 'sdkmanager'
tool.  Move it out of the way (or remove it entirely) and then run
bootstrap again.
"""

INSTALLING_ANDROID_PACKAGES = """
We are now installing the following Android packages:
%s
You may be prompted to agree to the Android license. You may see some of
output as packages are downloaded and installed.
"""

MOBILE_ANDROID_MOZCONFIG_TEMPLATE = """
# Build GeckoView/Firefox for Android:
ac_add_options --enable-project=mobile/android

# Targeting the following architecture.
# For regular phones, no --target is needed.
# For x86 emulators (and x86 devices, which are uncommon):
# ac_add_options --target=i686
# For newer phones or Apple silicon
# ac_add_options --target=aarch64
# For x86_64 emulators (and x86_64 devices, which are even less common):
# ac_add_options --target=x86_64

{extra_lines}
"""

MOBILE_ANDROID_ARTIFACT_MODE_MOZCONFIG_TEMPLATE = """
# Build GeckoView/Firefox for Android Artifact Mode:
ac_add_options --enable-project=mobile/android
ac_add_options --enable-artifact-builds

{extra_lines}
# Write build artifacts to:
mk_add_options MOZ_OBJDIR=./objdir-frontend
"""


class GetNdkVersionError(Exception):
    pass


def install_mobile_android_sdk_or_ndk(url, path: Path):
    """
    Fetch an Android SDK or NDK from |url| and unpack it into the given |path|.

    We use, and 'requests' respects, https. We could also include SHAs for a
    small improvement in the integrity guarantee we give. But this script is
    bootstrapped over https anyway, so it's a really minor improvement.

    We keep a cache of the downloaded artifacts, writing into |path|/mozboot.
    We don't yet clean the cache; it's better to waste some disk space and
    not require a long re-download than to wipe the cache prematurely.
    """

    download_path = path / "mozboot"
    try:
        download_path.mkdir(parents=True)
    except OSError as e:
        if e.errno == errno.EEXIST and download_path.is_dir():
            pass
        else:
            raise

    file_name = url.split("/")[-1]
    download_file_path = download_path / file_name
    download(url, download_file_path)

    if file_name.endswith(".tar.gz"or file_name.endswith(".tgz"):
        cmd = ["tar""zxf", str(download_file_path)]
    elif file_name.endswith(".tar.bz2"):
        cmd = ["tar""jxf", str(download_file_path)]
    elif file_name.endswith(".zip"):
        cmd = ["unzip""-q", str(download_file_path)]
    elif file_name.endswith(".bin"):
        # Execute the .bin file, which unpacks the content.
        mode = os.stat(path).st_mode
        download_file_path.chmod(mode | stat.S_IXUSR)
        cmd = [str(download_file_path)]
    else:
        raise NotImplementedError(f"Don't know how to unpack file: {file_name}")

    print(f"Unpacking {download_file_path}...")

    with open(os.devnull, "w"as stdout:
        # These unpack commands produce a ton of output; ignore it.  The
        # .bin files are 7z archives; there's no command line flag to quiet
        # output, so we use this hammer.
        subprocess.check_call(cmd, stdout=stdout, cwd=str(path))

    print(f"Unpacking {download_file_path}... DONE")
    # Now delete the archive
    download_file_path.unlink()


def download(
    url,
    download_file_path: Path,
):
    with requests.Session() as session:
        request = session.head(url, allow_redirects=True)
        request.raise_for_status()
        remote_file_size = int(request.headers["content-length"])

        if download_file_path.is_file():
            local_file_size = download_file_path.stat().st_size

            if local_file_size == remote_file_size:
                print(
                    f"{download_file_path.name} already downloaded. Skipping download..."
                )
            else:
                print(f"Partial download detected. Resuming download of {url}...")
                download_internal(
                    download_file_path,
                    session,
                    url,
                    remote_file_size,
                    local_file_size,
                )
        else:
            print(f"Downloading {url}...")
            download_internal(download_file_path, session, url, remote_file_size)


def download_internal(
    download_file_path: Path,
    session,
    url,
    remote_file_size,
    resume_from_byte_pos: int = None,
):
    """
    Handles both a fresh SDK/NDK download, as well as resuming a partial one
    """
    # "ab" will behave same as "wb" if file does not exist
    with open(download_file_path, "ab"as file:
        # 64 KB/s should be fine on even the slowest internet connections
        chunk_size = 1024 * 64
        https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Range#directives
        resume_header = (
            {"Range": f"bytes={resume_from_byte_pos}-"}
            if resume_from_byte_pos
            else None
        )

        request = session.get(
            url, stream=True, allow_redirects=True, headers=resume_header
        )

        with tqdm(
            total=int(remote_file_size),
            unit="B",
            unit_scale=True,
            unit_divisor=1024,
            desc=download_file_path.name,
            initial=resume_from_byte_pos if resume_from_byte_pos else 0,
        ) as progress_bar:
            for chunk in request.iter_content(chunk_size):
                file.write(chunk)
                progress_bar.update(len(chunk))


def get_ndk_version(ndk_path: Union[str, Path]):
    """Given the path to the NDK, return the version as a 3-tuple of (major,
    minor, human).
    """
    ndk_path = Path(ndk_path)
    with open(ndk_path / "source.properties""r"as f:
        revision = [line for line in f if line.startswith("Pkg.Revision")]
        if not revision:
            raise GetNdkVersionError(
                "Cannot determine NDK version from source.properties"
            )
        if len(revision) != 1:
            raise GetNdkVersionError("Too many Pkg.Revision lines in source.properties")

        (_, version) = revision[0].split("=")
        if not version:
            raise GetNdkVersionError(
                "Unexpected Pkg.Revision line in source.properties"
            )

        (major, minor, revision) = version.strip().split(".")
        if not major or not minor:
            raise GetNdkVersionError("Unexpected NDK version string: " + version)

        # source.properties contains a $MAJOR.$MINOR.$PATCH revision number,
        # but the more common nomenclature that Google uses is alphanumeric
        # version strings like "r20" or "r19c".  Convert the source.properties
        # notation into an alphanumeric string.
        int_minor = int(minor)
        alphas = "abcdefghijklmnop"
        ascii_minor = alphas[int_minor] if int_minor > 0 else ""
        human = "r%s%s" % (major, ascii_minor)
        return (major, minor, human)


def get_paths(os_name):
    mozbuild_path = Path(
        os.environ.get("MOZBUILD_STATE_PATH", Path("~/.mozbuild").expanduser())
    )
    sdk_path = Path(
        os.environ.get("ANDROID_SDK_HOME", mozbuild_path / f"android-sdk-{os_name}"),
    )
    ndk_path = Path(
        os.environ.get(
            "ANDROID_NDK_HOME", mozbuild_path / f"android-ndk-{NDK_VERSION}"
        ),
    )
    avd_home_path = Path(
        os.environ.get("ANDROID_AVD_HOME", mozbuild_path / "android-device" / "avd")
    )
    return mozbuild_path, sdk_path, ndk_path, avd_home_path


def sdkmanager_tool(sdk_path: Path):
    # sys.platform is win32 even if Python/Win64.
    sdkmanager = "sdkmanager.bat" if sys.platform.startswith("win"else "sdkmanager"
    return (
        sdk_path / "cmdline-tools" / CMDLINE_TOOLS_VERSION_STRING / "bin" / sdkmanager
    )


def avdmanager_tool(sdk_path: Path):
    # sys.platform is win32 even if Python/Win64.
    sdkmanager = "avdmanager.bat" if sys.platform.startswith("win"else "avdmanager"
    return (
        sdk_path / "cmdline-tools" / CMDLINE_TOOLS_VERSION_STRING / "bin" / sdkmanager
    )


def adb_tool(sdk_path: Path):
    adb = "adb.bat" if sys.platform.startswith("win"else "adb"
    return sdk_path / "platform-tools" / adb


def emulator_tool(sdk_path: Path):
    emulator = "emulator.bat" if sys.platform.startswith("win"else "emulator"
    return sdk_path / "emulator" / emulator


def ensure_android(
    os_name,
    os_arch,
    artifact_mode=False,
    ndk_only=False,
    system_images_only=False,
    emulator_only=False,
    avd_manifest_path: Optional[Path] = None,
    prewarm_avd=False,
    no_interactive=False,
    list_packages=False,
):
    """
    Ensure the Android SDK (and NDK, if `artifact_mode` is falsy) are
    installed.  If not, fetch and unpack the SDK and/or NDK from the
    given URLs.  Ensure the required Android SDK packages are
    installed.

    `os_name` can be 'linux''macosx' or 'windows'.
    """
    # The user may have an external Android SDK (in which case we
    # save them a lengthy download), or they may have already
    # completed the download. We unpack to
    # ~/.mozbuild/{android-sdk-$OS_NAME, android-ndk-$VER}.
    mozbuild_path, sdk_path, ndk_path, avd_home_path = get_paths(os_name)

    if os_name == "macosx":
        os_tag = "mac"
    elif os_name == "windows":
        os_tag = "win"
    else:
        os_tag = os_name

    sdk_url = "https://dl.google.com/android/repository/commandlinetools-{0}-{1}_latest.zip".format(  # NOQA: E501
        os_tag, CMDLINE_TOOLS_VERSION
    )
    ndk_url = android_ndk_url(os_name)
    bundletool_url = "https://github.com/google/bundletool/releases/download/{v}/bundletool-all-{v}.jar".format(  # NOQA: E501
        v=BUNDLETOOL_VERSION
    )

    ensure_android_sdk_and_ndk(
        mozbuild_path,
        os_name,
        sdk_path=sdk_path,
        sdk_url=sdk_url,
        ndk_path=ndk_path,
        ndk_url=ndk_url,
        bundletool_url=bundletool_url,
        artifact_mode=artifact_mode,
        ndk_only=ndk_only,
        emulator_only=emulator_only,
    )

    if ndk_only:
        return

    avd_manifest = None
    if avd_manifest_path is not None:
        with open(avd_manifest_path) as f:
            avd_manifest = json.load(f)
        # Some AVDs cannot be prewarmed in CI because they cannot run on linux64
        # (like the arm64 AVD).
        if "emulator_prewarm" in avd_manifest:
            prewarm_avd = prewarm_avd and avd_manifest["emulator_prewarm"]

    # We expect the |sdkmanager| tool to be at
    # ~/.mozbuild/android-sdk-$OS_NAME/tools/cmdline-tools/$CMDLINE_TOOLS_VERSION_STRING/bin/sdkmanager. # NOQA: E501
    ensure_android_packages(
        os_name,
        os_arch,
        sdkmanager_tool=sdkmanager_tool(sdk_path),
        emulator_only=emulator_only,
        system_images_only=system_images_only,
        avd_manifest=avd_manifest,
        no_interactive=no_interactive,
        list_packages=list_packages,
    )

    if emulator_only or system_images_only:
        return

    ensure_android_avd(
        avdmanager_tool=avdmanager_tool(sdk_path),
        adb_tool=adb_tool(sdk_path),
        emulator_tool=emulator_tool(sdk_path),
        avd_home_path=avd_home_path,
        sdk_path=sdk_path,
        no_interactive=no_interactive,
        avd_manifest=avd_manifest,
        prewarm_avd=prewarm_avd,
    )


def ensure_android_sdk_and_ndk(
    mozbuild_path: Path,
    os_name,
    sdk_path: Path,
    sdk_url,
    ndk_path: Path,
    ndk_url,
    bundletool_url,
    artifact_mode,
    ndk_only,
    emulator_only,
):
    """
    Ensure the Android SDK and NDK are found at the given paths.  If not, fetch
    and unpack the SDK and/or NDK from the given URLs into
    |mozbuild_path/{android-sdk-$OS_NAME,android-ndk-$VER}|.
    """

    # It's not particularly bad to overwrite the NDK toolchain, but it does take
    # a while to unpack, so let's avoid the disk activity if possible.  The SDK
    # may prompt about licensing, so we do this first.
    # Check for Android NDK only if we are not in artifact mode.
    if not artifact_mode and not emulator_only:
        install_ndk = True
        if ndk_path.is_dir():
            try:
                _, _, human = get_ndk_version(ndk_path)
                if human == NDK_VERSION:
                    print(ANDROID_NDK_EXISTS % ndk_path)
                    install_ndk = False
            except GetNdkVersionError:
                pass  # Just do the install.
        if install_ndk:
            # The NDK archive unpacks into a top-level android-ndk-$VER directory.
            install_mobile_android_sdk_or_ndk(ndk_url, mozbuild_path)

    if ndk_only:
        return

    # We don't want to blindly overwrite, since we use the
    # |sdkmanager| tool to install additional parts of the Android
    # toolchain.  If we overwrite, we lose whatever Android packages
    # the user may have already installed.
    if sdkmanager_tool(sdk_path).is_file():
        print(ANDROID_SDK_EXISTS % sdk_path)
    elif sdk_path.is_dir():
        raise NotImplementedError(ANDROID_SDK_TOO_OLD % sdk_path)
    else:
        # The SDK archive used to include a top-level
        # android-sdk-$OS_NAME directory; it no longer does so.  We
        # preserve the old convention to smooth detecting existing SDK
        # installations.
        cmdline_tools_path = mozbuild_path / f"android-sdk-{os_name}" / "cmdline-tools"
        install_mobile_android_sdk_or_ndk(sdk_url, cmdline_tools_path)
        # The tools package *really* wants to be in
        # <sdk>/cmdline-tools/$CMDLINE_TOOLS_VERSION_STRING
        (cmdline_tools_path / "cmdline-tools").rename(
            cmdline_tools_path / CMDLINE_TOOLS_VERSION_STRING
        )
        download(bundletool_url, mozbuild_path / "bundletool.jar")


def get_packages_to_install(packages_file_content, avd_manifest):
    packages = []
    packages += map(lambda package: package.strip(), packages_file_content)
    if avd_manifest is not None:
        packages += [avd_manifest["emulator_package"]]
    return packages


def ensure_android_avd(
    avdmanager_tool: Path,
    adb_tool: Path,
    emulator_tool: Path,
    avd_home_path: Path,
    sdk_path: Path,
    no_interactive=False,
    avd_manifest=None,
    prewarm_avd=False,
):
    """
    Use the given sdkmanager tool (like 'sdkmanager') to install required
    Android packages.
    """
    if avd_manifest is None:
        return

    avd_home_path.mkdir(parents=True, exist_ok=True)
    # The AVD needs this folder to boot, so make sure it exists here.
    (sdk_path / "platforms").mkdir(parents=True, exist_ok=True)

    avd_name = avd_manifest["emulator_avd_name"]
    args = [
        str(avdmanager_tool),
        "--verbose",
        "create",
        "avd",
        "--force",
        "--name",
        avd_name,
        "--package",
        avd_manifest["emulator_package"],
    ]

    if not no_interactive:
        subprocess.check_call(args)
        return

    # Flush outputs before running sdkmanager.
    sys.stdout.flush()
    env = os.environ.copy()
    env["ANDROID_AVD_HOME"] = str(avd_home_path)
    proc = subprocess.Popen(args, stdin=subprocess.PIPE, env=env)
    proc.communicate("no\n".encode("UTF-8"))

    retcode = proc.poll()
    if retcode:
        cmd = args[0]
        e = subprocess.CalledProcessError(retcode, cmd)
        raise e

    avd_path = avd_home_path / (str(avd_name) + ".avd")
    config_file_name = avd_path / "config.ini"

    print(f"Writing config at {config_file_name}")

    if config_file_name.is_file():
        with open(config_file_name, "a"as config:
            for key, value in avd_manifest["emulator_extra_config"].items():
                config.write("%s=%s\n" % (key, value))
    else:
        raise NotImplementedError(
            f"Could not find config file at {config_file_name}, something went wrong"
        )
    if prewarm_avd:
        run_prewarm_avd(adb_tool, emulator_tool, env, avd_name, avd_manifest)
    # When running in headless mode, the emulator does not run the cleanup
    # step, and thus doesn't delete lock files. On some platforms, left-over
    # lock files can cause the emulator to not start, so we remove them here.
    for lock_file in ["hardware-qemu.ini.lock""multiinstance.lock"]:
        lock_file_path = avd_path / lock_file
        try:
            lock_file_path.unlink()
            print(f"Removed lock file {lock_file_path}")
        except OSError:
            # The lock file is not there, nothing to do.
            pass


def run_prewarm_avd(
    adb_tool: Path,
    emulator_tool: Path,
    env,
    avd_name,
    avd_manifest,
):
    """
    Ensures the emulator is fully booted to save time on future iterations.
    """
    args = [str(emulator_tool), "-avd", avd_name] + avd_manifest["emulator_extra_args"]

    # Flush outputs before running emulator.
    sys.stdout.flush()
    proc = subprocess.Popen(args, env=env)

    booted = False
    for i in range(100):
        boot_completed_cmd = [str(adb_tool), "shell""getprop""sys.boot_completed"]
        completed_proc = subprocess.Popen(
            boot_completed_cmd, env=env, stdout=subprocess.PIPE
        )
        try:
            out, err = completed_proc.communicate(timeout=30)
            boot_completed = out.decode("UTF-8").strip()
            print("sys.boot_completed = %s" % boot_completed)
            time.sleep(30)
            if boot_completed == "1":
                booted = True
                break
        except subprocess.TimeoutExpired:
            # Sometimes the adb command hangs, that's ok
            print("sys.boot_completed = Timeout")

    if not booted:
        raise NotImplementedError("Could not prewarm emulator")

    # Wait until the emulator completely shuts down
    subprocess.Popen([str(adb_tool), "emu""kill"], env=env).wait()
    proc.wait()


def ensure_android_packages(
    os_name,
    os_arch,
    sdkmanager_tool: Path,
    emulator_only=False,
    system_images_only=False,
    avd_manifest=None,
    no_interactive=False,
    list_packages=False,
):
    """
    Use the given sdkmanager tool (like 'sdkmanager') to install required
    Android packages.
    """

    # This tries to install all the required Android packages.  The user
    # may be prompted to agree to the Android license.
    if system_images_only:
        packages_file_name = "android-system-images-packages.txt"
    elif emulator_only:
        packages_file_name = "android-emulator-packages.txt"
    else:
        packages_file_name = "android-packages.txt"

    packages_file_path = (Path(__file__).parent / packages_file_name).resolve()

    with open(packages_file_path) as packages_file:
        packages_file_content = packages_file.readlines()

    packages = get_packages_to_install(packages_file_content, avd_manifest)
    print(INSTALLING_ANDROID_PACKAGES % "\n".join(packages))

    args = [str(sdkmanager_tool)]
    if os_name == "macosx" and os_arch == "arm64":
        # Support for Apple Silicon is still in nightly
        args.append("--channel=3")
    args.extend(packages)

    # sdkmanager needs JAVA_HOME
    java_bin_path = ensure_java(os_name, os_arch)
    env = os.environ.copy()
    env["JAVA_HOME"] = str(java_bin_path.parent)

    if not no_interactive:
        subprocess.check_call(args, env=env)
        return

    # Flush outputs before running sdkmanager.
    sys.stdout.flush()
    sys.stderr.flush()
    # Emulate yes.  For a discussion of passing input to check_output,
    # see https://stackoverflow.com/q/10103551.
    yes = "\n".join(["y"] * 100).encode("UTF-8")
    proc = subprocess.Popen(args, stdin=subprocess.PIPE, env=env)
    proc.communicate(yes)

    retcode = proc.poll()
    if retcode:
        cmd = args[0]
        e = subprocess.CalledProcessError(retcode, cmd)
        raise e
    if list_packages:
        subprocess.check_call([str(sdkmanager_tool), "--list"])


def generate_mozconfig(os_name, artifact_mode=False):
    moz_state_dir, sdk_path, ndk_path, avd_home_path = get_paths(os_name)

    extra_lines = []
    if extra_lines:
        extra_lines.append("")

    if artifact_mode:
        template = MOBILE_ANDROID_ARTIFACT_MODE_MOZCONFIG_TEMPLATE
    else:
        template = MOBILE_ANDROID_MOZCONFIG_TEMPLATE

    kwargs = dict(
        sdk_path=sdk_path,
        ndk_path=ndk_path,
        avd_home_path=avd_home_path,
        moz_state_dir=moz_state_dir,
        extra_lines="\n".join(extra_lines),
    )
    return template.format(**kwargs).strip()


def android_ndk_url(os_name, ver=NDK_VERSION):
    # Produce a URL like
    # 'https://dl.google.com/android/repository/android-ndk-$VER-linux.zip
    base_url = "https://dl.google.com/android/repository/android-ndk"

    if os_name == "macosx":
        # |mach bootstrap| uses 'macosx', but Google uses 'darwin'.
        os_name = "darwin"

    return "%s-%s-%s.zip" % (base_url, ver, os_name)


def main(argv):
    import optparse  # No argparse, which is new in Python 2.7.
    import platform

    parser = optparse.OptionParser()
    parser.add_option(
        "-a",
        "--artifact-mode",
        dest="artifact_mode",
        action="store_true",
        help="If true, install only the Android SDK (and not the Android NDK).",
    )
    parser.add_option(
        "--jdk-only",
        dest="jdk_only",
        action="store_true",
        help="If true, install only the Java JDK.",
    )
    parser.add_option(
        "--ndk-only",
        dest="ndk_only",
        action="store_true",
        help="If true, install only the Android NDK (and not the Android SDK).",
    )
    parser.add_option(
        "--system-images-only",
        dest="system_images_only",
        action="store_true",
        help="If true, install only the system images for the AVDs.",
    )
    parser.add_option(
        "--no-interactive",
        dest="no_interactive",
        action="store_true",
        help="Accept the Android SDK licenses without user interaction.",
    )
    parser.add_option(
        "--emulator-only",
        dest="emulator_only",
        action="store_true",
        help="If true, install only the Android emulator (and not the SDK or NDK).",
    )
    parser.add_option(
        "--avd-manifest",
        dest="avd_manifest_path",
        help="If present, generate AVD from the manifest pointed by this argument.",
    )
    parser.add_option(
        "--prewarm-avd",
        dest="prewarm_avd",
        action="store_true",
        help="If true, boot the AVD and wait until completed to speed up subsequent boots.",
    )
    parser.add_option(
        "--list-packages",
        dest="list_packages",
        action="store_true",
        help="If true, list installed packages.",
    )

    options, _ = parser.parse_args(argv)

    if options.artifact_mode and options.ndk_only:
        raise NotImplementedError("Use no options to install the NDK and the SDK.")

    if options.artifact_mode and options.emulator_only:
        raise NotImplementedError("Use no options to install the SDK and emulators.")

    os_name = None
    if platform.system() == "Darwin":
        os_name = "macosx"
    elif platform.system() == "Linux":
        os_name = "linux"
    elif platform.system() == "Windows":
        os_name = "windows"
    else:
        raise NotImplementedError(
            "We don't support bootstrapping the Android SDK (or Android "
            "NDK) on {0} yet!".format(platform.system())
        )

    os_arch = platform.machine()

    if options.jdk_only:
        ensure_java(os_name, os_arch)
        return 0

    avd_manifest_path = (
        Path(options.avd_manifest_path) if options.avd_manifest_path else None
    )

    ensure_android(
        os_name,
        os_arch,
        artifact_mode=options.artifact_mode,
        ndk_only=options.ndk_only,
        system_images_only=options.system_images_only,
        emulator_only=options.emulator_only,
        avd_manifest_path=avd_manifest_path,
        prewarm_avd=options.prewarm_avd,
        no_interactive=options.no_interactive,
        list_packages=options.list_packages,
    )
    mozconfig = generate_mozconfig(os_name, options.artifact_mode)

    # |./mach bootstrap| automatically creates a mozconfig file for you if it doesn't
    # exist. However, here, we don't know where the "topsrcdir" is, and it's not worth
    # pulling in CommandContext (and its dependencies) to find out.
    # So, instead, we'll politely ask users to create (or update) the file themselves.
    suggestion = MOZCONFIG_SUGGESTION_TEMPLATE % ("$topsrcdir/mozconfig", mozconfig)
    print("\n" + suggestion)

    return 0


def ensure_java(os_name, os_arch):
    mozbuild_path, _, _, _ = get_paths(os_name)

    if os_name == "macosx":
        os_tag = "mac"
    else:
        os_tag = os_name

    if os_arch == "x86_64":
        arch = "x64"
    elif os_arch == "arm64":
        arch = "aarch64"
    else:
        arch = os_arch

    ext = "zip" if os_name == "windows" else "tar.gz"

    java_path = java_bin_path(os_name, mozbuild_path)
    if not java_path:
        raise NotImplementedError(f"Could not bootstrap java for {os_name}.")

    if not java_path.exists():
        # e.g. https://github.com/adoptium/temurin17-binaries/releases/
        #      download/jdk-17.0.12%2B7/OpenJDK17U-jdk_x64_linux_hotspot_17.0.13_11.tar.gz
        java_url = (
            "https://github.com/adoptium/temurin{major}-binaries/releases/"
            "download/jdk-{major}.{minor}%2B{patch}/"
            "OpenJDK{major}U-jdk_{arch}_{os}_hotspot_{major}.{minor}_{patch}.{ext}"
        ).format(
            major=JAVA_VERSION_MAJOR,
            minor=JAVA_VERSION_MINOR,
            patch=JAVA_VERSION_PATCH,
            os=os_tag,
            arch=arch,
            ext=ext,
        )
        install_mobile_android_sdk_or_ndk(java_url, mozbuild_path / "jdk")
    return java_path


def java_bin_path(os_name, toolchain_path: Path):
    # Like jdk-17.0.13+11
    jdk_folder = "jdk-{major}.{minor}+{patch}".format(
        major=JAVA_VERSION_MAJOR, minor=JAVA_VERSION_MINOR, patch=JAVA_VERSION_PATCH
    )

    java_path = toolchain_path / "jdk" / jdk_folder

    if os_name == "macosx":
        return java_path / "Contents" / "Home" / "bin"
    elif os_name == "linux":
        return java_path / "bin"
    elif os_name == "windows":
        return java_path / "bin"
    else:
        return None


def locate_java_bin_path(host_kernel, toolchain_path: Union[str, Path]):
    if host_kernel == "WINNT":
        os_name = "windows"
    elif host_kernel == "Darwin":
        os_name = "macosx"
    elif host_kernel == "Linux":
        os_name = "linux"
    else:
        # Default to Linux
        os_name = "linux"
    path = java_bin_path(os_name, Path(toolchain_path))
    if not path.is_dir():
        raise JavaLocationFailedException(
            f"Could not locate Java at {path}, please run "
            "./mach bootstrap --no-system-changes"
        )
    return str(path)


class JavaLocationFailedException(Exception):
    pass


if __name__ == "__main__":
    sys.exit(main(sys.argv))

96%


¤ Dauer der Verarbeitung: 0.17 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung ist noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


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