summaryrefslogtreecommitdiffstats
path: root/mach
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-19 00:47:55 +0000
commit26a029d407be480d791972afb5975cf62c9360a6 (patch)
treef435a8308119effd964b339f76abb83a57c29483 /mach
parentInitial commit. (diff)
downloadfirefox-26a029d407be480d791972afb5975cf62c9360a6.tar.xz
firefox-26a029d407be480d791972afb5975cf62c9360a6.zip
Adding upstream version 124.0.1.upstream/124.0.1
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'mach')
-rwxr-xr-xmach199
1 files changed, 199 insertions, 0 deletions
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:])