mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-25 22:01:30 +00:00
2eeafe257c
Shortly after mach was introduced, bug 840588 turned mach into a small wrapper that could be copied in a directory part of $PATH, making that wrapper load the right thing from the right source directory. Years later, that setup is not really supported, and it's extra complexity that can lead to unpleasant surprises. Differential Revision: https://phabricator.services.mozilla.com/D102376
196 lines
5.6 KiB
Bash
Executable File
196 lines
5.6 KiB
Bash
Executable File
#!/bin/sh
|
|
# 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/.
|
|
|
|
# The beginning of this script is both valid POSIX shell and valid Python,
|
|
# such that the script starts with the shell and is reexecuted with
|
|
# the right Python.
|
|
|
|
# Embeds a shell script inside a Python triple quote. This pattern is valid
|
|
# shell because `''':'`, `':'` and `:` are all equivalent, and `:` is a no-op.
|
|
''':'
|
|
# Commands that are to be run with Python 2.
|
|
py2commands="
|
|
awsy-test
|
|
firefox-ui-functional
|
|
jsshell-bench
|
|
marionette-test
|
|
jstests
|
|
mozharness
|
|
raptor
|
|
raptor-test
|
|
telemetry-tests-client
|
|
test
|
|
wpt-metadata-merge
|
|
"
|
|
|
|
# Commands that are to be run with the system Python 3 instead of the
|
|
# virtualenv.
|
|
nativecmds="
|
|
bootstrap
|
|
create-mach-environment
|
|
install-moz-phab
|
|
"
|
|
|
|
run_py() {
|
|
# Try to run a specific Python interpreter.
|
|
py_executable="$1"
|
|
shift
|
|
if command -v "$py_executable" > /dev/null
|
|
then
|
|
exec "$py_executable" "$0" "$@"
|
|
else
|
|
echo "This mach command requires $py_executable, which wasn't found on the system!"
|
|
case "$py_executable" in
|
|
python2.7|python3) ;;
|
|
*)
|
|
echo "Consider running 'mach bootstrap' or 'mach create-mach-environment' to create the mach virtualenvs, or set MACH_USE_SYSTEM_PYTHON to use the system Python installation over a virtualenv."
|
|
;;
|
|
esac
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
get_command() {
|
|
# Parse the name of the mach command out of the arguments. This is necessary
|
|
# in the presence of global mach arguments that come before the name of the
|
|
# command, e.g. `mach -v build`. We dispatch to the correct Python
|
|
# interpreter depending on the command.
|
|
while true; do
|
|
case $1 in
|
|
-v|--verbose) shift;;
|
|
-l|--log-file)
|
|
if [ "$#" -lt 2 ]
|
|
then
|
|
echo
|
|
break
|
|
else
|
|
shift 2
|
|
fi
|
|
;;
|
|
--log-interval) shift;;
|
|
--log-no-times) shift;;
|
|
-h) shift;;
|
|
--debug-command) shift;;
|
|
--settings)
|
|
if [ "$#" -lt 2 ]
|
|
then
|
|
echo
|
|
break
|
|
else
|
|
shift 2
|
|
fi
|
|
;;
|
|
# When running `./mach help <command>`, the correct Python for <command>
|
|
# needs to be used.
|
|
help) echo $2; break;;
|
|
# When running `./mach mach-completion /path/to/mach <command>`, the
|
|
# correct Python for <command> needs to be used.
|
|
mach-completion) echo $3; break;;
|
|
"") echo; break;;
|
|
*) echo $1; break;;
|
|
esac
|
|
done
|
|
}
|
|
|
|
state_dir=${MOZBUILD_STATE_PATH:-~/.mozbuild}
|
|
command=$(get_command "$@")
|
|
|
|
# If MACH_USE_SYSTEM_PYTHON or MOZ_AUTOMATION are set, always use the
|
|
# python{2.7,3} executables and not the virtualenv locations.
|
|
if [ -z ${MACH_USE_SYSTEM_PYTHON} ] && [ -z ${MOZ_AUTOMATION} ]
|
|
then
|
|
case "$OSTYPE" in
|
|
cygwin|msys|win32) bin_path=Scripts;;
|
|
*) bin_path=bin;;
|
|
esac
|
|
py2executable=$state_dir/_virtualenvs/mach_py2/$bin_path/python
|
|
py3executable=$state_dir/_virtualenvs/mach/$bin_path/python
|
|
else
|
|
py2executable=python2.7
|
|
py3executable=python3
|
|
fi
|
|
|
|
# Check whether we need to run with the native Python 3 interpreter.
|
|
case " $(echo $nativecmds) " in
|
|
*\ $command\ *)
|
|
run_py python3 "$@"
|
|
;;
|
|
esac
|
|
|
|
# Check for the mach subcommand in the Python 2 commands list and run it
|
|
# with the correct interpreter.
|
|
case " $(echo $py2commands) " in
|
|
*\ $command\ *)
|
|
run_py "$py2executable" "$@"
|
|
;;
|
|
*)
|
|
if [ -z ${MACH_PY2} ]
|
|
then
|
|
run_py "$py3executable" "$@"
|
|
else
|
|
if [ $command != "python-test" ]
|
|
then
|
|
echo "MACH_PY2 is only valid for mach python-test; please unset MACH_PY2 to continue."
|
|
exit 1
|
|
fi
|
|
run_py "$py2executable" "$@"
|
|
fi
|
|
;;
|
|
esac
|
|
|
|
# Run Python 3 for everything else.
|
|
run_py "$py3executable" "$@"
|
|
'''
|
|
|
|
from __future__ import absolute_import, print_function, unicode_literals
|
|
|
|
import os
|
|
import sys
|
|
|
|
def load_mach(dir_path, mach_path):
|
|
if sys.version_info < (3, 5):
|
|
import imp
|
|
mach_bootstrap = imp.load_source('mach_bootstrap', mach_path)
|
|
else:
|
|
import importlib.util
|
|
spec = importlib.util.spec_from_file_location('mach_bootstrap', mach_path)
|
|
mach_bootstrap = importlib.util.module_from_spec(spec)
|
|
spec.loader.exec_module(mach_bootstrap)
|
|
|
|
return mach_bootstrap.bootstrap(dir_path)
|
|
|
|
|
|
def check_and_get_mach(dir_path):
|
|
bootstrap_paths = (
|
|
'build/mach_bootstrap.py',
|
|
# test package bootstrap
|
|
'tools/mach_bootstrap.py',
|
|
)
|
|
for bootstrap_path in bootstrap_paths:
|
|
mach_path = os.path.join(dir_path, bootstrap_path)
|
|
if os.path.isfile(mach_path):
|
|
return load_mach(dir_path, mach_path)
|
|
return None
|
|
|
|
|
|
def main(args):
|
|
# 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:])
|