Bug 1667394 - Check for presence of pip3 and distutils.sysconfig in bootstrap r=firefox-build-system-reviewers,mhentges

`bootstrap` does not/cannot "fix" a broken Python environment, but we can do some checks and make sensible suggestions about how to fix the problem.

We expect that both of the checks we do here are primarily going to be triggered on new installs of Ubuntu. For macOS, installing `python` with `brew` will also install `pip`, and Windows has MozillaBuild. It's just Ubuntu that goes out of its way to be confusing, so add particularly informative error messages for Debian/Ubuntu.

Note that this doesn't change the functionality of `bootstrap` in any fundamental way -- `mach` is already broken if either of these conditions don't hold, but now we show an informative error message.

Differential Revision: https://phabricator.services.mozilla.com/D91470
This commit is contained in:
Ricky Stewart 2020-09-28 19:19:58 +00:00
parent f91c1a1428
commit d6d752863b
3 changed files with 52 additions and 0 deletions

View File

@ -169,6 +169,16 @@ class BaseBootstrapper(object):
to the user, if necessary. to the user, if necessary.
''' '''
def suggest_install_distutils(self):
'''Called if distutils.{sysconfig,spawn} can't be imported.'''
print('Does your distro require installing another package for '
'distutils?', file=sys.stderr)
def suggest_install_pip3(self):
'''Called if pip3 can't be found.'''
print("Try installing pip3 with your system's package manager.",
file=sys.stderr)
def install_system_packages(self): def install_system_packages(self):
''' '''
Install packages shared by all applications. These are usually Install packages shared by all applications. These are usually

View File

@ -364,6 +364,7 @@ class Bootstrapper(object):
env=self.instance._hg_cleanenv(load_hgrc=True), env=self.instance._hg_cleanenv(load_hgrc=True),
hg=which('hg')) hg=which('hg'))
self.instance.validate_environment(checkout_root) self.instance.validate_environment(checkout_root)
self._validate_python_environment()
self.instance.ensure_mach_environment(checkout_root) self.instance.ensure_mach_environment(checkout_root)
if self.instance.no_system_changes: if self.instance.no_system_changes:
@ -439,6 +440,38 @@ class Bootstrapper(object):
mozconfig_path, raw_mozconfig) mozconfig_path, raw_mozconfig)
print(suggestion) print(suggestion)
def _validate_python_environment(self):
valid = True
try:
# distutils is singled out here because some distros (namely Ubuntu)
# include it in a separate package outside of the main Python
# installation.
import distutils.sysconfig
import distutils.spawn
assert (distutils.sysconfig is not None
and distutils.spawn is not None)
except ImportError as e:
print('ERROR: Could not import package %s' % e.name,
file=sys.stderr)
self.instance.suggest_install_distutils()
valid = False
except AssertionError:
print('ERROR: distutils is not behaving as expected.',
file=sys.stderr)
self.instance.suggest_install_distutils()
valid = False
pip3 = which('pip3')
if not pip3:
print('ERROR: Could not find pip3.', file=sys.stderr)
self.instance.suggest_install_pip3()
valid = False
if not valid:
print('ERROR: Your Python installation will not be able to run '
'`mach bootstrap`. `mach bootstrap` cannot maintain your '
'Python environment for you; fix the errors shown here, and '
'then re-run `mach bootstrap`.', file=sys.stderr)
sys.exit(1)
def update_vct(hg, root_state_dir): def update_vct(hg, root_state_dir):
"""Ensure version-control-tools in the state directory is up to date.""" """Ensure version-control-tools in the state directory is up to date."""

View File

@ -7,6 +7,7 @@ from __future__ import absolute_import, print_function, unicode_literals
from mozboot.base import BaseBootstrapper from mozboot.base import BaseBootstrapper
from mozboot.linux_common import LinuxBootstrapper from mozboot.linux_common import LinuxBootstrapper
import sys
MERCURIAL_INSTALL_PROMPT = ''' MERCURIAL_INSTALL_PROMPT = '''
Mercurial releases a new version every 3 months and your distro's package Mercurial releases a new version every 3 months and your distro's package
@ -82,6 +83,14 @@ class DebianBootstrapper(
if self.distro == 'debian': if self.distro == 'debian':
self.packages += self.DEBIAN_PACKAGES self.packages += self.DEBIAN_PACKAGES
def suggest_install_distutils(self):
print('HINT: Try installing distutils with '
'`apt-get install python3-distutils`.', file=sys.stderr)
def suggest_install_pip3(self):
print("HINT: Try installing pip3 with `apt-get install python3-pip`.",
file=sys.stderr)
def install_system_packages(self): def install_system_packages(self):
self.apt_install(*self.packages) self.apt_install(*self.packages)