From 26a029d407be480d791972afb5975cf62c9360a6 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Fri, 19 Apr 2024 02:47:55 +0200 Subject: Adding upstream version 124.0.1. Signed-off-by: Daniel Baumann --- mach | 199 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 199 insertions(+) create mode 100755 mach (limited to 'mach') diff --git a/mach b/mach new file mode 100755 index 0000000000..5ea05fb643 --- /dev/null +++ b/mach @@ -0,0 +1,199 @@ +#!/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/. + +import os +import platform +import sys +import subprocess +import traceback +from textwrap import dedent, fill + +MIN_PYTHON_VERSION = (3, 8) +MAX_PYTHON_VERSION_TO_CONSIDER = (3, 11) + + +def load_mach(dir_path, mach_path, args): + # 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, args) + + +def check_and_get_mach(dir_path, args): + 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, args) + return None + + +def find_alternate_python3_executables(): + for i in range(MIN_PYTHON_VERSION[1], MAX_PYTHON_VERSION_TO_CONSIDER[1] + 1): + potential_python_binary = f"python3.{i}" + if os.name == "nt": + potential_python_binary += ".exe" + + try: + out = subprocess.run( + [potential_python_binary, "--version"], + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + encoding="UTF-8", + ) + + binary_minor_version = int(out.stdout[9:11].strip(".")) + + if binary_minor_version >= MIN_PYTHON_VERSION[1]: + yield potential_python_binary + + except Exception: + pass + + +def try_alternate_python3_executables(args): + for potential_python_binary in find_alternate_python3_executables(): + try: + print( + f"We found '{potential_python_binary}' and will attempt to re-run Mach with it." + ) + os.execvp( + potential_python_binary, [potential_python_binary] + ["mach"] + args + ) + except Exception: + # We don't really care what goes wrong, just don't let it bubble up + # If we can't successfully launch with a different python3 binary + # we will just print the normal help messages. + pass + + +def main(args): + # Ensure we are running Python 3.8+. We run this check as soon as + # possible to avoid a cryptic import/usage error. + if sys.version_info < MIN_PYTHON_VERSION: + print( + f"Python {MIN_PYTHON_VERSION[0]}.{MIN_PYTHON_VERSION[1]}+ is required to run mach." + ) + print("You are running Mach with Python {0}".format(platform.python_version())) + try_alternate_python3_executables(args) + 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) + + # 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) + + try: + mach = check_and_get_mach(os.path.dirname(os.path.realpath(__file__)), args) + if not mach: + print("Could not run mach: No mach source directory found.") + sys.exit(1) + sys.exit(mach.run(args)) + except (KeyboardInterrupt, SystemExit): + raise + except Exception as e: + if sys.version_info >= ( + MAX_PYTHON_VERSION_TO_CONSIDER[0], + MAX_PYTHON_VERSION_TO_CONSIDER[1] + 1, + ): + traceback.print_exc() + print() + print("---") + print() + print( + fill( + dedent( + f"""\ + Note that you are running Mach with Python + {platform.python_version()}, which is higher than the highest + known working version of Python for Mach. Consider running Mach + with Python {MAX_PYTHON_VERSION_TO_CONSIDER[0]}.{MAX_PYTHON_VERSION_TO_CONSIDER[1]} + or lower.""" + ) + ) + ) + + try: + alternative = next(find_alternate_python3_executables()) + print() + print("Running the following command may solve your issue:") + print() + print(f" {alternative} {sys.argv[0]} {' '.join(args)}") + print() + except StopIteration: + pass + sys.exit(1) + else: + raise + + +if __name__ == "__main__": + main(sys.argv[1:]) -- cgit v1.2.3