mach
author Matthew Gaudet <mgaudet@mozilla.com>
Wed, 05 Oct 2022 17:21:34 +0000
changeset 636997 517d690052a2c3b4011b937aa9d0220e52f754e6
parent 636824 243515c2a3fc88a36d87a9d53af8ef3cd77ab4c0
permissions -rwxr-xr-x
Bug 1792720 - Make JS Streams a MOZCONFIG opt in r=bthrall Differential Revision: https://phabricator.services.mozilla.com/D158281

#!/usr/bin/env python3
# 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/.

from __future__ import absolute_import, print_function, unicode_literals

import os
import platform
import sys
from textwrap import dedent


def load_mach(dir_path, mach_path):
    # Defer import of "importlib.util" until after Python version check has happened
    # so that Python 2 usages fail gracefully.
    import importlib.util
    spec = importlib.util.spec_from_file_location('mach_initialize', mach_path)
    mach_initialize = importlib.util.module_from_spec(spec)
    spec.loader.exec_module(mach_initialize)
    return mach_initialize.initialize(dir_path)


def check_and_get_mach(dir_path):
    initialize_paths = (
        # Run Thunderbird's mach_initialize.py if it exists
        'comm/build/mach_initialize.py',
        'build/mach_initialize.py',
        # test package initialize
        'tools/mach_initialize.py',
    )
    for initialize_path in initialize_paths:
        mach_path = os.path.join(dir_path, initialize_path)
        if os.path.isfile(mach_path):
            return load_mach(dir_path, mach_path)
    return None


def main(args):
    # Ensure we are running Python 3.6+. We run this check as soon as
    # possible to avoid a cryptic import/usage error.
    if sys.version_info < (3, 6):
        print("Python 3.6+ is required to run mach.")
        print("You are running Python", platform.python_version())
        if sys.platform.startswith("linux"):
            print(dedent("""
            See https://firefox-source-docs.mozilla.org/setup/linux_build.html#installingpython
            for guidance on how to install Python on your system.
            """).strip())
        elif sys.platform.startswith("darwin"):
            print(dedent("""
            See https://firefox-source-docs.mozilla.org/setup/macos_build.html
            for guidance on how to prepare your system to build Firefox. Perhaps
            you need to update Xcode, or install Python using brew?
            """).strip())
        elif "MOZILLABUILD" in os.environ and os.environ.get("TERM"):
            print(dedent("""
            Python is provided by MozillaBuild; ensure your MozillaBuild installation is
            up to date. See https://firefox-source-docs.mozilla.org/setup/windows_build.html#install-mozillabuild
            for details.
            """).strip())
        elif sys.platform.startswith("win"):
            print(dedent("""
            You probably want to be interacting with Mach from within MozillaBuild, see
            https://firefox-source-docs.mozilla.org/setup/windows_build.html for details.
            
            If you are deliberately using Mach from outside MozillaBuild, then see
            https://firefox-source-docs.mozilla.org/mach/windows-usage-outside-mozillabuild.html#install-python
            for guidance on installing native Python on your system.
            """).strip())
        else:
            print(dedent("""
            We do not have specific instructions for your platform on how to
            install Python. You may find Pyenv (https://github.com/pyenv/pyenv)
            helpful, if your system package manager does not provide a way to
            install a recent enough Python 3.
            """).strip())
        sys.exit(1)

    if sys.version_info >= (3, 10) and sys.platform.startswith("darwin"):
        version = f"{sys.version_info[0]}.{sys.version_info[1]}"
        if f"python@{version}" in sys.executable:
            print(dedent(f"""
            You are using python {version} from homebrew.
            There is a bug in virtualenv that prevents us from starting up mach in that situation.

            Please uninstall it with the following and try again:
              brew unlink python@{version}

            If you need python {version} later, you can re-link it with:
              brew link python@{version}
            """).strip())
            sys.exit(1)

    # XCode python sets __PYVENV_LAUNCHER__, which overrides the executable
    # used when a python subprocess is created. This is an issue when we want
    # to run using our virtualenv python executables.
    # In future Python relases, __PYVENV_LAUNCHER__ will be cleared before
    # application code (mach) is started.
    # https://github.com/python/cpython/pull/9516
    os.environ.pop("__PYVENV_LAUNCHER__", None)

    mach = check_and_get_mach(os.path.dirname(os.path.realpath(__file__)))
    if not mach:
        print('Could not run mach: No mach source directory found.')
        sys.exit(1)
    sys.exit(mach.run(args))


if __name__ == '__main__':
    main(sys.argv[1:])