aboutsummaryrefslogtreecommitdiffstats
path: root/python/servo/bootstrap_commands.py
diff options
context:
space:
mode:
Diffstat (limited to 'python/servo/bootstrap_commands.py')
-rw-r--r--python/servo/bootstrap_commands.py105
1 files changed, 104 insertions, 1 deletions
diff --git a/python/servo/bootstrap_commands.py b/python/servo/bootstrap_commands.py
index ce4e12381e0..092d6653d2d 100644
--- a/python/servo/bootstrap_commands.py
+++ b/python/servo/bootstrap_commands.py
@@ -13,6 +13,7 @@ import base64
import json
import os
import os.path as path
+import platform
import re
import subprocess
import sys
@@ -28,7 +29,7 @@ from mach.decorators import (
import servo.bootstrap as bootstrap
from servo.command_base import CommandBase, cd, check_call
-from servo.util import delete, download_bytes
+from servo.util import delete, download_bytes, download_file, extract, check_hash
@CommandProvider
@@ -54,6 +55,108 @@ class MachCommands(CommandBase):
def bootstrap(self, force=False):
return bootstrap.bootstrap(self.context, force=force)
+ @Command('bootstrap-android',
+ description='Install the Android SDK and NDK.',
+ category='bootstrap')
+ def bootstrap_android(self):
+
+ ndk = "android-ndk-r12b-{system}-{arch}"
+ tools = "sdk-tools-{system}-4333796"
+
+ sdk_build_tools = "25.0.2"
+ emulator_images = [
+ ("servo-arm", "25", "google_apis;armeabi-v7a"),
+ ("servo-x86", "28", "google_apis;x86"),
+ ]
+
+ known_sha1 = {
+ # https://dl.google.com/android/repository/repository2-1.xml
+ "sdk-tools-darwin-4333796.zip": "ed85ea7b59bc3483ce0af4c198523ba044e083ad",
+ "sdk-tools-linux-4333796.zip": "8c7c28554a32318461802c1291d76fccfafde054",
+ "sdk-tools-windows-4333796.zip": "aa298b5346ee0d63940d13609fe6bec621384510",
+
+ # https://developer.android.com/ndk/downloads/older_releases
+ "android-ndk-r12b-windows-x86.zip": "8e6eef0091dac2f3c7a1ecbb7070d4fa22212c04",
+ "android-ndk-r12b-windows-x86_64.zip": "337746d8579a1c65e8a69bf9cbdc9849bcacf7f5",
+ "android-ndk-r12b-darwin-x86_64.zip": "e257fe12f8947be9f79c10c3fffe87fb9406118a",
+ "android-ndk-r12b-linux-x86_64.zip": "170a119bfa0f0ce5dc932405eaa3a7cc61b27694",
+ }
+
+ toolchains = path.join(self.context.topdir, "android-toolchains")
+ if not path.isdir(toolchains):
+ os.makedirs(toolchains)
+
+ def download(target_dir, name, flatten=False):
+ final = path.join(toolchains, target_dir)
+ if path.isdir(final):
+ return
+
+ base_url = "https://dl.google.com/android/repository/"
+ filename = name + ".zip"
+ url = base_url + filename
+ archive = path.join(toolchains, filename)
+
+ if not path.isfile(archive):
+ download_file(filename, url, archive)
+ check_hash(archive, known_sha1[filename], "sha1")
+ print("Extracting " + filename)
+ remove = True # Set to False to avoid repeated downloads while debugging this script
+ if flatten:
+ extracted = final + "_"
+ extract(archive, extracted, remove=remove)
+ contents = os.listdir(extracted)
+ assert len(contents) == 1
+ os.rename(path.join(extracted, contents[0]), final)
+ os.rmdir(extracted)
+ else:
+ extract(archive, final, remove=remove)
+
+ system = platform.system().lower()
+ machine = platform.machine().lower()
+ arch = {"i386": "x86"}.get(machine, machine)
+ download("ndk", ndk.format(system=system, arch=arch), flatten=True)
+ download("sdk", tools.format(system=system))
+
+ subprocess.check_call([
+ path.join(toolchains, "sdk", "tools", "bin", "sdkmanager"),
+ "platform-tools",
+ "build-tools;" + sdk_build_tools,
+ "emulator",
+ ] + [
+ arg
+ for avd_name, api_level, system_image in emulator_images
+ for arg in [
+ "platforms;android-" + api_level,
+ "system-images;android-%s;%s" % (api_level, system_image),
+ ]
+ ])
+ for avd_name, api_level, system_image in emulator_images:
+ process = subprocess.Popen(stdin=subprocess.PIPE, stdout=subprocess.PIPE, args=[
+ path.join(toolchains, "sdk", "tools", "bin", "avdmanager"),
+ "create", "avd",
+ "--path", path.join(toolchains, "avd", avd_name),
+ "--name", avd_name,
+ "--package", "system-images;android-%s;%s" % (api_level, system_image),
+ "--force",
+ ])
+ output = b""
+ while 1:
+ # Read one byte at a time because in Python:
+ # * readline() blocks until "\n", which doesn't come before the prompt
+ # * read() blocks until EOF, which doesn't come before the prompt
+ # * read(n) keeps reading until it gets n bytes or EOF,
+ # but we don't know reliably how many bytes to read until the prompt
+ byte = process.stdout.read(1)
+ if len(byte) == 0:
+ break
+ output += byte
+ # There seems to be no way to disable this prompt:
+ if output.endswith(b"Do you wish to create a custom hardware profile? [no]"):
+ process.stdin.write("no\n")
+ assert process.wait() == 0
+ with open(path.join(toolchains, "avd", avd_name, "config.ini"), "a") as f:
+ f.write("disk.dataPartition.size=2G\n")
+
@Command('update-hsts-preload',
description='Download the HSTS preload list',
category='bootstrap')