1
0
mirror of https://github.com/ARM-software/workload-automation.git synced 2025-01-18 12:06:08 +00:00

workloads/speedometer: offline version of speedometer

This version replaces the previous uiauto version of Speedometer with a new
version.

* Supports both chrome and chromium again, this is selected with the
  chrome_package parameter.
* No longer needs internet access.
* Version 1.0 of Speedometer is no longer supported.
* Requires root:
  - sometimes uiautomator dump doesn't capture the score if not run as root
  - need to modify the browser's XML preferences file to bypass T&C acceptance
    screen
This commit is contained in:
Stephen Kyle 2020-06-24 11:49:31 +01:00 committed by Marc Bonnici
parent ba5a65aad7
commit 7489b487e1
14 changed files with 396 additions and 576 deletions

View File

@ -0,0 +1,7 @@
The speedometer_archive.tgz file is a tarball containing the following archives from WebKit:
the PerformanceTests/Speedometer directory state taken from https://github.com/WebKit/webkit as of:
commit 5f402692d5f3406527dc107b5d20cc47dac929e8 Tue Jul 14 14:06:17 2020 +0000
WebKit is open source software with portions licensed under the LGPL and BSD
licenses available at https://webkit.org/licensing-webkit/

View File

@ -12,57 +12,411 @@
# See the License for the specific language governing permissions and # See the License for the specific language governing permissions and
# limitations under the License. # limitations under the License.
# #
from collections import defaultdict
from http.server import SimpleHTTPRequestHandler, HTTPServer
import logging
import os import os
import re import re
import subprocess
import tarfile
import tempfile
import threading
import time
import uuid
from wa import ApkUiautoWorkload, Parameter from wa import Parameter, Workload, File
from wa.framework.exception import ValidationError, WorkloadError from wa.framework.exception import WorkloadError
from wa.utils.types import list_of_strs from wa.utils.exec_control import once
from wa.utils.misc import unique
from devlib.utils.android import adb_command
class Speedometer(ApkUiautoWorkload): class Speedometer(Workload):
name = 'speedometer' name = "speedometer"
package_names = ['com.android.chrome'] description = """
regex = re.compile(r'Speedometer Score ([\d.]+)') A workload to execute the speedometer 2.0 web based benchmark. Requires device to be rooted.
versions = ['1.0', '2.0'] This workload will only with Android 9+ devices if connected via TCP, or Android 5+ if
description = ''' connected via USB.
A workload to execute the speedometer web based benchmark
Test description: Test description:
1. Open chrome 1. Host a local copy of the Speedometer website, and make it visible to the device via ADB.
2. Navigate to the speedometer website - http://browserbench.org/Speedometer/ 2. Open chrome via an intent to access the local copy.
3. Execute the benchmark 3. Execute the benchmark - the copy has been modified to trigger the start of the benchmark.
4. The benchmark will write to the browser's sandboxed local storage to signal the benchmark
has completed. This local storage is monitored by this workload.
known working chrome version 80.0.3987.149 Known working chrome version 83.0.4103.106
'''
To modify the archived speedometer workload:
1. Run 'git clone https://github.com/WebKit/webkit'
2. Copy PerformanceTests/Speedometer to a directory called document_root, renaming Speedometer to Speedometer2.0
3. Modify document_root/Speedometer2.0/index.html:
3a. Remove the 'defer' attribute from the <script> tags within the <head> section.
3b. Add '<script>startTest();</script>' to the very end of the <body> section.
4. Modify document_root/Speedometer2.0/resources/main.js:
4a. Add the listed code after this line:
document.getElementById('result-number').textContent = results.formattedMean;
Code to add:
if (location.search.length > 1) {
var parts = location.search.substring(1).split('&');
for (var i = 0; i < parts.length; i++) {
var keyValue = parts[i].split('=');
var key = keyValue[0];
var value = keyValue[1];
if (key === "reportEndId") {
window.localStorage.setItem('reportEndId', value);
}
}
}
5. Run 'tar -cpzf speedometer_archive.tgz document_root'
6. Copy the tarball into the workloads/speedometer directory
7. If appropriate, update the commit info in the LICENSE file.
"""
supported_platforms = ["android"]
package_names = ["org.chromium.chrome", "com.android.chrome"]
# This regex finds a single XML tag where property 1 and 2 are true:
# 1. contains the attribute text="XXX" or content-desc="XXX"
# 2. and exclusively either 2a or 2b is true:
# 2a. there exists a resource-id="result-number" to that attribute's left
# 2b. there exists a resource-id="result-number" to that attribute's right
# The regex stores the XXX value of that attribute in the named group 'value'.
#
# Just in case someone wants to learn something:
# If you use (?P<tag>regex)? to match 'regex', and then afterwards you
# have (?(tag)A|B), then regex A will be used if the 'tag' group captured
# something and B will be used if nothing was captured. This is how we
# search for 'resource-id="result-number"' after the text/content-desc
# _only_ in the case we didn't see it before.
regex = re.compile(
'<[^>]*(?P<Z>resource-id="result-number")?[^>]*'
'(?:text|content-desc)="(?P<value>\d+.\d+)"[^>]*'
'(?(Z)|resource-id="result-number")[^>]*\/>'
)
parameters = [ parameters = [
Parameter('speedometer_version', allowed_values=versions, kind=str, default='2.0', Parameter(
description=''' "chrome_package",
The speedometer version to be used. allowed_values=package_names,
''') kind=str,
default="com.android.chrome",
description="""
The app package for the browser that will be launched.
""",
),
] ]
requires_network = True
def __init__(self, target, **kwargs): def __init__(self, target, **kwargs):
super(Speedometer, self).__init__(target, **kwargs) super(Speedometer, self).__init__(target, **kwargs)
self.gui.timeout = 1500 self.target_file_was_seen = defaultdict(lambda: False)
self.gui.uiauto_params['version'] = self.speedometer_version self.ui_dump_loc = None
@once
def initialize(self, context):
super(Speedometer, self).initialize(context)
self.archive_server = ArchiveServer()
if not self.target.is_rooted:
raise WorkloadError(
"Device must be rooted for the speedometer workload currently"
)
if self.target.adb_server is not None:
raise WorkloadError(
"Workload does not support the adb_server parameter, due to the webpage "
"hosting mechanism."
)
# Temporary directory used for storing the Speedometer files, uiautomator
# dumps, and modified XML chrome config files.
self.temp_dir = tempfile.TemporaryDirectory()
self.document_root = os.path.join(self.temp_dir.name, "document_root")
# Host a copy of Speedometer locally
tarball = context.get_resource(File(self, "speedometer_archive.tgz"))
with tarfile.open(name=tarball) as handle:
handle.extractall(self.temp_dir.name)
self.archive_server.start(self.document_root, self.target)
self.webserver_port = self.archive_server.get_port()
self.speedometer_url = "http://localhost:{}/Speedometer2.0/index.html".format(
self.webserver_port
)
def setup(self, context):
super(Speedometer, self).setup(context)
# We are making sure we start with a 'fresh' browser - no other tabs,
# nothing in the page cache, etc.
# Clear the application's cache.
self.target.execute("pm clear {}".format(self.chrome_package), as_root=True)
# Launch the browser for the first time and then stop it. Since the
# cache has just been cleared, this forces it to recreate its
# preferences file, that we need to modify.
browser_launch_cmd = "am start -a android.intent.action.VIEW -d {} {}".format(
self.speedometer_url, self.chrome_package
)
self.target.execute(browser_launch_cmd)
time.sleep(1)
self.target.execute("am force-stop {}".format(self.chrome_package))
time.sleep(1)
# Pull the preferences file from the device, modify it, and push it
# back. This is done to bypass the 'first launch' screen of the
# browser we see after the cache is cleared.
self.preferences_xml = "{}_preferences.xml".format(self.chrome_package)
file_to_modify = "/data/data/{}/shared_prefs/{}".format(
self.chrome_package, self.preferences_xml
)
self.target.pull(file_to_modify, self.temp_dir.name, as_root=True)
with open(os.path.join(self.temp_dir.name, self.preferences_xml)) as read_fh:
lines = read_fh.readlines()
# Add additional elements for the preferences XML to the
# _second-last_ line
for line in [
'<boolean name="first_run_flow" value="true" />\n',
'<boolean name="first_run_tos_accepted" value="true" />\n',
'<boolean name="first_run_signin_complete" value="true" />\n',
'<boolean name="displayed_data_reduction_promo" value="true" />\n',
]:
lines.insert(len(lines) - 1, line)
with open(
os.path.join(self.temp_dir.name, self.preferences_xml + ".new"), "w",
) as write_fh:
for line in lines:
write_fh.write(line)
# Make sure ownership of the original file is preserved.
user_owner, group_owner = self.target.execute(
"ls -l {}".format(file_to_modify), as_root=True,
).split()[2:4]
self.target.push(
os.path.join(self.temp_dir.name, self.preferences_xml + ".new"),
file_to_modify,
as_root=True,
)
self.target.execute(
"chown {}.{} {}".format(user_owner, group_owner, file_to_modify),
as_root=True,
)
def run(self, context):
super(Speedometer, self).run(context)
# Generate a UUID to search for in the browser's local storage to find out
# when the workload has ended.
report_end_id = uuid.uuid4().hex
url_with_unique_id = "{}?reportEndId={}".format(
self.speedometer_url, report_end_id
)
browser_launch_cmd = "am start -a android.intent.action.VIEW -d '{}' {}".format(
url_with_unique_id, self.chrome_package
)
self.target.execute(browser_launch_cmd)
self.wait_for_benchmark_to_complete(report_end_id)
def target_file_was_created(self, f):
"""Assume that once self.target.file_exists(f) returns True, it will
always be True from that point forward, so cache the response into the
self.target_file_was_seen dict."""
if not self.target_file_was_seen[f]:
self.target_file_was_seen[f] = self.target.file_exists(f)
return self.target_file_was_seen[f]
def wait_for_benchmark_to_complete(self, report_end_id):
local_storage = "/data/data/{}/app_chrome/Default/Local Storage/leveldb".format(
self.chrome_package
)
sleep_period_s = 5
find_period_s = 30
timeout_period_m = 15
iterations = 0
local_storage_seen = False
benchmark_complete = False
while not benchmark_complete:
if self.target_file_was_created(local_storage):
if (
iterations % (find_period_s // sleep_period_s) == 0 or
not local_storage_seen
):
# There's a chance we don't see the localstorage file immediately, and there's a
# chance more of them could be created later, so check for those files every ~30
# seconds.
find_cmd = '{} find "{}" -iname "*.log"'.format(
self.target.busybox, local_storage
)
candidate_files = self.target.execute(find_cmd, as_root=True).split(
"\n"
)
local_storage_seen = True
for ls_file in candidate_files:
# Each local storage file is in a binary format. The busybox grep seems to
# print out the line '[KEY][VALUE]' for a match, rather than just reporting
# that 'binary file X matches', so just check the output for our generated ID.
grep_cmd = '{} grep {} "{}"'.format(
self.target.busybox, report_end_id, ls_file
)
output = self.target.execute(
grep_cmd, as_root=True, check_exit_code=False
)
if report_end_id in output:
benchmark_complete = True
break
iterations += 1
if iterations > ((timeout_period_m * 60) // sleep_period_s):
# We've been waiting 15 minutes for Speedometer to finish running - give up.
if not local_storage_seen:
raise WorkloadError(
"Speedometer did not complete within 15m - Local Storage wasn't found"
)
raise WorkloadError("Speedometer did not complete within 15 minutes.")
time.sleep(sleep_period_s)
def read_score(self):
self.target.execute(
"uiautomator dump {}".format(self.ui_dump_loc), as_root=True
)
self.target.pull(self.ui_dump_loc, self.temp_dir.name)
with open(os.path.join(self.temp_dir.name, "ui_dump.xml"), "rb") as fh:
dump = fh.read().decode("utf-8")
match = self.regex.search(dump)
result = None
if match:
result = float(match.group("value"))
return result
def update_output(self, context): def update_output(self, context):
super(Speedometer, self).update_output(context) super(Speedometer, self).update_output(context)
result = None
logcat_file = context.get_artifact_path('logcat')
with open(logcat_file, errors='replace') as fh:
for line in fh:
match = self.regex.search(line)
if match:
result = float(match.group(1))
if result is not None: self.ui_dump_loc = os.path.join(self.target.working_directory, "ui_dump.xml")
context.add_metric('Speedometer Score', result, 'Runs per minute', lower_is_better=False)
else: score_read = False
raise WorkloadError("The Speedometer workload has failed. No score was obtainable.") iterations = 0
while not score_read:
score = self.read_score()
if score is not None:
context.add_metric(
"Speedometer Score", score, "Runs per minute", lower_is_better=False
)
score_read = True
else:
if iterations >= 10:
raise WorkloadError(
"The Speedometer workload has failed. No score was obtainable."
)
else:
# Sleep and retry...
time.sleep(2)
iterations += 1
def teardown(self, context):
super(Speedometer, self).teardown(context)
# The browser's processes can stick around and have minor impact on
# other performance sensitive workloads, so make sure we clean up.
self.target.execute("am force-stop {}".format(self.chrome_package))
if self.cleanup_assets:
if self.ui_dump_loc is not None and self.target_file_was_created(
self.ui_dump_loc
):
# The only thing left on device was the UI dump created by uiautomator.
self.target.execute("rm {}".format(self.ui_dump_loc), as_root=True)
# Clear the cache we used to check if the local storage directory exists.
self.target_file_was_seen.clear()
self.ui_dump_loc = None
@once
def finalize(self, context):
super(Speedometer, self).finalize(context)
# Shutdown the locally hosted version of Speedometer
self.archive_server.stop(self.target)
class ArchiveServerThread(threading.Thread):
"""Thread for running the HTTPServer"""
def __init__(self, httpd):
self._httpd = httpd
threading.Thread.__init__(self)
def run(self):
self._httpd.serve_forever()
class DifferentDirectoryHTTPRequestHandler(SimpleHTTPRequestHandler):
"""A version of SimpleHTTPRequestHandler that allows us to serve
relative files from a different directory than the current one.
This directory is captured in |document_root|. It also suppresses
logging."""
def translate_path(self, path):
document_root = self.server.document_root
path = SimpleHTTPRequestHandler.translate_path(self, path)
requested_uri = os.path.relpath(path, os.getcwd())
return os.path.join(document_root, requested_uri)
# Disable the logging.
# pylint: disable=redefined-builtin
def log_message(self, format, *args):
pass
class ArchiveServer(object):
def __init__(self):
self._port = None
def start(self, document_root, target):
# Create the server, and find out the port we've been assigned...
self._httpd = HTTPServer(("", 0), DifferentDirectoryHTTPRequestHandler)
# (This property is expected to be read by the
# DifferentDirectoryHTTPRequestHandler.translate_path method.)
self._httpd.document_root = document_root
_, self._port = self._httpd.server_address
self._thread = ArchiveServerThread(self._httpd)
self._thread.start()
adb_command(target.adb_name, "reverse tcp:{0} tcp:{0}".format(self._port))
def stop(self, target):
adb_command(target.adb_name, "reverse --remove tcp:{}".format(self._port))
self._httpd.shutdown()
self._thread.join()
def get_port(self):
return self._port

Binary file not shown.

View File

@ -1,41 +0,0 @@
apply plugin: 'com.android.application'
def packageName = "com.arm.wa.uiauto.speedometer"
android {
compileSdkVersion 28
buildToolsVersion "28.0.3"
defaultConfig {
applicationId "${packageName}"
minSdkVersion 18
targetSdkVersion 28
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
applicationVariants.all { variant ->
variant.outputs.each { output ->
output.outputFile = file("$project.buildDir/apk/${packageName}.apk")
}
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support.test:runner:0.5'
compile 'com.android.support.test:rules:0.5'
compile 'com.android.support.test.uiautomator:uiautomator-v18:2.1.2'
compile(name: 'uiauto', ext:'aar')
}
repositories {
flatDir {
dirs 'libs'
}
}

View File

@ -1,13 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.arm.wa.uiauto.speedometer"
android:versionCode="1"
android:versionName="1.0">
<instrumentation
android:name="android.support.test.runner.AndroidJUnitRunner"
android:targetPackage="${applicationId}"/>
</manifest>

View File

@ -1,152 +0,0 @@
/* Copyright 2014-2018 ARM Limited
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.arm.wa.uiauto.speedometer;
import android.os.Bundle;
import android.support.test.runner.AndroidJUnit4;
import android.support.test.uiautomator.UiObject;
import android.support.test.uiautomator.UiObjectNotFoundException;
import android.support.test.uiautomator.UiSelector;
import com.arm.wa.uiauto.BaseUiAutomation;
import android.util.Log;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import java.util.concurrent.TimeUnit;
@RunWith(AndroidJUnit4.class)
public class UiAutomation extends BaseUiAutomation {
private int networkTimeoutSecs = 30;
private long networkTimeout = TimeUnit.SECONDS.toMillis(networkTimeoutSecs);
public static String TAG = "UXPERF";
public boolean textenabled = false;
private String speedometerVersion;
@Before
public void initialize(){
Bundle params = getParams();
speedometerVersion = params.getString("version");
initialize_instrumentation();
}
@Test
public void setup() throws Exception{
setScreenOrientation(ScreenOrientation.NATURAL);
dismissChromePopup();
openSpeedometer();
}
@Test
public void runWorkload() throws Exception {
runBenchmark();
}
@Test
public void teardown() throws Exception{
clearTabs();
unsetScreenOrientation();
}
public void runBenchmark() throws Exception {
UiObject start =
mDevice.findObject(new UiSelector().description("Start Test")
.className("android.widget.Button"));
UiObject starttext =
mDevice.findObject(new UiSelector().text("Start Test")
.className("android.widget.Button"));
// Run speedometer test
if (start.waitForExists(10000)) {
start.click();
} else {
starttext.click();
}
UiObject scores =
mDevice.findObject(new UiSelector().resourceId("result-number")
.className("android.view.View"));
scores.waitForExists(2100000);
getScores(scores);
}
public void openSpeedometer() throws Exception {
UiObject urlBar =
mDevice.findObject(new UiSelector().resourceId("com.android.chrome:id/url_bar"));
UiObject searchBox = mDevice.findObject(new UiSelector().resourceId("com.android.chrome:id/search_box_text"));
if (!urlBar.waitForExists(5000)) {
searchBox.click();
}
String url = "http://browserbench.org/Speedometer" + speedometerVersion;
if (speedometerVersion.equals("1.0")) {
url = "http://browserbench.org/Speedometer";
}
// Clicking search box turns it into url bar on some deivces
if(urlBar.waitForExists(2000)) {
urlBar.click();
sleep(2);
urlBar.setText(url);
} else {
searchBox.setText(url);
}
pressEnter();
}
public void getScores(UiObject scores) throws Exception {
boolean isScoreAvailable = false;
int waitAttempts = 0;
while (!isScoreAvailable && waitAttempts < 10) {
sleep(1);
if (!scores.getText().isEmpty() || !scores.getContentDescription().isEmpty()) {
isScoreAvailable = true;
}
waitAttempts++;
}
String textScore = scores.getText();
String descScore = scores.getContentDescription();
// Chrome throws loads of errors on some devices clogging up logcat so clear tabs before saving score.
clearTabs();
Log.i(TAG, "Speedometer Score " + textScore);
Log.i(TAG, "Speedometer Score " + descScore);
}
public void clearTabs() throws Exception {
UiObject tabselector =
mDevice.findObject(new UiSelector().resourceId("com.android.chrome:id/tab_switcher_button")
.className("android.widget.ImageButton"));
if (!tabselector.exists()){
return;
}
tabselector.click();
UiObject menu =
mDevice.findObject(new UiSelector().resourceId("com.android.chrome:id/menu_button")
.className("android.widget.ImageButton"));
menu.click();
UiObject closetabs =
mDevice.findObject(new UiSelector().textContains("Close all tabs"));
if (closetabs.exists()){
closetabs.click();
}
}
}

View File

@ -1,23 +0,0 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:2.3.2'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
jcenter()
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}

View File

@ -1,55 +0,0 @@
#!/bin/bash
# Copyright 2018 ARM Limited
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
# CD into build dir if possible - allows building from any directory
script_path='.'
if `readlink -f $0 &>/dev/null`; then
script_path=`readlink -f $0 2>/dev/null`
fi
script_dir=`dirname $script_path`
cd $script_dir
# Ensure gradelw exists before starting
if [[ ! -f gradlew ]]; then
echo 'gradlew file not found! Check that you are in the right directory.'
exit 9
fi
# Copy base class library from wa dist
libs_dir=app/libs
base_class=`python3 -c "import os, wa; print(os.path.join(os.path.dirname(wa.__file__), 'framework', 'uiauto', 'uiauto.aar'))"`
mkdir -p $libs_dir
cp $base_class $libs_dir
# Build and return appropriate exit code if failed
# gradle build
./gradlew clean :app:assembleDebug
exit_code=$?
if [[ $exit_code -ne 0 ]]; then
echo "ERROR: 'gradle build' exited with code $exit_code"
exit $exit_code
fi
# If successful move APK file to workload folder (overwrite previous)
package=com.arm.wa.uiauto.speedometer
rm -f ../$package
if [[ -f app/build/apk/$package.apk ]]; then
cp app/build/apk/$package.apk ../$package.apk
else
echo 'ERROR: UiAutomator apk could not be found!'
exit 9
fi

View File

@ -1,6 +0,0 @@
#Wed May 03 15:42:44 BST 2017
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip

View File

@ -1,160 +0,0 @@
#!/usr/bin/env bash
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS=""
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn ( ) {
echo "$*"
}
die ( ) {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
esac
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=$((i+1))
done
case $i in
(0) set -- ;;
(1) set -- "$args0" ;;
(2) set -- "$args0" "$args1" ;;
(3) set -- "$args0" "$args1" "$args2" ;;
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules
function splitJvmOpts() {
JVM_OPTS=("$@")
}
eval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS
JVM_OPTS[${#JVM_OPTS[*]}]="-Dorg.gradle.appname=$APP_BASE_NAME"
exec "$JAVACMD" "${JVM_OPTS[@]}" -classpath "$CLASSPATH" org.gradle.wrapper.GradleWrapperMain "$@"

View File

@ -1,90 +0,0 @@
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS=
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto init
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:init
@rem Get command-line arguments, handling Windowz variants
if not "%OS%" == "Windows_NT" goto win9xME_args
if "%@eval[2+2]" == "4" goto 4NT_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
goto execute
:4NT_args
@rem Get arguments from the 4NT Shell from JP Software
set CMD_LINE_ARGS=%$
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega

View File

@ -1 +0,0 @@
include ':app'