Bug 1384202 - Add --no-interactive bootstrap support for Android SDK and NDK. r=rillian
Hacky, but it works -- until Google updates its license hashes. This
looks ahead to using |mach bootstrap| to build docker images.
MozReview-Commit-ID: DF23v8tr8SW
--- a/python/mozboot/mozboot/android.py
+++ b/python/mozboot/mozboot/android.py
@@ -136,17 +136,27 @@ def get_paths(os_name):
os.path.expanduser(os.path.join('~', '.mozbuild')))
sdk_path = os.environ.get('ANDROID_SDK_HOME',
os.path.join(mozbuild_path, 'android-sdk-{}'.format(os_name)))
ndk_path = os.environ.get('ANDROID_NDK_HOME',
os.path.join(mozbuild_path, 'android-ndk-r11c'))
return (mozbuild_path, sdk_path, ndk_path)
-def ensure_android(os_name, artifact_mode):
+def ensure_dir(dir):
+ '''Ensures the given directory exists'''
+ if dir and not os.path.exists(dir):
+ try:
+ os.makedirs(dir)
+ except OSError as error:
+ if error.errno != errno.EEXIST:
+ raise
+
+
+def ensure_android(os_name, artifact_mode=False, no_interactive=False):
'''
Ensure the Android SDK (and NDK, if `artifact_mode` is falsy) are
installed. If not, fetch and unpack the SDK and/or NDK from the
given URLs. Ensure the required Android SDK packages are
installed.
`os_name` can be 'linux' or 'macosx'.
'''
@@ -159,16 +169,31 @@ def ensure_android(os_name, artifact_mod
sdk_url = 'https://dl.google.com/android/repository/sdk-tools-{}-3859397.zip'.format(os_tag)
ndk_url = android_ndk_url(os_name)
ensure_android_sdk_and_ndk(mozbuild_path, os_name,
sdk_path=sdk_path, sdk_url=sdk_url,
ndk_path=ndk_path, ndk_url=ndk_url,
artifact_mode=artifact_mode)
+ if no_interactive:
+ # Cribbed from observation and https://stackoverflow.com/a/38381577.
+ path = os.path.join(mozbuild_path, 'android-sdk-{}'.format(os_name), 'licenses')
+ ensure_dir(path)
+
+ licenses = {
+ 'android-sdk-license': '8933bad161af4178b1185d1a37fbf41ea5269c55',
+ 'android-sdk-preview-license': '84831b9409646a918e30573bab4c9c91346d8abd',
+ }
+ for license, tag in licenses.items():
+ lname = os.path.join(path, license)
+ if not os.path.isfile(lname):
+ open(lname, 'w').write('\n{}\n'.format(tag))
+
+
# We expect the |sdkmanager| tool to be at
# ~/.mozbuild/android-sdk-$OS_NAME/tools/bin/sdkmanager.
sdkmanager_tool = os.path.join(sdk_path, 'tools', 'bin', 'sdkmanager')
ensure_android_packages(sdkmanager_tool=sdkmanager_tool)
def ensure_android_sdk_and_ndk(mozbuild_path, os_name, sdk_path, sdk_url, ndk_path, ndk_url, artifact_mode):
'''
@@ -244,30 +269,32 @@ def android_ndk_url(os_name, ver='r11c')
def main(argv):
import optparse # No argparse, which is new in Python 2.7.
import platform
parser = optparse.OptionParser()
parser.add_option('-a', '--artifact-mode', dest='artifact_mode', action='store_true',
help='If true, install only the Android SDK (and not the Android NDK).')
+ parser.add_option('--no-interactive', dest='no_interactive', action='store_true',
+ help='Accept the Android SDK licenses without user interaction.')
options, _ = parser.parse_args(argv)
os_name = None
if platform.system() == 'Darwin':
os_name = 'macosx'
elif platform.system() == 'Linux':
os_name = 'linux'
elif platform.system() == 'Windows':
os_name = 'windows'
else:
raise NotImplementedError("We don't support bootstrapping the Android SDK (or Android NDK) "
"on {} yet!".format(platform.system()))
- ensure_android(os_name, options.artifact_mode)
+ ensure_android(os_name, artifact_mode=options.artifact_mode, no_interactive=options.no_interactive)
suggest_mozconfig(os_name, options.artifact_mode)
return 0
if __name__ == '__main__':
sys.exit(main(sys.argv))
--- a/python/mozboot/mozboot/archlinux.py
+++ b/python/mozboot/mozboot/archlinux.py
@@ -118,17 +118,18 @@ class ArchlinuxBootstrapper(StyloInstall
'toolchain requires 32 bit binaries be enabled (see '
'https://wiki.archlinux.org/index.php/Android). You may need to '
'manually enable the multilib repository following the instructions '
'at https://wiki.archlinux.org/index.php/Multilib.')
raise e
# 2. Android pieces.
import android
- android.ensure_android('linux', artifact_mode=artifact_mode)
+ android.ensure_android('linux', artifact_mode=artifact_mode,
+ no_interactive=self.no_interactive)
def suggest_mobile_android_mozconfig(self, artifact_mode=False):
import android
android.suggest_mozconfig('linux', artifact_mode=artifact_mode)
def suggest_mobile_android_artifact_mode_mozconfig(self):
self.suggest_mobile_android_mozconfig(artifact_mode=True)
--- a/python/mozboot/mozboot/centosfedora.py
+++ b/python/mozboot/mozboot/centosfedora.py
@@ -107,17 +107,18 @@ class CentOSFedoraBootstrapper(StyloInst
self.run_as_root(['rpm', '-ivh', yasm])
def ensure_mobile_android_packages(self, artifact_mode=False):
# Install Android specific packages.
self.dnf_install(*self.mobile_android_packages)
import android
- android.ensure_android('linux', artifact_mode=artifact_mode)
+ android.ensure_android('linux', artifact_mode=artifact_mode,
+ no_interactive=self.no_interactive)
def suggest_mobile_android_mozconfig(self, artifact_mode=False):
import android
android.suggest_mozconfig('linux', artifact_mode=artifact_mode)
def suggest_mobile_android_artifact_mode_mozconfig(self):
self.suggest_mobile_android_mozconfig(artifact_mode=True)
--- a/python/mozboot/mozboot/debian.py
+++ b/python/mozboot/mozboot/debian.py
@@ -122,17 +122,18 @@ class DebianBootstrapper(StyloInstall, B
# http://developer.android.com/sdk/installing/index.html?pkg=tools.
self.run_as_root(['dpkg', '--add-architecture', 'i386'])
# After adding a new arch, the list of packages has to be updated
self.apt_update()
self.apt_install(*self.mobile_android_packages)
# 2. Android pieces.
import android
- android.ensure_android('linux', artifact_mode=artifact_mode)
+ android.ensure_android('linux', artifact_mode=artifact_mode,
+ no_interactive=self.no_interactive)
def suggest_mobile_android_mozconfig(self, artifact_mode=False):
import android
android.suggest_mozconfig('linux', artifact_mode=artifact_mode)
def suggest_mobile_android_artifact_mode_mozconfig(self):
self.suggest_mobile_android_mozconfig(artifact_mode=True)
--- a/python/mozboot/mozboot/mach_commands.py
+++ b/python/mozboot/mozboot/mach_commands.py
@@ -18,20 +18,22 @@ class Bootstrap(object):
"""Bootstrap system and mach for optimal development experience."""
@Command('bootstrap', category='devenv',
description='Install required system packages for building.')
@CommandArgument('--application-choice',
default=None,
help='Pass in an application choice (see mozboot.bootstrap.APPLICATIONS) '
'instead of using the default interactive prompt.')
- def bootstrap(self, application_choice=None):
+ @CommandArgument('--no-interactive', dest='no_interactive', action='store_true',
+ help='Answer yes to any (Y/n) interactive prompts.')
+ def bootstrap(self, application_choice=None, no_interactive=False):
from mozboot.bootstrap import Bootstrapper
- bootstrapper = Bootstrapper(choice=application_choice)
+ bootstrapper = Bootstrapper(choice=application_choice, no_interactive=no_interactive)
bootstrapper.bootstrap()
@CommandProvider
class VersionControlCommands(object):
def __init__(self, context):
self._context = context
--- a/python/mozboot/mozboot/osx.py
+++ b/python/mozboot/mozboot/osx.py
@@ -349,17 +349,18 @@ class OSXBootstrapper(BaseBootstrapper):
print(JAVA_LICENSE_NOTICE) # We accepted a license agreement for the user.
is_64bits = sys.maxsize > 2**32
if not is_64bits:
raise Exception('You need a 64-bit version of Mac OS X to build Firefox for Android.')
# 2. Android pieces.
import android
- android.ensure_android('macosx', artifact_mode=artifact_mode)
+ android.ensure_android('macosx', artifact_mode=artifact_mode,
+ no_interactive=self.no_interactive)
def suggest_homebrew_mobile_android_mozconfig(self, artifact_mode=False):
import android
android.suggest_mozconfig('macosx', artifact_mode=artifact_mode)
def _ensure_macports_packages(self, packages):
self.port = self.which('port')
assert self.port is not None
@@ -412,17 +413,18 @@ class OSXBootstrapper(BaseBootstrapper):
'to get the latest version.')
is_64bits = sys.maxsize > 2**32
if not is_64bits:
raise Exception('You need a 64-bit version of Mac OS X to build Firefox for Android.')
# 2. Android pieces.
import android
- android.ensure_android('macosx', artifact_mode=artifact_mode)
+ android.ensure_android('macosx', artifact_mode=artifact_mode,
+ no_interactive=self.no_interactive)
def suggest_macports_mobile_android_mozconfig(self, artifact_mode=False):
import android
android.suggest_mozconfig('macosx', artifact_mode=artifact_mode)
def ensure_package_manager(self):
'''
Search package mgr in sys.path, if none is found, prompt the user to install one.