From b9d5f11b208e3b888433e9de3ad5eee503e82ea1 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Thu, 21 Jun 2018 16:52:33 +0200 Subject: [PATCH 01/30] Add `./mach bootstrap-android` --- .gitignore | 1 + python/servo/bootstrap_commands.py | 53 +++++++++++++++++++++++++++++- python/servo/util.py | 13 ++++++++ 3 files changed, 66 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 65e048a001d9..94acd5b1d033 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ /.cargo/* !/.cargo/config.* /.servobuild +/android-toolchains /target /ports/android/bin /ports/android/libs diff --git a/python/servo/bootstrap_commands.py b/python/servo/bootstrap_commands.py index b422a5530037..f2f672f76536 100644 --- a/python/servo/bootstrap_commands.py +++ b/python/servo/bootstrap_commands.py @@ -13,6 +13,7 @@ import json import os import os.path as path +import platform import re import subprocess import sys @@ -28,7 +29,7 @@ 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, check_hash, extract @CommandProvider @@ -54,6 +55,56 @@ def env(self): 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_version = "r12b" + ndk_sha512 = "2d85b476436ca50896e4b7c5d0f15547fd14a6ebec7e0081022b28f791709af7" \ + "8ea5ebddcdf4722b5e94daeac288d509bd5f240b0280167edef8e199da3d0501" + + sdk_version = "r25.2.3" + sdk_sha512 = "dfc30ee3e2714cf8008ab1f99757deded002d21b23a8d2ab07952e1afd1c9312" \ + "4ddec06660babf6a46c54e5e7e135c8c0cb4cc512378a8509da074dbf7e253d7" + sdk_platform = "25" + sdk_build_tools = "25.0.2" + + + def download(kind, name, sha512): + toolchains = path.join(self.context.topdir, "android-toolchains") + directory = path.join(toolchains, kind) + final = path.join(directory, name) + if path.isdir(final): + return final + + base_url = "https://dl.google.com/android/repository/" + filename = name + ".zip" + url = base_url + filename + archive = path.join(directory, filename) + extract_to = final + ".tmp" + + if not path.isdir(directory): + os.makedirs(directory) + download_file(filename, url, archive) + check_hash(archive, sha512, "sha512") + print("Extracting " + filename) + extract(archive, extract_to) + contents = os.listdir(extract_to) + assert len(contents) == 1 + extracted_dir = path.join(extract_to, contents[0]) + assert path.isdir(extracted_dir) + os.rename(extracted_dir, final) + os.rmdir(extract_to) + return final + + system = platform.system().lower() + machine = platform.machine().lower() + os_ = {"darwin": "macosx"}.get(system, system) + arch = {"i386": "x86"}.get(machine, machine) + ndk = download("ndk", "android-ndk-%s-%s-%s" % (ndk_version, system, arch), ndk_sha512) + sdk = download("sdk", "tools_%s-%s" % (sdk_version, os_), sdk_sha512) + @Command('update-hsts-preload', description='Download the HSTS preload list', category='bootstrap') diff --git a/python/servo/util.py b/python/servo/util.py index 2043b0e2868c..a4e126d3240f 100644 --- a/python/servo/util.py +++ b/python/servo/util.py @@ -9,6 +9,7 @@ from __future__ import absolute_import, print_function, unicode_literals +import hashlib import os import os.path import platform @@ -165,3 +166,15 @@ def extract(src, dst, movedir=None): os.rmdir(movedir) os.remove(src) + +def check_hash(filename, expected, algorithm): + hasher = hashlib.new(algorithm) + with open(filename, "rb") as f: + while True: + block = f.read(16 * 1024) + if len(block) == 0: + break + hasher.update(block) + if hasher.hexdigest() != expected: + print("Incorrect {} hash for {}".format(algorithm, filename)) + sys.exit(1) From 510cf1a2ab4221234b9666a6499d4291e817fe50 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Thu, 21 Jun 2018 23:05:38 +0200 Subject: [PATCH 02/30] boostrap: set executable bits when extracting zip files --- python/servo/util.py | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/python/servo/util.py b/python/servo/util.py index a4e126d3240f..7c4cc5aee1b9 100644 --- a/python/servo/util.py +++ b/python/servo/util.py @@ -153,10 +153,25 @@ def download_file(desc, src, dst): download(desc, src, fd) os.rename(tmp_path, dst) - -def extract(src, dst, movedir=None): +# https://stackoverflow.com/questions/39296101/python-zipfile-removes-execute-permissions-from-binaries +# In particular, we want the executable bit for executable files. +class ZipFileWithUnixPermissions(zipfile.ZipFile): + def extract(self, member, path=None, pwd=None): + if not isinstance(member, zipfile.ZipInfo): + member = self.getinfo(member) + + if path is None: + path = os.getcwd() + + extracted = self._extract_member(member, path, pwd) + mode = os.stat(extracted).st_mode + mode |= (member.external_attr >> 16) + os.chmod(extracted, mode) + return extracted + +def extract(src, dst, movedir=None, remove=True): assert src.endswith(".zip") - zipfile.ZipFile(src).extractall(dst) + ZipFileWithUnixPermissions(src).extractall(dst) if movedir: for f in os.listdir(movedir): @@ -165,7 +180,8 @@ def extract(src, dst, movedir=None): os.rename(frm, to) os.rmdir(movedir) - os.remove(src) + if remove: + os.remove(src) def check_hash(filename, expected, algorithm): hasher = hashlib.new(algorithm) From 56df7f42206dc9d877469aabb7d6a39a12decf76 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Thu, 21 Jun 2018 23:07:11 +0200 Subject: [PATCH 03/30] Install complete Android SDK (as much as on Buildbot CI) --- python/servo/bootstrap_commands.py | 29 ++++++++++++++++++++--------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/python/servo/bootstrap_commands.py b/python/servo/bootstrap_commands.py index f2f672f76536..149ed15be49e 100644 --- a/python/servo/bootstrap_commands.py +++ b/python/servo/bootstrap_commands.py @@ -82,20 +82,15 @@ def download(kind, name, sha512): filename = name + ".zip" url = base_url + filename archive = path.join(directory, filename) - extract_to = final + ".tmp" if not path.isdir(directory): os.makedirs(directory) - download_file(filename, url, archive) + if not path.isfile(archive): + download_file(filename, url, archive) check_hash(archive, sha512, "sha512") print("Extracting " + filename) - extract(archive, extract_to) - contents = os.listdir(extract_to) - assert len(contents) == 1 - extracted_dir = path.join(extract_to, contents[0]) - assert path.isdir(extracted_dir) - os.rename(extracted_dir, final) - os.rmdir(extract_to) + remove = True # Set to False to avoid repeated downloads while debugging this script + extract(archive, final, remove=remove) return final system = platform.system().lower() @@ -105,6 +100,22 @@ def download(kind, name, sha512): ndk = download("ndk", "android-ndk-%s-%s-%s" % (ndk_version, system, arch), ndk_sha512) sdk = download("sdk", "tools_%s-%s" % (sdk_version, os_), sdk_sha512) + if not path.isdir(path.join(sdk, "platform-tools")): + subprocess.check_call([ + path.join(sdk, "tools", "android"), + "update", "sdk", "--no-ui", "--all", "--filter", + "platform-tools,android-%s,build-tools-%s" % (sdk_platform, sdk_build_tools), + ]) + + contents = os.listdir(ndk) + assert len(contents) == 1 + ndk = path.join(ndk, contents[0]) + + print("") + print("export ANDROID_SDK=\"%s\"" % sdk) + print("export ANDROID_NDK=\"%s\"" % ndk) + print("export PATH=\"%s:$PATH\"" % path.join(sdk, "platform-tools")) + @Command('update-hsts-preload', description='Download the HSTS preload list', category='bootstrap') From 244a33297639919d8e1aa016bc137242a1ca7146 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Mon, 25 Jun 2018 12:30:24 +0200 Subject: [PATCH 04/30] Use more recent Android tools The older version seems to insist on updating itself when asked to install other components. --- python/servo/bootstrap_commands.py | 61 ++++++++++++++++-------------- 1 file changed, 32 insertions(+), 29 deletions(-) diff --git a/python/servo/bootstrap_commands.py b/python/servo/bootstrap_commands.py index 149ed15be49e..371f6c2e0ea7 100644 --- a/python/servo/bootstrap_commands.py +++ b/python/servo/bootstrap_commands.py @@ -29,7 +29,7 @@ import servo.bootstrap as bootstrap from servo.command_base import CommandBase, cd, check_call -from servo.util import delete, download_bytes, download_file, check_hash, extract +from servo.util import delete, download_bytes, download_file, extract @CommandProvider @@ -58,36 +58,36 @@ def bootstrap(self, force=False): @Command('bootstrap-android', description='Install the Android SDK and NDK.', category='bootstrap') - def bootstrap_android(self): + @CommandArgument('--update', + action='store_true', + help='Run "android sdk update" again') + def bootstrap_android(self, update=False): - ndk_version = "r12b" - ndk_sha512 = "2d85b476436ca50896e4b7c5d0f15547fd14a6ebec7e0081022b28f791709af7" \ - "8ea5ebddcdf4722b5e94daeac288d509bd5f240b0280167edef8e199da3d0501" + # Available filenames: see https://dl.google.com/android/repository/repository2-1.xml + ndk = "android-ndk-r12b-{system}-{arch}" + tools = "sdk-tools-{system}-4333796" - sdk_version = "r25.2.3" - sdk_sha512 = "dfc30ee3e2714cf8008ab1f99757deded002d21b23a8d2ab07952e1afd1c9312" \ - "4ddec06660babf6a46c54e5e7e135c8c0cb4cc512378a8509da074dbf7e253d7" - sdk_platform = "25" + api_level = "25" sdk_build_tools = "25.0.2" + system_image = "google_apis;armeabi-v7a" + + toolchains = path.join(self.context.topdir, "android-toolchains") + if not path.isdir(toolchains): + os.makedirs(toolchains) - def download(kind, name, sha512): - toolchains = path.join(self.context.topdir, "android-toolchains") - directory = path.join(toolchains, kind) - final = path.join(directory, name) + def download(name): + final = path.join(toolchains, name) if path.isdir(final): return final base_url = "https://dl.google.com/android/repository/" filename = name + ".zip" url = base_url + filename - archive = path.join(directory, filename) + archive = path.join(toolchains, filename) - if not path.isdir(directory): - os.makedirs(directory) if not path.isfile(archive): download_file(filename, url, archive) - check_hash(archive, sha512, "sha512") print("Extracting " + filename) remove = True # Set to False to avoid repeated downloads while debugging this script extract(archive, final, remove=remove) @@ -95,26 +95,29 @@ def download(kind, name, sha512): system = platform.system().lower() machine = platform.machine().lower() - os_ = {"darwin": "macosx"}.get(system, system) arch = {"i386": "x86"}.get(machine, machine) - ndk = download("ndk", "android-ndk-%s-%s-%s" % (ndk_version, system, arch), ndk_sha512) - sdk = download("sdk", "tools_%s-%s" % (sdk_version, os_), sdk_sha512) + ndk_path = download(ndk.format(system=system, arch=arch)) + tools_path = download(tools.format(system=system)) - if not path.isdir(path.join(sdk, "platform-tools")): + if update or not path.isdir(path.join(tools_path, "platform-tools")): + image = "system-images;android-%s;%s" % (api_level, system_image) subprocess.check_call([ - path.join(sdk, "tools", "android"), - "update", "sdk", "--no-ui", "--all", "--filter", - "platform-tools,android-%s,build-tools-%s" % (sdk_platform, sdk_build_tools), + path.join(tools_path, "tools", "bin", "sdkmanager"), + "platform-tools", + "platforms;android-" + api_level, + "build-tools;" + sdk_build_tools, + "emulator", + image, ]) - contents = os.listdir(ndk) + contents = os.listdir(ndk_path) assert len(contents) == 1 - ndk = path.join(ndk, contents[0]) + ndk_path = path.join(ndk_path, contents[0]) print("") - print("export ANDROID_SDK=\"%s\"" % sdk) - print("export ANDROID_NDK=\"%s\"" % ndk) - print("export PATH=\"%s:$PATH\"" % path.join(sdk, "platform-tools")) + print("export ANDROID_SDK=\"%s\"" % tools_path) + print("export ANDROID_NDK=\"%s\"" % ndk_path) + print("export PATH=\"%s:$PATH\"" % path.join(tools_path, "platform-tools")) @Command('update-hsts-preload', description='Download the HSTS preload list', From 1ee54ab5fb4ba6de80174b65d2e3cf335c33611c Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Mon, 25 Jun 2018 12:31:23 +0200 Subject: [PATCH 05/30] Create and Android virtual device --- python/servo/bootstrap_commands.py | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/python/servo/bootstrap_commands.py b/python/servo/bootstrap_commands.py index 371f6c2e0ea7..51ed2cd542c7 100644 --- a/python/servo/bootstrap_commands.py +++ b/python/servo/bootstrap_commands.py @@ -70,6 +70,7 @@ def bootstrap_android(self, update=False): api_level = "25" sdk_build_tools = "25.0.2" system_image = "google_apis;armeabi-v7a" + avd_name = "servo-armv7" toolchains = path.join(self.context.topdir, "android-toolchains") @@ -109,6 +110,14 @@ def download(name): "emulator", image, ]) + subprocess.check_call([ + path.join(tools_path, "tools", "bin", "avdmanager"), + "create", "avd", + "--path", path.join(toolchains, "avd", avd_name), + "--name", avd_name, + "--package", image, + "--force", + ]) contents = os.listdir(ndk_path) assert len(contents) == 1 From 888974240705670db18e4e4acab4ec53b57f8a9f Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Mon, 25 Jun 2018 18:48:20 +0200 Subject: [PATCH 06/30] mach bootstrap-android: configure and show how to start an emulator --- python/servo/bootstrap_commands.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/python/servo/bootstrap_commands.py b/python/servo/bootstrap_commands.py index 51ed2cd542c7..eadebb837ce7 100644 --- a/python/servo/bootstrap_commands.py +++ b/python/servo/bootstrap_commands.py @@ -118,6 +118,8 @@ def download(name): "--package", image, "--force", ]) + with open(path.join(toolchains, "avd", avd_name, "config.ini"), "a") as f: + f.write("disk.dataPartition.size=1G\n") contents = os.listdir(ndk_path) assert len(contents) == 1 @@ -127,6 +129,10 @@ def download(name): print("export ANDROID_SDK=\"%s\"" % tools_path) print("export ANDROID_NDK=\"%s\"" % ndk_path) print("export PATH=\"%s:$PATH\"" % path.join(tools_path, "platform-tools")) + print("") + # https://developer.android.com/studio/run/emulator-acceleration#command-gpu + print(path.join(tools_path, "tools", "emulator") + + " @servo-armv7 -gpu swiftshader_indirect [ -no-window ]") @Command('update-hsts-preload', description='Download the HSTS preload list', From fe24816d12f348b5328386557d3e67b896ec2f4d Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Mon, 25 Jun 2018 18:49:32 +0200 Subject: [PATCH 07/30] mach run --android: show PID --- python/servo/post_build_commands.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/python/servo/post_build_commands.py b/python/servo/post_build_commands.py index 4cca8f80a208..2705fda10fa2 100644 --- a/python/servo/post_build_commands.py +++ b/python/servo/post_build_commands.py @@ -91,6 +91,8 @@ def run(self, params, release=False, dev=False, android=None, debug=False, debug ] script += [ "am start com.mozilla.servo/com.mozilla.servo.MainActivity", + "sleep 0.5", + "echo Servo PID: $(pidof com.mozilla.servo)", "exit" ] shell = subprocess.Popen([self.android_adb_path(env), "shell"], stdin=subprocess.PIPE) From 4cbf3dea054469c03551b19afc8a819dc52a453e Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Mon, 25 Jun 2018 18:50:15 +0200 Subject: [PATCH 08/30] mach {package,install} --android: add --emulator and --usb --- python/servo/package_commands.py | 18 ++++++++++++++++-- python/servo/post_build_commands.py | 18 ++++++++++++++++-- 2 files changed, 32 insertions(+), 4 deletions(-) diff --git a/python/servo/package_commands.py b/python/servo/package_commands.py index 5f0e3494279d..296f25cd00eb 100644 --- a/python/servo/package_commands.py +++ b/python/servo/package_commands.py @@ -389,10 +389,16 @@ def package(self, release=False, dev=False, android=None, debug=False, debugger= @CommandArgument('--android', action='store_true', help='Install on Android') + @CommandArgument('--emulator', + action='store_true', + help='For Android, intall to the only emulated device') + @CommandArgument('--usb', + action='store_true', + help='For Android, intall to the only USB device') @CommandArgument('--target', '-t', default=None, help='Install the given target platform') - def install(self, release=False, dev=False, android=False, target=None): + def install(self, release=False, dev=False, android=False, emulator=False, usb=False, target=None): env = self.build_env() if target and android: print("Please specify either --target or --android.") @@ -416,7 +422,15 @@ def install(self, release=False, dev=False, android=False, target=None): if android: pkg_path = binary_path + ".apk" - exec_command = [self.android_adb_path(env), "install", "-r", pkg_path] + exec_command = [self.android_adb_path(env)] + if emulator and usb: + print("Cannot install to both emulator and USB at the same time.") + return 1 + if emulator: + exec_command += ["-e"] + if usb: + exec_command += ["-d"] + exec_command += ["install", "-r", pkg_path] elif is_windows(): pkg_path = path.join(path.dirname(binary_path), 'msi', 'Servo.msi') exec_command = ["msiexec", "/i", pkg_path] diff --git a/python/servo/post_build_commands.py b/python/servo/post_build_commands.py index 2705fda10fa2..d89a8af458ab 100644 --- a/python/servo/post_build_commands.py +++ b/python/servo/post_build_commands.py @@ -45,6 +45,12 @@ class PostBuildCommands(CommandBase): help='Run the dev build') @CommandArgument('--android', action='store_true', default=None, help='Run on an Android device through `adb shell`') + @CommandArgument('--emulator', + action='store_true', + help='For Android, intall to the only emulated device') + @CommandArgument('--usb', + action='store_true', + help='For Android, intall to the only USB device') @CommandArgument('--debug', action='store_true', help='Enable the debugger. Not specifying a ' '--debugger option will result in the default ' @@ -64,7 +70,7 @@ class PostBuildCommands(CommandBase): 'params', nargs='...', help="Command-line arguments to be passed through to Servo") def run(self, params, release=False, dev=False, android=None, debug=False, debugger=None, - headless=False, software=False, bin=None, nightly=None): + headless=False, software=False, bin=None, emulator=False, usb=False, nightly=None): env = self.build_env() env["RUST_BACKTRACE"] = "1" @@ -95,7 +101,15 @@ def run(self, params, release=False, dev=False, android=None, debug=False, debug "echo Servo PID: $(pidof com.mozilla.servo)", "exit" ] - shell = subprocess.Popen([self.android_adb_path(env), "shell"], stdin=subprocess.PIPE) + args = [self.android_adb_path(env)] + if emulator and usb: + print("Cannot install to both emulator and USB at the same time.") + return 1 + if emulator: + args += ["-e"] + if usb: + args += ["-d"] + shell = subprocess.Popen(args + ["shell"], stdin=subprocess.PIPE) shell.communicate("\n".join(script) + "\n") return shell.wait() From eab971cba14654fa19494b1ded8848b3854e1aed Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Mon, 25 Jun 2018 19:12:26 +0200 Subject: [PATCH 09/30] Android cross-compiled command line hello world MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `cargo run` Just Works® --- .gitignore | 1 + Cargo.toml | 2 +- support/android/egl-configs/.cargo/config | 6 ++++++ support/android/egl-configs/Cargo.lock | 4 ++++ support/android/egl-configs/Cargo.toml | 3 +++ support/android/egl-configs/ld.sh | 6 ++++++ support/android/egl-configs/run.sh | 10 ++++++++++ support/android/egl-configs/src/main.rs | 6 ++++++ 8 files changed, 37 insertions(+), 1 deletion(-) create mode 100644 support/android/egl-configs/.cargo/config create mode 100644 support/android/egl-configs/Cargo.lock create mode 100644 support/android/egl-configs/Cargo.toml create mode 100755 support/android/egl-configs/ld.sh create mode 100755 support/android/egl-configs/run.sh create mode 100644 support/android/egl-configs/src/main.rs diff --git a/.gitignore b/.gitignore index 94acd5b1d033..a1b982002afd 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,7 @@ /.servobuild /android-toolchains /target +/support/android/egl-configs/target /ports/android/bin /ports/android/libs /ports/android/local.properties diff --git a/Cargo.toml b/Cargo.toml index 4f107203f283..7fe866b06a42 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,7 +7,7 @@ default-members = [ "ports/servo", "tests/unit/*", ] -exclude = [".cargo"] +exclude = [".cargo", "support/android/egl-configs"] [profile.release] opt-level = 3 diff --git a/support/android/egl-configs/.cargo/config b/support/android/egl-configs/.cargo/config new file mode 100644 index 000000000000..1f0c80724a2d --- /dev/null +++ b/support/android/egl-configs/.cargo/config @@ -0,0 +1,6 @@ +[build] +target = "armv7-linux-androideabi" + +[target.armv7-linux-androideabi] +linker = "./ld.sh" +runner = "./run.sh" diff --git a/support/android/egl-configs/Cargo.lock b/support/android/egl-configs/Cargo.lock new file mode 100644 index 000000000000..cc9c0e8b6fb0 --- /dev/null +++ b/support/android/egl-configs/Cargo.lock @@ -0,0 +1,4 @@ +[[package]] +name = "egl-configs" +version = "0.1.0" + diff --git a/support/android/egl-configs/Cargo.toml b/support/android/egl-configs/Cargo.toml new file mode 100644 index 000000000000..9ff8eca7a40b --- /dev/null +++ b/support/android/egl-configs/Cargo.toml @@ -0,0 +1,3 @@ +[package] +name = "egl-configs" +version = "0.1.0" diff --git a/support/android/egl-configs/ld.sh b/support/android/egl-configs/ld.sh new file mode 100755 index 000000000000..98d61a1dc88c --- /dev/null +++ b/support/android/egl-configs/ld.sh @@ -0,0 +1,6 @@ +#!/bin/sh +NDK=../../../android-toolchains/android-ndk-r12b-linux-x86_64/android-ndk-r12b + +"${NDK}/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin/arm-linux-androideabi-gcc" \ + --sysroot "${NDK}/platforms/android-18/arch-arm" \ + "$@" diff --git a/support/android/egl-configs/run.sh b/support/android/egl-configs/run.sh new file mode 100755 index 000000000000..df59214af77b --- /dev/null +++ b/support/android/egl-configs/run.sh @@ -0,0 +1,10 @@ +#!/bin/sh + +path="$1" +base="$(basename $1)" +remote_path="/data/local/tmp/$base" +shift + +adb -e wait-for-device +adb -e push "$path" "$remote_path" +adb -e shell "$remote_path" "$@" diff --git a/support/android/egl-configs/src/main.rs b/support/android/egl-configs/src/main.rs new file mode 100644 index 000000000000..997012da1a51 --- /dev/null +++ b/support/android/egl-configs/src/main.rs @@ -0,0 +1,6 @@ +fn main() { + println!("Hello, world!"); + for arg in std::env::args() { + println!("{}", arg); + } +} From 90ba22b8d2577de467ef22479a4abcc6a03fe09b Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Mon, 25 Jun 2018 19:52:34 +0200 Subject: [PATCH 10/30] egl-configs: link to EGL and generate bindings --- support/android/egl-configs/Cargo.lock | 51 +++++++++++++++++++++++++ support/android/egl-configs/Cargo.toml | 3 ++ support/android/egl-configs/build.rs | 16 ++++++++ support/android/egl-configs/src/ffi.rs | 21 ++++++++++ support/android/egl-configs/src/main.rs | 12 ++++-- 5 files changed, 100 insertions(+), 3 deletions(-) create mode 100644 support/android/egl-configs/build.rs create mode 100644 support/android/egl-configs/src/ffi.rs diff --git a/support/android/egl-configs/Cargo.lock b/support/android/egl-configs/Cargo.lock index cc9c0e8b6fb0..1f846687f054 100644 --- a/support/android/egl-configs/Cargo.lock +++ b/support/android/egl-configs/Cargo.lock @@ -1,4 +1,55 @@ +[[package]] +name = "bitflags" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "cfg-if" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "egl-configs" version = "0.1.0" +dependencies = [ + "gl_generator 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "gl_generator" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "khronos_api 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", + "xml-rs 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "khronos_api" +version = "2.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "log" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "cfg-if 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "xml-rs" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", +] +[metadata] +"checksum bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d0c54bb8f454c567f21197eefcdbf5679d0bd99f2ddbe52e84c77061952e6789" +"checksum cfg-if 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "405216fd8fe65f718daa7102ea808a946b6ce40c742998fbfd3463645552de18" +"checksum gl_generator 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a795170cbd85b5a7baa58d6d7525cae6a03e486859860c220f7ebbbdd379d0a" +"checksum khronos_api 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "037ab472c33f67b5fbd3e9163a2645319e5356fcd355efa6d4eb7fff4bbcb554" +"checksum log 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6fddaa003a65722a7fb9e26b0ce95921fe4ba590542ced664d8ce2fa26f9f3ac" +"checksum xml-rs 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3c1cb601d29fe2c2ac60a2b2e5e293994d87a1f6fa9687a31a15270f909be9c2" diff --git a/support/android/egl-configs/Cargo.toml b/support/android/egl-configs/Cargo.toml index 9ff8eca7a40b..9ce73a900f5f 100644 --- a/support/android/egl-configs/Cargo.toml +++ b/support/android/egl-configs/Cargo.toml @@ -1,3 +1,6 @@ [package] name = "egl-configs" version = "0.1.0" + +[build-dependencies] +gl_generator = "0.9" diff --git a/support/android/egl-configs/build.rs b/support/android/egl-configs/build.rs new file mode 100644 index 000000000000..8c0e589607cd --- /dev/null +++ b/support/android/egl-configs/build.rs @@ -0,0 +1,16 @@ +extern crate gl_generator; + +use gl_generator::{Registry, Api, Profile, Fallbacks}; +use std::env; +use std::fs::File; +use std::path::PathBuf; + +fn main() { + let out_dir = PathBuf::from(&env::var("OUT_DIR").unwrap()); + let mut file = File::create(&out_dir.join("egl_bindings.rs")).unwrap(); + Registry::new(Api::Egl, (1, 5), Profile::Core, Fallbacks::All, [ + "EGL_KHR_create_context", + "EGL_KHR_platform_android", + ]) + .write_bindings(gl_generator::StaticGenerator, &mut file).unwrap(); +} diff --git a/support/android/egl-configs/src/ffi.rs b/support/android/egl-configs/src/ffi.rs new file mode 100644 index 000000000000..ce106bb0a941 --- /dev/null +++ b/support/android/egl-configs/src/ffi.rs @@ -0,0 +1,21 @@ +#![allow(non_camel_case_types)] + +use std::os::raw::*; + +pub type NativeDisplayType = *const c_void; +pub type NativePixmapType = *const c_void; +pub type NativeWindowType = *const c_void; + +pub type EGLNativeDisplayType = NativeDisplayType; +pub type EGLNativePixmapType = NativePixmapType; +pub type EGLNativeWindowType = NativeWindowType; + +pub type khronos_utime_nanoseconds_t = khronos_uint64_t; +pub type khronos_uint64_t = u64; +pub type khronos_ssize_t = c_long; +pub type EGLint = i32; + +#[link(name = "EGL")] +extern "C" {} + +include!(concat!(env!("OUT_DIR"), "/egl_bindings.rs")); diff --git a/support/android/egl-configs/src/main.rs b/support/android/egl-configs/src/main.rs index 997012da1a51..d04fc204b1c9 100644 --- a/support/android/egl-configs/src/main.rs +++ b/support/android/egl-configs/src/main.rs @@ -1,6 +1,12 @@ +mod ffi; +use ffi::*; + fn main() { - println!("Hello, world!"); - for arg in std::env::args() { - println!("{}", arg); + unsafe { + run() } } + +unsafe fn run() { + let _display = GetDisplay(DEFAULT_DISPLAY as *mut _); +} From 89f6c6dbf0b88654b8b23ef5df9998e3d2d4c6c8 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Mon, 25 Jun 2018 21:14:19 +0200 Subject: [PATCH 11/30] egl-configs: get the number of configs --- support/android/egl-configs/src/main.rs | 32 +++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/support/android/egl-configs/src/main.rs b/support/android/egl-configs/src/main.rs index d04fc204b1c9..d091a28d6065 100644 --- a/support/android/egl-configs/src/main.rs +++ b/support/android/egl-configs/src/main.rs @@ -1,5 +1,8 @@ -mod ffi; use ffi::*; +use ffi::types::*; +use std::ptr::null_mut; + +mod ffi; fn main() { unsafe { @@ -7,6 +10,31 @@ fn main() { } } +macro_rules! check { + ($name: ident ( $($arg: expr),* )) => { + check($name( $($arg),* ), stringify!($name)) + } +} + unsafe fn run() { - let _display = GetDisplay(DEFAULT_DISPLAY as *mut _); + let display = GetDisplay(DEFAULT_DISPLAY as *mut _); + assert!(!display.is_null()); + + check!(Initialize(display, null_mut(), null_mut())); + + let mut num_config = -1; + check!(GetConfigs(display, null_mut(), 0, &mut num_config)); + println!("Got {} configs", num_config); +} + +unsafe fn check(result: EGLBoolean, function_name: &str) { + check_error(); + assert_eq!(result, TRUE, "{} failed", function_name); +} + +unsafe fn check_error() { + let status = GetError(); + if status != SUCCESS as i32 { + println!("Error: 0x{:x}", status); + } } From 7e7316e76629aa57fb7316540b65d1877c53541d Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Mon, 25 Jun 2018 21:38:55 +0200 Subject: [PATCH 12/30] egl-configs: print all config attributes --- support/android/egl-configs/src/main.rs | 58 ++++++++++++++++++++++++- 1 file changed, 57 insertions(+), 1 deletion(-) diff --git a/support/android/egl-configs/src/main.rs b/support/android/egl-configs/src/main.rs index d091a28d6065..5963f18a5e2a 100644 --- a/support/android/egl-configs/src/main.rs +++ b/support/android/egl-configs/src/main.rs @@ -25,6 +25,62 @@ unsafe fn run() { let mut num_config = -1; check!(GetConfigs(display, null_mut(), 0, &mut num_config)); println!("Got {} configs", num_config); + assert!(num_config >= 0); + + let mut configs = Vec::with_capacity(num_config as usize); + let mut num_config2 = -1; + check!(GetConfigs(display, configs.as_mut_ptr(), num_config, &mut num_config2)); + assert_eq!(num_config, num_config2); + configs.set_len(num_config as usize); + + for (i, &config) in configs.iter().enumerate() { + println!("Config #{}", i + 1); + + macro_rules! to_pairs { + ($($name: ident)*) => { + &[ $( (stringify!($name), $name) ),* ] + } + } + // https://www.khronos.org/registry/EGL/sdk/docs/man/html/eglGetConfigAttrib.xhtml#description + for &(attr_name, attr) in to_pairs! [ + ALPHA_SIZE + ALPHA_MASK_SIZE + BIND_TO_TEXTURE_RGB + BIND_TO_TEXTURE_RGBA + BLUE_SIZE + BUFFER_SIZE + COLOR_BUFFER_TYPE + CONFIG_CAVEAT + CONFIG_ID + CONFORMANT + DEPTH_SIZE + GREEN_SIZE + LEVEL + LUMINANCE_SIZE + MAX_PBUFFER_WIDTH + MAX_PBUFFER_HEIGHT + MAX_PBUFFER_PIXELS + MAX_SWAP_INTERVAL + MIN_SWAP_INTERVAL + NATIVE_RENDERABLE + NATIVE_VISUAL_ID + NATIVE_VISUAL_TYPE + RED_SIZE + RENDERABLE_TYPE + SAMPLE_BUFFERS + SAMPLES + STENCIL_SIZE + SURFACE_TYPE + TRANSPARENT_TYPE + TRANSPARENT_RED_VALUE + TRANSPARENT_GREEN_VALUE + TRANSPARENT_BLUE_VALUE + ] { + let mut value = -1; + check!(GetConfigAttrib(display, config, attr as i32, &mut value)); + println!(" {} = {}", attr_name, value) + } + } } unsafe fn check(result: EGLBoolean, function_name: &str) { @@ -35,6 +91,6 @@ unsafe fn check(result: EGLBoolean, function_name: &str) { unsafe fn check_error() { let status = GetError(); if status != SUCCESS as i32 { - println!("Error: 0x{:x}", status); + panic!("Error: 0x{:x}", status); } } From 1f8d04b8e1d25e57d5ee77b8325fcd25227d6cff Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Mon, 25 Jun 2018 22:16:51 +0200 Subject: [PATCH 13/30] egl-configs: print hex too --- support/android/egl-configs/src/main.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/support/android/egl-configs/src/main.rs b/support/android/egl-configs/src/main.rs index 5963f18a5e2a..5fada2458ee7 100644 --- a/support/android/egl-configs/src/main.rs +++ b/support/android/egl-configs/src/main.rs @@ -78,7 +78,11 @@ unsafe fn run() { ] { let mut value = -1; check!(GetConfigAttrib(display, config, attr as i32, &mut value)); - println!(" {} = {}", attr_name, value) + if value < 10 { + println!(" {}\t = {}", attr_name, value) + } else { + println!(" {}\t= {} = 0x{:x}", attr_name, value, value) + } } } } From 6e6870516e38ce7d9be785ef7e3d7711e6d1b55b Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Mon, 25 Jun 2018 22:17:05 +0200 Subject: [PATCH 14/30] cargo run into Android/adb: configurable target device --- support/android/egl-configs/run.sh | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/support/android/egl-configs/run.sh b/support/android/egl-configs/run.sh index df59214af77b..3842b4bb3728 100755 --- a/support/android/egl-configs/run.sh +++ b/support/android/egl-configs/run.sh @@ -1,10 +1,22 @@ #!/bin/sh +# Any +#target="" + +# Specific device +#target="-s something" + +# Emulator +target="-e" + +# USB +#target="-d" + path="$1" base="$(basename $1)" remote_path="/data/local/tmp/$base" shift -adb -e wait-for-device -adb -e push "$path" "$remote_path" -adb -e shell "$remote_path" "$@" +adb $target "wait-for-device" +adb $target push "$path" "$remote_path" >&2 +adb $target shell "$remote_path" "$@" From 484eee86248e7eab71fe78dab2c1419a42e61271 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Mon, 25 Jun 2018 23:25:22 +0200 Subject: [PATCH 15/30] Tidy --- python/servo/bootstrap_commands.py | 1 - python/servo/util.py | 3 +++ servo-tidy.toml | 1 + support/android/egl-configs/Cargo.toml | 1 + support/android/egl-configs/build.rs | 4 ++++ support/android/egl-configs/ld.sh | 16 ++++++++++++--- support/android/egl-configs/run.sh | 26 ++++++++++++++++--------- support/android/egl-configs/src/ffi.rs | 4 ++++ support/android/egl-configs/src/main.rs | 8 ++++++-- 9 files changed, 49 insertions(+), 15 deletions(-) diff --git a/python/servo/bootstrap_commands.py b/python/servo/bootstrap_commands.py index eadebb837ce7..dcc278797a23 100644 --- a/python/servo/bootstrap_commands.py +++ b/python/servo/bootstrap_commands.py @@ -72,7 +72,6 @@ def bootstrap_android(self, update=False): system_image = "google_apis;armeabi-v7a" avd_name = "servo-armv7" - toolchains = path.join(self.context.topdir, "android-toolchains") if not path.isdir(toolchains): os.makedirs(toolchains) diff --git a/python/servo/util.py b/python/servo/util.py index 7c4cc5aee1b9..d71cffe27dac 100644 --- a/python/servo/util.py +++ b/python/servo/util.py @@ -153,6 +153,7 @@ def download_file(desc, src, dst): download(desc, src, fd) os.rename(tmp_path, dst) + # https://stackoverflow.com/questions/39296101/python-zipfile-removes-execute-permissions-from-binaries # In particular, we want the executable bit for executable files. class ZipFileWithUnixPermissions(zipfile.ZipFile): @@ -169,6 +170,7 @@ def extract(self, member, path=None, pwd=None): os.chmod(extracted, mode) return extracted + def extract(src, dst, movedir=None, remove=True): assert src.endswith(".zip") ZipFileWithUnixPermissions(src).extractall(dst) @@ -183,6 +185,7 @@ def extract(src, dst, movedir=None, remove=True): if remove: os.remove(src) + def check_hash(filename, expected, algorithm): hasher = hashlib.new(algorithm) with open(filename, "rb") as f: diff --git a/servo-tidy.toml b/servo-tidy.toml index ce69b5a24cce..286a303d3035 100644 --- a/servo-tidy.toml +++ b/servo-tidy.toml @@ -58,6 +58,7 @@ files = [ "./resources/hsts_preload.json", "./tests/wpt/metadata/MANIFEST.json", "./support/android/openssl.sh", + "./support/android/egl-configs/Cargo.lock", # Upstream code from Khronos/WebGL uses tabs for indentation "./tests/wpt/mozilla/tests/webgl", # Ignore those files since the issues reported are on purpose diff --git a/support/android/egl-configs/Cargo.toml b/support/android/egl-configs/Cargo.toml index 9ce73a900f5f..ae5a6f5d3422 100644 --- a/support/android/egl-configs/Cargo.toml +++ b/support/android/egl-configs/Cargo.toml @@ -1,6 +1,7 @@ [package] name = "egl-configs" version = "0.1.0" +license = "MPL-2.0" [build-dependencies] gl_generator = "0.9" diff --git a/support/android/egl-configs/build.rs b/support/android/egl-configs/build.rs index 8c0e589607cd..62558fbafd47 100644 --- a/support/android/egl-configs/build.rs +++ b/support/android/egl-configs/build.rs @@ -1,3 +1,7 @@ +/* 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/. */ + extern crate gl_generator; use gl_generator::{Registry, Api, Profile, Fallbacks}; diff --git a/support/android/egl-configs/ld.sh b/support/android/egl-configs/ld.sh index 98d61a1dc88c..f49c9940c4cd 100755 --- a/support/android/egl-configs/ld.sh +++ b/support/android/egl-configs/ld.sh @@ -1,6 +1,16 @@ -#!/bin/sh +#!/usr/bin/env bash + +# 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/. + +set -o errexit +set -o nounset +set -o pipefail + NDK=../../../android-toolchains/android-ndk-r12b-linux-x86_64/android-ndk-r12b +BIN="${NDK}/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin/" -"${NDK}/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin/arm-linux-androideabi-gcc" \ +"${BIN}/arm-linux-androideabi-gcc" \ --sysroot "${NDK}/platforms/android-18/arch-arm" \ - "$@" + "${@}" diff --git a/support/android/egl-configs/run.sh b/support/android/egl-configs/run.sh index 3842b4bb3728..dfe4a1dbd4e8 100755 --- a/support/android/egl-configs/run.sh +++ b/support/android/egl-configs/run.sh @@ -1,22 +1,30 @@ -#!/bin/sh +#!/usr/bin/env bash + +# 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/. + +set -o errexit +set -o nounset +set -o pipefail # Any -#target="" +target="" # Specific device #target="-s something" # Emulator -target="-e" +#target="-e" # USB #target="-d" -path="$1" -base="$(basename $1)" -remote_path="/data/local/tmp/$base" +path="${1}" +base="$(basename ${1})" +remote_path="/data/local/tmp/${base}" shift -adb $target "wait-for-device" -adb $target push "$path" "$remote_path" >&2 -adb $target shell "$remote_path" "$@" +adb ${target} "wait-for-device" +adb ${target} push "${path}" "${remote_path}" >&2 +adb ${target} shell "${remote_path}" "${@}" diff --git a/support/android/egl-configs/src/ffi.rs b/support/android/egl-configs/src/ffi.rs index ce106bb0a941..ee2b43aebd47 100644 --- a/support/android/egl-configs/src/ffi.rs +++ b/support/android/egl-configs/src/ffi.rs @@ -1,3 +1,7 @@ +/* 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/. */ + #![allow(non_camel_case_types)] use std::os::raw::*; diff --git a/support/android/egl-configs/src/main.rs b/support/android/egl-configs/src/main.rs index 5fada2458ee7..eb7a4388263d 100644 --- a/support/android/egl-configs/src/main.rs +++ b/support/android/egl-configs/src/main.rs @@ -1,3 +1,7 @@ +/* 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/. */ + use ffi::*; use ffi::types::*; use std::ptr::null_mut; @@ -11,8 +15,8 @@ fn main() { } macro_rules! check { - ($name: ident ( $($arg: expr),* )) => { - check($name( $($arg),* ), stringify!($name)) + ($name: ident($($arg: expr),*)) => { + check($name($($arg),*), stringify!($name)) } } From 3c992af8a1c3265d20930b119859b77d0cf16962 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Tue, 26 Jun 2018 14:10:10 +0200 Subject: [PATCH 16/30] Remove debugging println from a year ago --- components/gfx/platform/freetype/android/font_list.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/components/gfx/platform/freetype/android/font_list.rs b/components/gfx/platform/freetype/android/font_list.rs index e26e6c84e60b..3c52e854112b 100644 --- a/components/gfx/platform/freetype/android/font_list.rs +++ b/components/gfx/platform/freetype/android/font_list.rs @@ -436,7 +436,6 @@ pub fn for_each_available_family(mut callback: F) where F: FnMut(String) { pub fn for_each_variation(family_name: &str, mut callback: F) where F: FnMut(String) { - println!("Variatioooon {:?}", family_name); if let Some(family) = FONT_LIST.find_family(family_name) { for font in &family.fonts { callback(FontList::font_absolute_path(&font.filename)); From 7d7f2025b7bf4c42dfa085ae34fba9f80b4e40a7 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Tue, 26 Jun 2018 19:12:35 +0200 Subject: [PATCH 17/30] Fix copy/paste mistake --- python/servo/post_build_commands.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/servo/post_build_commands.py b/python/servo/post_build_commands.py index d89a8af458ab..84c927bb8cc1 100644 --- a/python/servo/post_build_commands.py +++ b/python/servo/post_build_commands.py @@ -103,7 +103,7 @@ def run(self, params, release=False, dev=False, android=None, debug=False, debug ] args = [self.android_adb_path(env)] if emulator and usb: - print("Cannot install to both emulator and USB at the same time.") + print("Cannot run in both emulator and USB at the same time.") return 1 if emulator: args += ["-e"] From b7a8b81071e91fa466d40f6060197d495e55d5f5 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Tue, 26 Jun 2018 19:13:01 +0200 Subject: [PATCH 18/30] egl-configs: add i686 support --- support/android/egl-configs/.cargo/config | 6 +++++- support/android/egl-configs/ld-i686.sh | 16 ++++++++++++++++ 2 files changed, 21 insertions(+), 1 deletion(-) create mode 100755 support/android/egl-configs/ld-i686.sh diff --git a/support/android/egl-configs/.cargo/config b/support/android/egl-configs/.cargo/config index 1f0c80724a2d..800226ab1083 100644 --- a/support/android/egl-configs/.cargo/config +++ b/support/android/egl-configs/.cargo/config @@ -1,6 +1,10 @@ [build] -target = "armv7-linux-androideabi" +target = "i686-linux-android" [target.armv7-linux-androideabi] linker = "./ld.sh" runner = "./run.sh" + +[target.i686-linux-android] +linker = "./ld-i686.sh" +runner = "./run.sh" diff --git a/support/android/egl-configs/ld-i686.sh b/support/android/egl-configs/ld-i686.sh new file mode 100755 index 000000000000..37b1dadd64e6 --- /dev/null +++ b/support/android/egl-configs/ld-i686.sh @@ -0,0 +1,16 @@ +#!/usr/bin/env bash + +# 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/. + +set -o errexit +set -o nounset +set -o pipefail + +NDK=../../../android-toolchains/android-ndk-r12b-linux-x86_64/android-ndk-r12b +BIN="${NDK}/toolchains/x86-4.9/prebuilt/linux-x86_64/bin/" + +"${BIN}/i686-linux-android-gcc" \ + --sysroot "${NDK}/platforms/android-18/arch-x86" \ + "${@}" From f4d740f08664c3800a8044279dcc41c6c69d8bcd Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Wed, 27 Jun 2018 11:59:45 +0200 Subject: [PATCH 19/30] Typo fixes --- python/servo/package_commands.py | 4 ++-- python/servo/post_build_commands.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/python/servo/package_commands.py b/python/servo/package_commands.py index 296f25cd00eb..03c2390e3080 100644 --- a/python/servo/package_commands.py +++ b/python/servo/package_commands.py @@ -391,10 +391,10 @@ def package(self, release=False, dev=False, android=None, debug=False, debugger= help='Install on Android') @CommandArgument('--emulator', action='store_true', - help='For Android, intall to the only emulated device') + help='For Android, install to the only emulated device') @CommandArgument('--usb', action='store_true', - help='For Android, intall to the only USB device') + help='For Android, install to the only USB device') @CommandArgument('--target', '-t', default=None, help='Install the given target platform') diff --git a/python/servo/post_build_commands.py b/python/servo/post_build_commands.py index 84c927bb8cc1..f99de244e781 100644 --- a/python/servo/post_build_commands.py +++ b/python/servo/post_build_commands.py @@ -47,10 +47,10 @@ class PostBuildCommands(CommandBase): help='Run on an Android device through `adb shell`') @CommandArgument('--emulator', action='store_true', - help='For Android, intall to the only emulated device') + help='For Android, run in the only emulated device') @CommandArgument('--usb', action='store_true', - help='For Android, intall to the only USB device') + help='For Android, run in the only USB device') @CommandArgument('--debug', action='store_true', help='Enable the debugger. Not specifying a ' '--debugger option will result in the default ' From e54ad7759432c35d44bc6f6a7fb4a948269c540f Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Thu, 28 Jun 2018 15:48:25 +0200 Subject: [PATCH 20/30] Do not prompt for Android emulator hardware profile --- python/servo/bootstrap_commands.py | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/python/servo/bootstrap_commands.py b/python/servo/bootstrap_commands.py index dcc278797a23..973d89d76325 100644 --- a/python/servo/bootstrap_commands.py +++ b/python/servo/bootstrap_commands.py @@ -109,14 +109,17 @@ def download(name): "emulator", image, ]) - subprocess.check_call([ - path.join(tools_path, "tools", "bin", "avdmanager"), - "create", "avd", - "--path", path.join(toolchains, "avd", avd_name), - "--name", avd_name, - "--package", image, - "--force", - ]) + subprocess.Popen( + stdin=subprocess.PIPE, args=[ + path.join(tools_path, "tools", "bin", "avdmanager"), + "create", "avd", + "--path", path.join(toolchains, "avd", avd_name), + "--name", avd_name, + "--package", image, + "--force", + ] + # This command always prompts "Do you wish to create a custom hardware profile?" + ).communicate("no\n") with open(path.join(toolchains, "avd", avd_name, "config.ini"), "a") as f: f.write("disk.dataPartition.size=1G\n") @@ -124,6 +127,7 @@ def download(name): assert len(contents) == 1 ndk_path = path.join(ndk_path, contents[0]) + print("") print("") print("export ANDROID_SDK=\"%s\"" % tools_path) print("export ANDROID_NDK=\"%s\"" % ndk_path) From 0e2e9cb019e73abcabe7907c4890c6bd96b9b607 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Thu, 28 Jun 2018 16:02:02 +0200 Subject: [PATCH 21/30] Create emulator images for both ARM and x86 --- python/servo/bootstrap_commands.py | 49 ++++++++++++++++++++---------- 1 file changed, 33 insertions(+), 16 deletions(-) diff --git a/python/servo/bootstrap_commands.py b/python/servo/bootstrap_commands.py index 973d89d76325..950dc3f02139 100644 --- a/python/servo/bootstrap_commands.py +++ b/python/servo/bootstrap_commands.py @@ -60,17 +60,18 @@ def bootstrap(self, force=False): category='bootstrap') @CommandArgument('--update', action='store_true', - help='Run "android sdk update" again') + help='Run SDK component install and emulator image creation again') def bootstrap_android(self, update=False): # Available filenames: see https://dl.google.com/android/repository/repository2-1.xml ndk = "android-ndk-r12b-{system}-{arch}" tools = "sdk-tools-{system}-4333796" - api_level = "25" sdk_build_tools = "25.0.2" - system_image = "google_apis;armeabi-v7a" - avd_name = "servo-armv7" + emulator_images = [ + ("servo-armv7", "25", "google_apis;armeabi-v7a"), + ("servo-x86", "28", "google_apis;x86"), + ] toolchains = path.join(self.context.topdir, "android-toolchains") if not path.isdir(toolchains): @@ -100,34 +101,50 @@ def download(name): tools_path = download(tools.format(system=system)) if update or not path.isdir(path.join(tools_path, "platform-tools")): - image = "system-images;android-%s;%s" % (api_level, system_image) subprocess.check_call([ path.join(tools_path, "tools", "bin", "sdkmanager"), "platform-tools", - "platforms;android-" + api_level, "build-tools;" + sdk_build_tools, "emulator", - image, + ] + [ + 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), + ] ]) - subprocess.Popen( - stdin=subprocess.PIPE, args=[ + for avd_name, api_level, system_image in emulator_images: + process = subprocess.Popen(stdin=subprocess.PIPE, stdout=subprocess.PIPE, args=[ path.join(tools_path, "tools", "bin", "avdmanager"), "create", "avd", "--path", path.join(toolchains, "avd", avd_name), "--name", avd_name, - "--package", image, + "--package", "system-images;android-%s;%s" % (api_level, system_image), "--force", - ] - # This command always prompts "Do you wish to create a custom hardware profile?" - ).communicate("no\n") - with open(path.join(toolchains, "avd", avd_name, "config.ini"), "a") as f: - f.write("disk.dataPartition.size=1G\n") + ]) + 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=1G\n") contents = os.listdir(ndk_path) assert len(contents) == 1 ndk_path = path.join(ndk_path, contents[0]) - print("") print("") print("export ANDROID_SDK=\"%s\"" % tools_path) print("export ANDROID_NDK=\"%s\"" % ndk_path) From aa1c3cea2fbf8c0907bda54ac4183d7fc878b33e Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Thu, 28 Jun 2018 16:21:09 +0200 Subject: [PATCH 22/30] bootstrap-android: use predictable paths for SDK and NDK MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit … independent of the version number --- python/servo/bootstrap_commands.py | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/python/servo/bootstrap_commands.py b/python/servo/bootstrap_commands.py index 950dc3f02139..da887830a98b 100644 --- a/python/servo/bootstrap_commands.py +++ b/python/servo/bootstrap_commands.py @@ -77,8 +77,8 @@ def bootstrap_android(self, update=False): if not path.isdir(toolchains): os.makedirs(toolchains) - def download(name): - final = path.join(toolchains, name) + def download(name, target_dir, flatten=False): + final = path.join(toolchains, target_dir) if path.isdir(final): return final @@ -90,15 +90,23 @@ def download(name): if not path.isfile(archive): download_file(filename, url, archive) print("Extracting " + filename) - remove = True # Set to False to avoid repeated downloads while debugging this script - extract(archive, final, remove=remove) + remove = False # 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) return final system = platform.system().lower() machine = platform.machine().lower() arch = {"i386": "x86"}.get(machine, machine) - ndk_path = download(ndk.format(system=system, arch=arch)) - tools_path = download(tools.format(system=system)) + ndk_path = download(ndk.format(system=system, arch=arch), "ndk", flatten=True) + tools_path = download(tools.format(system=system), "sdk") if update or not path.isdir(path.join(tools_path, "platform-tools")): subprocess.check_call([ @@ -141,10 +149,6 @@ def download(name): with open(path.join(toolchains, "avd", avd_name, "config.ini"), "a") as f: f.write("disk.dataPartition.size=1G\n") - contents = os.listdir(ndk_path) - assert len(contents) == 1 - ndk_path = path.join(ndk_path, contents[0]) - print("") print("export ANDROID_SDK=\"%s\"" % tools_path) print("export ANDROID_NDK=\"%s\"" % ndk_path) From 65122b10d3d303ec44c5182d48fecea483ce9b5e Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Thu, 28 Jun 2018 16:22:15 +0200 Subject: [PATCH 23/30] bootstrap-android: always run sdkmanager It is quick when already up to date --- python/servo/bootstrap_commands.py | 77 +++++++++++++++--------------- 1 file changed, 38 insertions(+), 39 deletions(-) diff --git a/python/servo/bootstrap_commands.py b/python/servo/bootstrap_commands.py index da887830a98b..2e7791d00c14 100644 --- a/python/servo/bootstrap_commands.py +++ b/python/servo/bootstrap_commands.py @@ -108,46 +108,45 @@ def download(name, target_dir, flatten=False): ndk_path = download(ndk.format(system=system, arch=arch), "ndk", flatten=True) tools_path = download(tools.format(system=system), "sdk") - if update or not path.isdir(path.join(tools_path, "platform-tools")): - subprocess.check_call([ - path.join(tools_path, "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), - ] + subprocess.check_call([ + path.join(tools_path, "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(tools_path, "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", ]) - for avd_name, api_level, system_image in emulator_images: - process = subprocess.Popen(stdin=subprocess.PIPE, stdout=subprocess.PIPE, args=[ - path.join(tools_path, "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=1G\n") + 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=1G\n") print("") print("export ANDROID_SDK=\"%s\"" % tools_path) From fc77db4b09ebd7eae69089f1dc1c95191a4a611a Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Thu, 28 Jun 2018 16:32:46 +0200 Subject: [PATCH 24/30] Use the bootstraped Android toolchains by default --- python/servo/bootstrap_commands.py | 22 ++++++---------------- python/servo/build_commands.py | 4 ++-- python/servo/command_base.py | 10 ++++++++++ 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/python/servo/bootstrap_commands.py b/python/servo/bootstrap_commands.py index 2e7791d00c14..7fa91825a02c 100644 --- a/python/servo/bootstrap_commands.py +++ b/python/servo/bootstrap_commands.py @@ -77,10 +77,10 @@ def bootstrap_android(self, update=False): if not path.isdir(toolchains): os.makedirs(toolchains) - def download(name, target_dir, flatten=False): + def download(target_dir, name, flatten=False): final = path.join(toolchains, target_dir) if path.isdir(final): - return final + return base_url = "https://dl.google.com/android/repository/" filename = name + ".zip" @@ -100,16 +100,15 @@ def download(name, target_dir, flatten=False): os.rmdir(extracted) else: extract(archive, final, remove=remove) - return final system = platform.system().lower() machine = platform.machine().lower() arch = {"i386": "x86"}.get(machine, machine) - ndk_path = download(ndk.format(system=system, arch=arch), "ndk", flatten=True) - tools_path = download(tools.format(system=system), "sdk") + download("ndk", ndk.format(system=system, arch=arch), flatten=True) + download("sdk", tools.format(system=system)) subprocess.check_call([ - path.join(tools_path, "tools", "bin", "sdkmanager"), + path.join(toolchains, "sdk", "tools", "bin", "sdkmanager"), "platform-tools", "build-tools;" + sdk_build_tools, "emulator", @@ -123,7 +122,7 @@ def download(name, target_dir, flatten=False): ]) for avd_name, api_level, system_image in emulator_images: process = subprocess.Popen(stdin=subprocess.PIPE, stdout=subprocess.PIPE, args=[ - path.join(tools_path, "tools", "bin", "avdmanager"), + path.join(toolchains, "sdk", "tools", "bin", "avdmanager"), "create", "avd", "--path", path.join(toolchains, "avd", avd_name), "--name", avd_name, @@ -148,15 +147,6 @@ def download(name, target_dir, flatten=False): with open(path.join(toolchains, "avd", avd_name, "config.ini"), "a") as f: f.write("disk.dataPartition.size=1G\n") - print("") - print("export ANDROID_SDK=\"%s\"" % tools_path) - print("export ANDROID_NDK=\"%s\"" % ndk_path) - print("export PATH=\"%s:$PATH\"" % path.join(tools_path, "platform-tools")) - print("") - # https://developer.android.com/studio/run/emulator-acceleration#command-gpu - print(path.join(tools_path, "tools", "emulator") + - " @servo-armv7 -gpu swiftshader_indirect [ -no-window ]") - @Command('update-hsts-preload', description='Download the HSTS preload list', category='bootstrap') diff --git a/python/servo/build_commands.py b/python/servo/build_commands.py index d48730252b2f..02d71eee8bdf 100644 --- a/python/servo/build_commands.py +++ b/python/servo/build_commands.py @@ -260,10 +260,10 @@ def build(self, target=None, release=False, dev=False, jobs=None, env['RUSTFLAGS'] = env.get('RUSTFLAGS', "") + " -C debug_assertions" if android: - if "ANDROID_NDK" not in os.environ: + if "ANDROID_NDK" not in env: print("Please set the ANDROID_NDK environment variable.") sys.exit(1) - if "ANDROID_SDK" not in os.environ: + if "ANDROID_SDK" not in env: print("Please set the ANDROID_SDK environment variable.") sys.exit(1) diff --git a/python/servo/command_base.py b/python/servo/command_base.py index 8e7a9f4b2dc4..70f19203ec63 100644 --- a/python/servo/command_base.py +++ b/python/servo/command_base.py @@ -525,6 +525,16 @@ def package_dir(package): if self.config["android"]["platform"]: env["ANDROID_PLATFORM"] = self.config["android"]["platform"] + toolchains = path.join(self.context.topdir, "android-toolchains") + for kind in ["sdk", "ndk"]: + default = os.path.join(toolchains, kind) + if os.path.isdir(default): + env.setdefault("ANDROID_" + kind.upper(), default) + + tools = os.path.join(toolchains, "sdk", "platform-tools") + if os.path.isdir(tools): + env["PATH"] = "%s%s%s" % (tools, os.pathsep, env["PATH"]) + # These are set because they are the variable names that build-apk # expects. However, other submodules have makefiles that reference # the env var names above. Once glutin is enabled and set as the From b6b9fe07e2ff55b5bee31e7a9b0a85d31390a762 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Thu, 28 Jun 2018 16:40:07 +0200 Subject: [PATCH 25/30] Add "./mach android-emulator" --- python/servo/bootstrap_commands.py | 2 +- python/servo/post_build_commands.py | 14 ++++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/python/servo/bootstrap_commands.py b/python/servo/bootstrap_commands.py index 7fa91825a02c..3cf7f36a0a79 100644 --- a/python/servo/bootstrap_commands.py +++ b/python/servo/bootstrap_commands.py @@ -69,7 +69,7 @@ def bootstrap_android(self, update=False): sdk_build_tools = "25.0.2" emulator_images = [ - ("servo-armv7", "25", "google_apis;armeabi-v7a"), + ("servo-arm", "25", "google_apis;armeabi-v7a"), ("servo-x86", "28", "google_apis;x86"), ] diff --git a/python/servo/post_build_commands.py b/python/servo/post_build_commands.py index f99de244e781..b5dd211a144a 100644 --- a/python/servo/post_build_commands.py +++ b/python/servo/post_build_commands.py @@ -169,6 +169,20 @@ def run(self, params, release=False, dev=False, android=None, debug=False, debug else: raise e + @Command('android-emulator', + description='Run the Android emulator', + category='post-build') + @CommandArgument( + 'args', nargs='...', + help="Command-line arguments to be passed through to the emulator") + def android_emulator(self, args=None): + if not args: + print("Pass at least an AVD name such as @servo-arm or @servo-x86") + return 1 + env = self.build_env() + emulator = path.join(env["ANDROID_SDK"], "emulator", "emulator") + check_call([emulator] + args) + @Command('rr-record', description='Run Servo whilst recording execution with rr', category='post-build') From 9e544c2aae5d94be562683e216d1b64d888930ff Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Fri, 29 Jun 2018 16:39:30 +0200 Subject: [PATCH 26/30] Remove the egl-configs diagnostic program MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit It has served its purpose. If we ever need it again it’s in git history. --- .gitignore | 1 - Cargo.toml | 2 +- servo-tidy.toml | 1 - support/android/egl-configs/.cargo/config | 10 --- support/android/egl-configs/Cargo.lock | 55 ------------ support/android/egl-configs/Cargo.toml | 7 -- support/android/egl-configs/build.rs | 20 ----- support/android/egl-configs/ld-i686.sh | 16 ---- support/android/egl-configs/ld.sh | 16 ---- support/android/egl-configs/run.sh | 30 ------- support/android/egl-configs/src/ffi.rs | 25 ------ support/android/egl-configs/src/main.rs | 104 ---------------------- 12 files changed, 1 insertion(+), 286 deletions(-) delete mode 100644 support/android/egl-configs/.cargo/config delete mode 100644 support/android/egl-configs/Cargo.lock delete mode 100644 support/android/egl-configs/Cargo.toml delete mode 100644 support/android/egl-configs/build.rs delete mode 100755 support/android/egl-configs/ld-i686.sh delete mode 100755 support/android/egl-configs/ld.sh delete mode 100755 support/android/egl-configs/run.sh delete mode 100644 support/android/egl-configs/src/ffi.rs delete mode 100644 support/android/egl-configs/src/main.rs diff --git a/.gitignore b/.gitignore index a1b982002afd..94acd5b1d033 100644 --- a/.gitignore +++ b/.gitignore @@ -4,7 +4,6 @@ /.servobuild /android-toolchains /target -/support/android/egl-configs/target /ports/android/bin /ports/android/libs /ports/android/local.properties diff --git a/Cargo.toml b/Cargo.toml index 7fe866b06a42..4f107203f283 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,7 +7,7 @@ default-members = [ "ports/servo", "tests/unit/*", ] -exclude = [".cargo", "support/android/egl-configs"] +exclude = [".cargo"] [profile.release] opt-level = 3 diff --git a/servo-tidy.toml b/servo-tidy.toml index 286a303d3035..ce69b5a24cce 100644 --- a/servo-tidy.toml +++ b/servo-tidy.toml @@ -58,7 +58,6 @@ files = [ "./resources/hsts_preload.json", "./tests/wpt/metadata/MANIFEST.json", "./support/android/openssl.sh", - "./support/android/egl-configs/Cargo.lock", # Upstream code from Khronos/WebGL uses tabs for indentation "./tests/wpt/mozilla/tests/webgl", # Ignore those files since the issues reported are on purpose diff --git a/support/android/egl-configs/.cargo/config b/support/android/egl-configs/.cargo/config deleted file mode 100644 index 800226ab1083..000000000000 --- a/support/android/egl-configs/.cargo/config +++ /dev/null @@ -1,10 +0,0 @@ -[build] -target = "i686-linux-android" - -[target.armv7-linux-androideabi] -linker = "./ld.sh" -runner = "./run.sh" - -[target.i686-linux-android] -linker = "./ld-i686.sh" -runner = "./run.sh" diff --git a/support/android/egl-configs/Cargo.lock b/support/android/egl-configs/Cargo.lock deleted file mode 100644 index 1f846687f054..000000000000 --- a/support/android/egl-configs/Cargo.lock +++ /dev/null @@ -1,55 +0,0 @@ -[[package]] -name = "bitflags" -version = "1.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "cfg-if" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "egl-configs" -version = "0.1.0" -dependencies = [ - "gl_generator 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "gl_generator" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "khronos_api 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "log 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", - "xml-rs 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "khronos_api" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "log" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "cfg-if 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "xml-rs" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[metadata] -"checksum bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "d0c54bb8f454c567f21197eefcdbf5679d0bd99f2ddbe52e84c77061952e6789" -"checksum cfg-if 0.1.3 (registry+https://github.com/rust-lang/crates.io-index)" = "405216fd8fe65f718daa7102ea808a946b6ce40c742998fbfd3463645552de18" -"checksum gl_generator 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "7a795170cbd85b5a7baa58d6d7525cae6a03e486859860c220f7ebbbdd379d0a" -"checksum khronos_api 2.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "037ab472c33f67b5fbd3e9163a2645319e5356fcd355efa6d4eb7fff4bbcb554" -"checksum log 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "6fddaa003a65722a7fb9e26b0ce95921fe4ba590542ced664d8ce2fa26f9f3ac" -"checksum xml-rs 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3c1cb601d29fe2c2ac60a2b2e5e293994d87a1f6fa9687a31a15270f909be9c2" diff --git a/support/android/egl-configs/Cargo.toml b/support/android/egl-configs/Cargo.toml deleted file mode 100644 index ae5a6f5d3422..000000000000 --- a/support/android/egl-configs/Cargo.toml +++ /dev/null @@ -1,7 +0,0 @@ -[package] -name = "egl-configs" -version = "0.1.0" -license = "MPL-2.0" - -[build-dependencies] -gl_generator = "0.9" diff --git a/support/android/egl-configs/build.rs b/support/android/egl-configs/build.rs deleted file mode 100644 index 62558fbafd47..000000000000 --- a/support/android/egl-configs/build.rs +++ /dev/null @@ -1,20 +0,0 @@ -/* 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/. */ - -extern crate gl_generator; - -use gl_generator::{Registry, Api, Profile, Fallbacks}; -use std::env; -use std::fs::File; -use std::path::PathBuf; - -fn main() { - let out_dir = PathBuf::from(&env::var("OUT_DIR").unwrap()); - let mut file = File::create(&out_dir.join("egl_bindings.rs")).unwrap(); - Registry::new(Api::Egl, (1, 5), Profile::Core, Fallbacks::All, [ - "EGL_KHR_create_context", - "EGL_KHR_platform_android", - ]) - .write_bindings(gl_generator::StaticGenerator, &mut file).unwrap(); -} diff --git a/support/android/egl-configs/ld-i686.sh b/support/android/egl-configs/ld-i686.sh deleted file mode 100755 index 37b1dadd64e6..000000000000 --- a/support/android/egl-configs/ld-i686.sh +++ /dev/null @@ -1,16 +0,0 @@ -#!/usr/bin/env bash - -# 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/. - -set -o errexit -set -o nounset -set -o pipefail - -NDK=../../../android-toolchains/android-ndk-r12b-linux-x86_64/android-ndk-r12b -BIN="${NDK}/toolchains/x86-4.9/prebuilt/linux-x86_64/bin/" - -"${BIN}/i686-linux-android-gcc" \ - --sysroot "${NDK}/platforms/android-18/arch-x86" \ - "${@}" diff --git a/support/android/egl-configs/ld.sh b/support/android/egl-configs/ld.sh deleted file mode 100755 index f49c9940c4cd..000000000000 --- a/support/android/egl-configs/ld.sh +++ /dev/null @@ -1,16 +0,0 @@ -#!/usr/bin/env bash - -# 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/. - -set -o errexit -set -o nounset -set -o pipefail - -NDK=../../../android-toolchains/android-ndk-r12b-linux-x86_64/android-ndk-r12b -BIN="${NDK}/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin/" - -"${BIN}/arm-linux-androideabi-gcc" \ - --sysroot "${NDK}/platforms/android-18/arch-arm" \ - "${@}" diff --git a/support/android/egl-configs/run.sh b/support/android/egl-configs/run.sh deleted file mode 100755 index dfe4a1dbd4e8..000000000000 --- a/support/android/egl-configs/run.sh +++ /dev/null @@ -1,30 +0,0 @@ -#!/usr/bin/env bash - -# 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/. - -set -o errexit -set -o nounset -set -o pipefail - -# Any -target="" - -# Specific device -#target="-s something" - -# Emulator -#target="-e" - -# USB -#target="-d" - -path="${1}" -base="$(basename ${1})" -remote_path="/data/local/tmp/${base}" -shift - -adb ${target} "wait-for-device" -adb ${target} push "${path}" "${remote_path}" >&2 -adb ${target} shell "${remote_path}" "${@}" diff --git a/support/android/egl-configs/src/ffi.rs b/support/android/egl-configs/src/ffi.rs deleted file mode 100644 index ee2b43aebd47..000000000000 --- a/support/android/egl-configs/src/ffi.rs +++ /dev/null @@ -1,25 +0,0 @@ -/* 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/. */ - -#![allow(non_camel_case_types)] - -use std::os::raw::*; - -pub type NativeDisplayType = *const c_void; -pub type NativePixmapType = *const c_void; -pub type NativeWindowType = *const c_void; - -pub type EGLNativeDisplayType = NativeDisplayType; -pub type EGLNativePixmapType = NativePixmapType; -pub type EGLNativeWindowType = NativeWindowType; - -pub type khronos_utime_nanoseconds_t = khronos_uint64_t; -pub type khronos_uint64_t = u64; -pub type khronos_ssize_t = c_long; -pub type EGLint = i32; - -#[link(name = "EGL")] -extern "C" {} - -include!(concat!(env!("OUT_DIR"), "/egl_bindings.rs")); diff --git a/support/android/egl-configs/src/main.rs b/support/android/egl-configs/src/main.rs deleted file mode 100644 index eb7a4388263d..000000000000 --- a/support/android/egl-configs/src/main.rs +++ /dev/null @@ -1,104 +0,0 @@ -/* 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/. */ - -use ffi::*; -use ffi::types::*; -use std::ptr::null_mut; - -mod ffi; - -fn main() { - unsafe { - run() - } -} - -macro_rules! check { - ($name: ident($($arg: expr),*)) => { - check($name($($arg),*), stringify!($name)) - } -} - -unsafe fn run() { - let display = GetDisplay(DEFAULT_DISPLAY as *mut _); - assert!(!display.is_null()); - - check!(Initialize(display, null_mut(), null_mut())); - - let mut num_config = -1; - check!(GetConfigs(display, null_mut(), 0, &mut num_config)); - println!("Got {} configs", num_config); - assert!(num_config >= 0); - - let mut configs = Vec::with_capacity(num_config as usize); - let mut num_config2 = -1; - check!(GetConfigs(display, configs.as_mut_ptr(), num_config, &mut num_config2)); - assert_eq!(num_config, num_config2); - configs.set_len(num_config as usize); - - for (i, &config) in configs.iter().enumerate() { - println!("Config #{}", i + 1); - - macro_rules! to_pairs { - ($($name: ident)*) => { - &[ $( (stringify!($name), $name) ),* ] - } - } - // https://www.khronos.org/registry/EGL/sdk/docs/man/html/eglGetConfigAttrib.xhtml#description - for &(attr_name, attr) in to_pairs! [ - ALPHA_SIZE - ALPHA_MASK_SIZE - BIND_TO_TEXTURE_RGB - BIND_TO_TEXTURE_RGBA - BLUE_SIZE - BUFFER_SIZE - COLOR_BUFFER_TYPE - CONFIG_CAVEAT - CONFIG_ID - CONFORMANT - DEPTH_SIZE - GREEN_SIZE - LEVEL - LUMINANCE_SIZE - MAX_PBUFFER_WIDTH - MAX_PBUFFER_HEIGHT - MAX_PBUFFER_PIXELS - MAX_SWAP_INTERVAL - MIN_SWAP_INTERVAL - NATIVE_RENDERABLE - NATIVE_VISUAL_ID - NATIVE_VISUAL_TYPE - RED_SIZE - RENDERABLE_TYPE - SAMPLE_BUFFERS - SAMPLES - STENCIL_SIZE - SURFACE_TYPE - TRANSPARENT_TYPE - TRANSPARENT_RED_VALUE - TRANSPARENT_GREEN_VALUE - TRANSPARENT_BLUE_VALUE - ] { - let mut value = -1; - check!(GetConfigAttrib(display, config, attr as i32, &mut value)); - if value < 10 { - println!(" {}\t = {}", attr_name, value) - } else { - println!(" {}\t= {} = 0x{:x}", attr_name, value, value) - } - } - } -} - -unsafe fn check(result: EGLBoolean, function_name: &str) { - check_error(); - assert_eq!(result, TRUE, "{} failed", function_name); -} - -unsafe fn check_error() { - let status = GetError(); - if status != SUCCESS as i32 { - panic!("Error: 0x{:x}", status); - } -} From 8293b295beb8c76113f525f41ba16e204a7cb22b Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Fri, 29 Jun 2018 16:46:50 +0200 Subject: [PATCH 27/30] bootstrap-android: check SHA1 hashes of downloaded archives --- python/servo/bootstrap_commands.py | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/python/servo/bootstrap_commands.py b/python/servo/bootstrap_commands.py index 3cf7f36a0a79..07c31c660cd4 100644 --- a/python/servo/bootstrap_commands.py +++ b/python/servo/bootstrap_commands.py @@ -29,7 +29,7 @@ import servo.bootstrap as bootstrap from servo.command_base import CommandBase, cd, check_call -from servo.util import delete, download_bytes, download_file, extract +from servo.util import delete, download_bytes, download_file, extract, check_hash @CommandProvider @@ -63,7 +63,6 @@ def bootstrap(self, force=False): help='Run SDK component install and emulator image creation again') def bootstrap_android(self, update=False): - # Available filenames: see https://dl.google.com/android/repository/repository2-1.xml ndk = "android-ndk-r12b-{system}-{arch}" tools = "sdk-tools-{system}-4333796" @@ -73,6 +72,19 @@ def bootstrap_android(self, update=False): ("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) @@ -89,8 +101,9 @@ def download(target_dir, name, flatten=False): if not path.isfile(archive): download_file(filename, url, archive) + check_hash(archive, known_sha1[filename], "sha1") print("Extracting " + filename) - remove = False # Set to False to avoid repeated downloads while debugging this script + remove = True # Set to False to avoid repeated downloads while debugging this script if flatten: extracted = final + "_" extract(archive, extracted, remove=remove) From bee3fd09c210a192e52f9950c630c49c655de802 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Fri, 29 Jun 2018 21:21:35 +0200 Subject: [PATCH 28/30] mach android-emulator: avoid mach error messages for Python exceptions --- python/servo/post_build_commands.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/servo/post_build_commands.py b/python/servo/post_build_commands.py index b5dd211a144a..30c59f417f50 100644 --- a/python/servo/post_build_commands.py +++ b/python/servo/post_build_commands.py @@ -181,7 +181,7 @@ def android_emulator(self, args=None): return 1 env = self.build_env() emulator = path.join(env["ANDROID_SDK"], "emulator", "emulator") - check_call([emulator] + args) + return subprocess.call([emulator] + args) @Command('rr-record', description='Run Servo whilst recording execution with rr', From eecbe837500270f530e943a1b6bb718031156dd6 Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Fri, 29 Jun 2018 23:27:31 +0200 Subject: [PATCH 29/30] Add ./mach test-android-startup --- python/servo/command_base.py | 7 +++ python/servo/post_build_commands.py | 6 +- python/servo/testing_commands.py | 87 ++++++++++++++++++++++++++++- 3 files changed, 93 insertions(+), 7 deletions(-) diff --git a/python/servo/command_base.py b/python/servo/command_base.py index 70f19203ec63..0963242226b2 100644 --- a/python/servo/command_base.py +++ b/python/servo/command_base.py @@ -623,6 +623,13 @@ def android_adb_path(self, env): return sdk_adb return "adb" + def android_emulator_path(self, env): + if "ANDROID_SDK" in env: + sdk_adb = path.join(env["ANDROID_SDK"], "emulator", "emulator") + if path.exists(sdk_adb): + return sdk_adb + return "emulator" + def handle_android_target(self, target): if target == "arm-linux-androideabi": self.config["android"]["platform"] = "android-18" diff --git a/python/servo/post_build_commands.py b/python/servo/post_build_commands.py index 30c59f417f50..0132d2ea4b04 100644 --- a/python/servo/post_build_commands.py +++ b/python/servo/post_build_commands.py @@ -177,10 +177,8 @@ def run(self, params, release=False, dev=False, android=None, debug=False, debug help="Command-line arguments to be passed through to the emulator") def android_emulator(self, args=None): if not args: - print("Pass at least an AVD name such as @servo-arm or @servo-x86") - return 1 - env = self.build_env() - emulator = path.join(env["ANDROID_SDK"], "emulator", "emulator") + print("AVDs created by `./mach bootstrap-android` are servo-arm and servo-x86.") + emulator = self.android_emulator_path(self.build_env()) return subprocess.call([emulator] + args) @Command('rr-record', diff --git a/python/servo/testing_commands.py b/python/servo/testing_commands.py index 545fa19f3b05..f705939ba532 100644 --- a/python/servo/testing_commands.py +++ b/python/servo/testing_commands.py @@ -17,7 +17,7 @@ import platform import copy from collections import OrderedDict -from time import time +import time import json import urllib2 import urllib @@ -157,7 +157,7 @@ def test(self, params, render_mode=DEFAULT_RENDER_MODE, release=False, tidy_all= print("%s is not a valid test path or suite name" % arg) return 1 - test_start = time() + test_start = time.time() for suite, tests in selected_suites.iteritems(): props = suites[suite] kwargs = props.get("kwargs", {}) @@ -166,7 +166,7 @@ def test(self, params, render_mode=DEFAULT_RENDER_MODE, release=False, tidy_all= Registrar.dispatch("test-%s" % suite, context=self.context, **kwargs) - elapsed = time() - test_start + elapsed = time.time() - test_start print("Tests completed in %0.2fs" % elapsed) @@ -551,6 +551,87 @@ def filter_intermittents(self, summary, log_filteredsummary, log_intermittents, output.close() return 1 + @Command('test-android-startup', + description='Extremely minimal testing of Servo for Android', + category='testing') + @CommandArgument('--release', '-r', action='store_true', + help='Run the release build') + @CommandArgument('--dev', '-d', action='store_true', + help='Run the dev build') + def test_android_startup(self, release, dev): + if (release and dev) or not (release or dev): + print("Please specify one of --dev or --release.") + return 1 + target = "i686-linux-android" + print("Assuming --target " + target) + env = self.build_env(target=target) + assert self.handle_android_target(target) + + emulator_port = "5580" + adb = [self.android_adb_path(env), "-s", "emulator-" + emulator_port] + emulator_process = subprocess.Popen([ + self.android_emulator_path(env), + "@servo-x86", + "-no-window", + "-gpu", "guest", + "-port", emulator_port, + ]) + try: + # This is hopefully enough time for the emulator to exit + # if it cannot start because of a configuration problem, + # and probably more time than it needs to boot anyway + time.sleep(1) + if emulator_process.poll() is not None: + # The process has terminated already, wait-for-device would block indefinitely + return 1 + + subprocess.call(adb + ["wait-for-device"]) + + # https://stackoverflow.com/a/38896494/1162888 + while 1: + stdout, stderr = subprocess.Popen( + adb + ["shell", "getprop", "sys.boot_completed"], + stdout=subprocess.PIPE, + ).communicate() + if "1" in stdout: + break + print("Waiting for the emulator to boot") + time.sleep(1) + + binary_path = self.get_binary_path(release, dev, android=True) + result = subprocess.call(adb + ["install", "-r", binary_path + ".apk"]) + if result != 0: + return result + + html = """ + + """ + url = "data:text/html;base64," + html.encode("base64").replace("\n", "") + result = subprocess.call(adb + ["shell", """ + mkdir -p /sdcard/Android/data/com.mozilla.servo/files/ + echo 'servo' > /sdcard/Android/data/com.mozilla.servo/files/android_params + echo '%s' >> /sdcard/Android/data/com.mozilla.servo/files/android_params + am start com.mozilla.servo/com.mozilla.servo.MainActivity + """ % url]) + if result != 0: + return result + + logcat = adb + ["logcat", "RustAndroidGlueStdouterr:D", "*:S", "-v", "raw"] + logcat_process = subprocess.Popen(logcat, stdout=subprocess.PIPE) + while 1: + line = logcat_process.stdout.readline() + if "JavaScript is running!" in line: + print(line) + break + logcat_process.kill() + finally: + try: + emulator_process.kill() + except OSError: + pass + @Command('test-jquery', description='Run the jQuery test suite', category='testing') From c0d1b8e80861e75f7f3e76660675e88d963b81bb Mon Sep 17 00:00:00 2001 From: Simon Sapin Date: Mon, 2 Jul 2018 16:56:49 +0200 Subject: [PATCH 30/30] Android: increase emulator disk size, for debug builds Avoid INSTALL_FAILED_INSUFFICIENT_STORAGE on install. --- python/servo/bootstrap_commands.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/python/servo/bootstrap_commands.py b/python/servo/bootstrap_commands.py index 07c31c660cd4..699981ff6d14 100644 --- a/python/servo/bootstrap_commands.py +++ b/python/servo/bootstrap_commands.py @@ -158,7 +158,7 @@ def download(target_dir, name, flatten=False): 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=1G\n") + f.write("disk.dataPartition.size=2G\n") @Command('update-hsts-preload', description='Download the HSTS preload list',