mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-27 14:52:16 +00:00
e53cf4ad77
Do not try to outsmart the user and pick an older Python version there: first because it may work, second because when you leave on the bleeding edge, you may want to fix the portability issue, and should be skilled enough to invoke another Python interpreter on your own. Still give an advice if we can find an alternate python version that should work. Differential Revision: https://phabricator.services.mozilla.com/D191266
169 lines
6.6 KiB
Python
Executable File
169 lines
6.6 KiB
Python
Executable File
#!/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, 7)
|
|
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.7+. 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:
|
|
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:])
|