| // Copyright (c) 2016, the R8 project authors. Please see the AUTHORS file | 
 | // for details. All rights reserved. Use of this source code is governed by a | 
 | // BSD-style license that can be found in the LICENSE file. | 
 |  | 
 |  | 
 |  | 
 | import desugaredlibrary.CustomConversionAsmRewriterTask | 
 | import net.ltgt.gradle.errorprone.CheckSeverity | 
 | import org.gradle.internal.os.OperatingSystem | 
 | import tasks.DownloadDependency | 
 | import smali.SmaliTask | 
 | import tasks.GetJarsFromConfiguration | 
 | import utils.Utils | 
 |  | 
 | buildscript { | 
 |     repositories { | 
 |         mavenCentral() | 
 |         gradlePluginPortal() | 
 |         jcenter() | 
 |     } | 
 | } | 
 |  | 
 | plugins { | 
 |   id "net.ltgt.errorprone" version "2.0.2" | 
 | } | 
 |  | 
 | apply plugin: 'java' | 
 | apply plugin: 'idea' | 
 |  | 
 | ext { | 
 |     androidSupportVersion = '25.4.0' | 
 |     asmVersion = '9.4'  // When updating update tools/asmifier.py, build.src and Toolhelper as well. | 
 |     javassistVersion = '3.29.2-GA' | 
 |     espressoVersion = '3.0.0' | 
 |     fastutilVersion = '7.2.0' | 
 |     guavaVersion = '30.1.1-jre' | 
 |     joptSimpleVersion = '4.6' | 
 |     gsonVersion = '2.7' | 
 |     junitVersion = '4.13-beta-2' | 
 |     mockitoVersion = '2.10.0' | 
 |     // The kotlin version is only here to specify the kotlin language level, | 
 |     // all kotlin compilations are done in tests. | 
 |     kotlinVersion = '1.8.0' | 
 |     kotlinExtMetadataJVMVersion = '0.6.0' | 
 |     smaliVersion = '2.2b4' | 
 |     errorproneVersion = '2.18.0' | 
 |     testngVersion = '6.10' | 
 | } | 
 |  | 
 | repositories { | 
 |     google() | 
 |     mavenCentral() | 
 | } | 
 |  | 
 | if (project.hasProperty('with_code_coverage')) { | 
 |     apply plugin: 'jacoco' | 
 | } | 
 |  | 
 | // Custom source set for example tests and generated tests. | 
 | sourceSets { | 
 |     main { | 
 |         java { | 
 |             srcDirs = ['src/main/java', 'src/keepanno/java'] | 
 |         } | 
 |         resources { | 
 |             srcDirs "third_party/api_database/api_database" | 
 |         } | 
 |     } | 
 |     main17 { | 
 |         java { | 
 |             srcDirs = ['src/main/java', 'src/keepanno/java'] | 
 |         } | 
 |         resources { | 
 |             srcDirs "third_party/api_database/api_database" | 
 |         } | 
 |     } | 
 |     test { | 
 |         java { | 
 |             srcDirs = [ | 
 |                     'src/test/java', | 
 |                     'build/generated/test/java', | 
 |             ] | 
 |         } | 
 |     } | 
 |     apiUsageSample { | 
 |         java { | 
 |             srcDirs = ['src/test/apiUsageSample', 'src/main/java'] | 
 |             include 'com/android/tools/apiusagesample/*.java' | 
 |             include 'com/android/tools/r8/BaseCompilerCommandParser.java' | 
 |             include 'com/android/tools/r8/D8CommandParser.java' | 
 |             include 'com/android/tools/r8/R8CommandParser.java' | 
 |             include 'com/android/tools/r8/utils/FlagFile.java' | 
 |         } | 
 |     } | 
 |     cfSegments { | 
 |         java { | 
 |             srcDirs = ['third_party/classlib/java', 'src/cf_segments/java'] | 
 |         } | 
 |         output.resourcesDir = 'build/classes/cfSegments' | 
 |     } | 
 |     libraryDesugarConversions { | 
 |         java { | 
 |             srcDirs = ['src/library_desugar/java'] | 
 |         } | 
 |         output.resourcesDir = 'build/classes/library_desugar_conversions' | 
 |     } | 
 |     debugTestResources { | 
 |         java { | 
 |             srcDirs = ['src/test/debugTestResources'] | 
 |         } | 
 |         output.resourcesDir = 'build/classes/debugTestResources' | 
 |     } | 
 |     debugTestResourcesJava8 { | 
 |         java { | 
 |             srcDirs = ['src/test/debugTestResourcesJava8'] | 
 |         } | 
 |         output.resourcesDir = 'build/classes/debugTestResourcesJava8' | 
 |     } | 
 |     examples { | 
 |         java { | 
 |             srcDirs = ['src/test/examples'] | 
 |         } | 
 |         output.resourcesDir = 'build/classes/examples' | 
 |     } | 
 |     examplesJava9 { | 
 |         java { | 
 |             srcDirs = ['src/test/examplesJava9'] | 
 |         } | 
 |     } | 
 |     examplesJava10 { | 
 |         java { | 
 |             srcDirs = ['src/test/examplesJava10'] | 
 |         } | 
 |     } | 
 |     examplesJava11 { | 
 |         java { | 
 |             srcDirs = ['src/test/examplesJava11'] | 
 |         } | 
 |     } | 
 |     examplesJava17 { | 
 |         java { | 
 |             srcDirs = ['src/test/examplesJava17'] | 
 |         } | 
 |     } | 
 |     examplesJava18 { | 
 |         java { | 
 |             srcDirs = ['src/test/examplesJava18'] | 
 |         } | 
 |     } | 
 |     examplesTestNGRunner { | 
 |         java { | 
 |             srcDirs = ['src/test/testngrunner'] | 
 |         } | 
 |     } | 
 |     examplesAndroidN { | 
 |         java { | 
 |             srcDirs = ['src/test/examplesAndroidN'] | 
 |         } | 
 |         output.resourcesDir = 'build/classes/examplesAndroidN' | 
 |     } | 
 |     examplesAndroidO { | 
 |         java { | 
 |             srcDirs = ['src/test/examplesAndroidO'] | 
 |         } | 
 |         output.resourcesDir = 'build/classes/examplesAndroidO' | 
 |     } | 
 |     examplesAndroidP { | 
 |         java { | 
 |             srcDirs = ['src/test/examplesAndroidP'] | 
 |         } | 
 |         output.resourcesDir = 'build/classes/examplesAndroidP' | 
 |     } | 
 |     examplesProto { | 
 |         java { | 
 |             srcDirs = ['src/test/examplesProto'] | 
 |         } | 
 |         compileClasspath = files("third_party/protobuf-lite/libprotobuf_lite.jar") | 
 |         compileClasspath += fileTree(dir: "build/generated/test/proto", include: "*.jar") | 
 |         output.resourcesDir = 'build/classes/examplesProto' | 
 |     } | 
 |     kotlinR8TestResources { | 
 |         java { | 
 |             srcDirs = ['src/test/kotlinR8TestResources'] | 
 |         } | 
 |         output.resourcesDir = 'build/classes/kotlinR8TestResources' | 
 |     } | 
 |     keepanno { | 
 |         java { | 
 |             srcDirs = ['src/keepanno/java'] | 
 |             include 'com/android/tools/r8/keepanno/annotations/*.java' | 
 |         } | 
 |     } | 
 | } | 
 |  | 
 | // Ensure importing into IntelliJ IDEA use the same output directories as Gradle. In tests we | 
 | // use the output path for tests (ultimately through ToolHelper.getClassPathForTests()) and | 
 | // therefore these paths need to be the same. See https://youtrack.jetbrains.com/issue/IDEA-175172 | 
 | // for context. | 
 | idea { | 
 |     sourceSets.all { SourceSet sources -> | 
 |         module { | 
 |             if (sources.name == "main") { | 
 |                 sourceDirs += sources.java.srcDirs | 
 |                 outputDir sources.output.classesDirs[0] | 
 |             } else { | 
 |                 testSourceDirs += sources.java.srcDirs | 
 |                 testOutputDir sources.output.classesDirs[0] | 
 |             } | 
 |         } | 
 |     } | 
 | } | 
 |  | 
 | configurations { | 
 |     supportLibs | 
 | } | 
 |  | 
 | dependencies { | 
 |     implementation "net.sf.jopt-simple:jopt-simple:$joptSimpleVersion" | 
 |     implementation "com.google.code.gson:gson:$gsonVersion" | 
 |     // Include all of guava when compiling the code, but exclude annotations that we don't | 
 |     // need from the packaging. | 
 |     compileOnly("com.google.guava:guava:$guavaVersion") | 
 |     implementation("com.google.guava:guava:$guavaVersion", { | 
 |         exclude group: 'com.google.errorprone' | 
 |         exclude group: 'com.google.code.findbugs' | 
 |         exclude group: 'com.google.j2objc' | 
 |         exclude group: 'org.codehaus.mojo' | 
 |     }) | 
 |     implementation group: 'it.unimi.dsi', name: 'fastutil', version: fastutilVersion | 
 |     implementation "org.jetbrains.kotlinx:kotlinx-metadata-jvm:$kotlinExtMetadataJVMVersion" | 
 |     implementation group: 'org.ow2.asm', name: 'asm', version: asmVersion | 
 |     implementation group: 'org.ow2.asm', name: 'asm-commons', version: asmVersion | 
 |     implementation group: 'org.ow2.asm', name: 'asm-tree', version: asmVersion | 
 |     implementation group: 'org.ow2.asm', name: 'asm-analysis', version: asmVersion | 
 |     implementation group: 'org.ow2.asm', name: 'asm-util', version: asmVersion | 
 |  | 
 |     main17Implementation "net.sf.jopt-simple:jopt-simple:$joptSimpleVersion" | 
 |     main17Implementation "com.google.code.gson:gson:$gsonVersion" | 
 |     // Include all of guava when compiling the code, but exclude annotations that we don't | 
 |     // need from the packaging. | 
 |     main17CompileOnly("com.google.guava:guava:$guavaVersion") | 
 |     main17Implementation("com.google.guava:guava:$guavaVersion", { | 
 |         exclude group: 'com.google.errorprone' | 
 |         exclude group: 'com.google.code.findbugs' | 
 |         exclude group: 'com.google.j2objc' | 
 |         exclude group: 'org.codehaus.mojo' | 
 |     }) | 
 |     main17Implementation group: 'it.unimi.dsi', name: 'fastutil', version: fastutilVersion | 
 |     main17Implementation "org.jetbrains.kotlinx:kotlinx-metadata-jvm:$kotlinExtMetadataJVMVersion" | 
 |     main17Implementation group: 'org.ow2.asm', name: 'asm', version: asmVersion | 
 |     main17Implementation group: 'org.ow2.asm', name: 'asm-commons', version: asmVersion | 
 |     main17Implementation group: 'org.ow2.asm', name: 'asm-tree', version: asmVersion | 
 |     main17Implementation group: 'org.ow2.asm', name: 'asm-analysis', version: asmVersion | 
 |     main17Implementation group: 'org.ow2.asm', name: 'asm-util', version: asmVersion | 
 |  | 
 |     examplesTestNGRunnerCompile group: 'org.testng', name: 'testng', version: testngVersion | 
 |  | 
 |     testCompile sourceSets.examples.output | 
 |     testCompile "junit:junit:$junitVersion" | 
 |     testCompile "com.google.guava:guava:$guavaVersion" | 
 |     testCompile "org.jetbrains.kotlin:kotlin-stdlib:$kotlinVersion" | 
 |     testCompile "org.jetbrains.kotlin:kotlin-reflect:$kotlinVersion" | 
 |     testCompile group: 'org.smali', name: 'smali', version: smaliVersion | 
 |     testCompile files('third_party/jasmin/jasmin-2.4.jar') | 
 |     testCompile files('third_party/jdwp-tests/apache-harmony-jdwp-tests-host.jar') | 
 |     testCompile files('third_party/ddmlib/ddmlib.jar') | 
 |     testCompile group: 'org.ow2.asm', name: 'asm', version: asmVersion | 
 |     testCompile group: 'org.ow2.asm', name: 'asm-commons', version: asmVersion | 
 |     testCompile group: 'org.ow2.asm', name: 'asm-tree', version: asmVersion | 
 |     testCompile group: 'org.ow2.asm', name: 'asm-analysis', version: asmVersion | 
 |     testCompile group: 'org.ow2.asm', name: 'asm-util', version: asmVersion | 
 |     testCompile group: 'it.unimi.dsi', name: 'fastutil', version: fastutilVersion | 
 |     testCompile group: 'org.javassist', name: 'javassist', version: javassistVersion | 
 |  | 
 |     examplesAndroidOCompile group: 'org.ow2.asm', name: 'asm', version: asmVersion | 
 |     examplesAndroidPCompile group: 'org.ow2.asm', name: 'asm', version: asmVersion | 
 |     // Import Guava for @Nullable annotation | 
 |     examplesCompile "com.google.guava:guava:$guavaVersion" | 
 |     examplesCompile "junit:junit:$junitVersion" | 
 |     examplesCompile "org.mockito:mockito-core:$mockitoVersion" | 
 |     supportLibs "com.android.support:support-v4:$androidSupportVersion" | 
 |     supportLibs "junit:junit:$junitVersion" | 
 |     supportLibs "com.android.support.test.espresso:espresso-core:$espressoVersion" | 
 |     apiUsageSampleCompile sourceSets.main.output | 
 |     apiUsageSampleCompile "com.google.guava:guava:$guavaVersion" | 
 |     kotlinR8TestResourcesCompileOnly "org.jetbrains.kotlin:kotlin-stdlib:$kotlinVersion" | 
 |     errorprone("com.google.errorprone:error_prone_core:$errorproneVersion") | 
 |  | 
 |     keepannoCompile group: 'org.ow2.asm', name: 'asm', version: asmVersion | 
 |     keepannoCompile "com.google.guava:guava:$guavaVersion" | 
 | } | 
 |  | 
 | def r8LibPath = "$buildDir/libs/r8lib.jar" | 
 | def r8LibExludeDepsPath = "$buildDir/libs/r8lib-exclude-deps.jar" | 
 | def r8DesugaredPath = "$buildDir/libs/r8desugared.jar" | 
 | def r8LibGeneratedKeepRulesPath = "$buildDir/generated/keep.txt" | 
 | def r8LibTestPath = "$buildDir/classes/r8libtest" | 
 | def java11ClassFiles = "$buildDir/classes/java/mainJava11" | 
 | def r8RetracePath = "$buildDir/libs/r8retrace.jar" | 
 | def r8RetraceExludeDepsPath = "$buildDir/libs/r8retrace-exclude-deps.jar" | 
 |  | 
 | def osString = OperatingSystem.current().isLinux() ? "linux" : | 
 |         OperatingSystem.current().isMacOsX() ? "mac" : "windows" | 
 |  | 
 | def cloudDependencies = [ | 
 |         "tests"      : [ | 
 |                 "2017-10-04/art", | 
 |                 "2016-12-19/art" | 
 |         ], | 
 |         "third_party": [ | 
 |                 "aapt2", | 
 |                 "android_cts_baseline", | 
 |                 "android_jar/libcore_latest", | 
 |                 "android_jar/lib-v14", | 
 |                 "android_jar/lib-v15", | 
 |                 "android_jar/lib-v19", | 
 |                 "android_jar/lib-v21", | 
 |                 "android_jar/lib-v22", | 
 |                 "android_jar/lib-v23", | 
 |                 "android_jar/lib-v24", | 
 |                 "android_jar/lib-v25", | 
 |                 "android_jar/lib-v26", | 
 |                 "android_jar/lib-v27", | 
 |                 "android_jar/lib-v28", | 
 |                 "android_jar/lib-v29", | 
 |                 "android_jar/lib-v30", | 
 |                 "android_jar/lib-v31", | 
 |                 "android_jar/lib-v32", | 
 |                 "android_jar/lib-v33", | 
 |                 "android_jar/lib-v34", | 
 |                 "android_jar/lib-master", | 
 |                 "api_database/api_database", | 
 |                 "api-outlining/simple-app-dump", | 
 |                 "binary_compatibility_tests/compiler_api_tests", | 
 |                 "bundletool/bundletool-1.11.0", | 
 |                 "core-lambda-stubs", | 
 |                 "dagger/2.41", | 
 |                 "dart-sdk", | 
 |                 "ddmlib", | 
 |                 "gradle/gradle", | 
 |                 "google/google-java-format/1.14.0", | 
 |                 "google-java-format", | 
 |                 "iosched_2019", | 
 |                 "jacoco/0.8.2", | 
 |                 "jacoco/0.8.6", | 
 |                 "jasmin", | 
 |                 "junit", | 
 |                 "jdwp-tests", | 
 |                 "jsr223-api-1.0", | 
 |                 "rhino-1.7.10", | 
 |                 "rhino-android-1.1.1", | 
 |                 "kotlin/kotlin-compiler-1.3.11", | 
 |                 "kotlin/kotlin-compiler-1.3.41", | 
 |                 "kotlin/kotlin-compiler-1.3.72", | 
 |                 "kotlin/kotlin-compiler-1.4.20", | 
 |                 "kotlin/kotlin-compiler-1.5.0", | 
 |                 "kotlin/kotlin-compiler-1.6.0", | 
 |                 "kotlin/kotlin-compiler-1.7.0", | 
 |                 "kotlin/kotlin-compiler-1.8.0", | 
 |                 "kotlinx-coroutines-1.3.6", | 
 |                 "multidex", | 
 |                 "openjdk/openjdk-rt-1.8", | 
 |                 "openjdk/desugar_jdk_libs", | 
 |                 "openjdk/desugar_jdk_libs_11", | 
 |                 "openjdk/desugar_jdk_libs_legacy", | 
 |                 "openjdk/desugar_jdk_libs_releases/1.0.9", | 
 |                 "openjdk/desugar_jdk_libs_releases/1.0.10", | 
 |                 "openjdk/desugar_jdk_libs_releases/1.1.0", | 
 |                 "openjdk/desugar_jdk_libs_releases/1.1.1", | 
 |                 "openjdk/desugar_jdk_libs_releases/1.1.5", | 
 |                 "openjdk/jdk-11-test", | 
 |                 "opensource-apps/tivi", | 
 |                 "proguard/proguard5.2.1", | 
 |                 "proguard/proguard6.0.1", | 
 |                 "proguard/proguard-7.0.0", | 
 |                 "retrace_benchmark", | 
 |                 "retrace/binary_compatibility", | 
 |                 "r8", | 
 |                 "r8-releases/2.0.74", | 
 |                 "r8-releases/3.2.54", | 
 |                 "r8mappings", | 
 |                 "tachiyomi" | 
 |         ], | 
 |         // All dex-vms have a fixed OS of Linux, as they are only supported on Linux, and will be run in a Docker | 
 |         // container on other platforms where supported. | 
 |         "tools"      : [ | 
 |                 "linux/art", | 
 |                 "linux/art-5.1.1", | 
 |                 "linux/art-6.0.1", | 
 |                 "linux/art-7.0.0", | 
 |                 "linux/art-8.1.0", | 
 |                 "linux/art-9.0.0", | 
 |                 "linux/art-10.0.0", | 
 |                 "linux/host/art-12.0.0-beta4", | 
 |                 "linux/host/art-13.0.0", | 
 |                 "linux/host/art-14.0.0-dp1", | 
 |                 "linux/host/art-master", | 
 |                 "linux/dalvik", | 
 |                 "linux/dalvik-4.0.4", | 
 |         ] | 
 | ] | 
 |  | 
 | def cloudSystemDependencies = [ | 
 |         linux: [ | 
 |                 "third_party": ["openjdk/openjdk-9.0.4/linux", | 
 |                                 "openjdk/jdk8/linux-x86", | 
 |                                 "openjdk/jdk-11/linux", | 
 |                                 "openjdk/jdk-17/linux", | 
 |                                 "openjdk/jdk-18/linux"], | 
 |         ], | 
 |         osx: [ | 
 |                 "third_party": ["openjdk/openjdk-9.0.4/osx", | 
 |                                 "openjdk/jdk8/darwin-x86", | 
 |                                 "openjdk/jdk-11/osx", | 
 |                                 "openjdk/jdk-17/osx", | 
 |                                 "openjdk/jdk-18/osx"], | 
 |         ], | 
 |         windows: [ | 
 |                 "third_party": ["openjdk/openjdk-9.0.4/windows", | 
 |                                 "openjdk/jdk-11/windows", | 
 |                                 "openjdk/jdk-17/windows", | 
 |                                 "openjdk/jdk-18/windows"], | 
 |         ], | 
 | ] | 
 |  | 
 | if (OperatingSystem.current().isWindows()) { | 
 |     cloudSystemDependencies.windows.each { entry -> | 
 |         cloudDependencies.get(entry.key).addAll(entry.value) | 
 |     } | 
 | } else if (OperatingSystem.current().isLinux()) { | 
 |     cloudSystemDependencies.linux.each { entry -> | 
 |         cloudDependencies.get(entry.key).addAll(entry.value) | 
 |     } | 
 | } else if (OperatingSystem.current().isMacOsX()) { | 
 |     cloudSystemDependencies.osx.each { entry -> | 
 |         cloudDependencies.get(entry.key).addAll(entry.value) | 
 |     } | 
 | } else { | 
 |     println "WARNING: Unsupported system: " + OperatingSystem.current() | 
 | } | 
 |  | 
 | def getDownloadDepsTaskName(entryKey, entryFile) { | 
 |     return "download_deps_${entryKey}_${entryFile.replace('/', '_').replace('\\', '_')}" | 
 | } | 
 |  | 
 | cloudDependencies.each { entry -> | 
 |     entry.value.each { entryFile -> | 
 |         task (getDownloadDepsTaskName(entry.key, entryFile), type: DownloadDependency) { | 
 |             type DownloadDependency.Type.GOOGLE_STORAGE | 
 |             dependency "${entry.key}/${entryFile}" | 
 |         } | 
 |     } | 
 | } | 
 |  | 
 | def x20Dependencies = [ | 
 |     "third_party": [ | 
 |         "benchmarks/kotlin-benches", | 
 |         "chrome/chrome_180917_ffbaa8", | 
 |         "chrome/chrome_200430", | 
 |         "chrome/monochrome_public_minimal_apks/chrome_200520", | 
 |         "chrome/clank_google3_prebuilt", | 
 |         "classlib", | 
 |         "cf_segments", | 
 |         "desugar/desugar_20180308", | 
 |         "internal/issue-127524985", | 
 |         "framework", | 
 |         "gmail/gmail_android_170604.16", | 
 |         "gmail/gmail_android_180826.15", | 
 |         "gmscore/gmscore_v10", | 
 |         "gmscore/latest", | 
 |         "nest/nest_20180926_7c6cfb", | 
 |         "proguard/proguard_internal_159423826", | 
 |         "proguardsettings", | 
 |         "proto", | 
 |         "protobuf-lite", | 
 |         "retrace_internal", | 
 |         "youtube/youtube.android_16.20", | 
 |         "youtube/youtube.android_17.19" | 
 |     ], | 
 | ] | 
 |  | 
 | x20Dependencies.each { entry -> | 
 |     entry.value.each { entryFile -> | 
 |         task "${getDownloadDepsTaskName(entry.key, entryFile)}"(type: DownloadDependency) { | 
 |             type DownloadDependency.Type.X20 | 
 |             dependency "${entry.key}/${entryFile}" | 
 |         } | 
 |     } | 
 | } | 
 |  | 
 | task downloadProguard { | 
 |     cloudDependencies.each { entry -> | 
 |         entry.value.each { entryFile -> | 
 |             if (entryFile.contains("proguard")) { | 
 |                 dependsOn "${getDownloadDepsTaskName(entry.key, entryFile)}" | 
 |             } | 
 |         } | 
 |     } | 
 | } | 
 |  | 
 | task downloadOpenJDKrt { | 
 |    cloudDependencies.each { entry -> | 
 |         entry.value.each { entryFile -> | 
 |             if (entryFile.contains("openjdk-rt")) { | 
 |                 dependsOn "${getDownloadDepsTaskName(entry.key, entryFile)}" | 
 |             } | 
 |         } | 
 |     } | 
 | } | 
 |  | 
 | task downloadAndroidCts { | 
 |     cloudDependencies.each { entry -> | 
 |         entry.value.each { entryFile -> | 
 |             if (entryFile.contains("android_cts_baseline")) { | 
 |                 dependsOn "${getDownloadDepsTaskName(entry.key, entryFile)}" | 
 |             } | 
 |         } | 
 |     } | 
 | } | 
 |  | 
 | task downloadCloudDeps() { | 
 |     cloudDependencies.each { entry -> | 
 |         entry.value.each { entryFile -> | 
 |             dependsOn "${getDownloadDepsTaskName(entry.key, entryFile)}" | 
 |         } | 
 |     } | 
 | } | 
 |  | 
 | task downloadX20Deps() { | 
 |     x20Dependencies.each { entry -> | 
 |         entry.value.each { entryFile -> | 
 |             dependsOn "${getDownloadDepsTaskName(entry.key, entryFile)}" | 
 |         } | 
 |     } | 
 | } | 
 |  | 
 | task downloadDeps { | 
 |     dependsOn downloadCloudDeps | 
 |     if (!project.hasProperty('no_internal')) { | 
 |         dependsOn downloadX20Deps | 
 |     } | 
 | } | 
 |  | 
 | allprojects { | 
 |     sourceCompatibility = JavaVersion.VERSION_1_8 | 
 |     targetCompatibility = JavaVersion.VERSION_1_8 | 
 | } | 
 |  | 
 | // TODO(ricow): Remove debug prints | 
 | println("NOTE: Current operating system: " + OperatingSystem.current()) | 
 | println("NOTE: Current operating system isWindows: " + OperatingSystem.current().isWindows()) | 
 |  | 
 | // Check if running with the JDK location from tools/jdk.py. | 
 | if (OperatingSystem.current().isWindows()) { | 
 |     println "NOTE: Running with JDK: " + org.gradle.internal.jvm.Jvm.current().javaHome | 
 |     compileJava.options.encoding = "UTF-8" | 
 |     compileTestJava.options.encoding = "UTF-8" | 
 | } else { | 
 |     def javaHomeOut = new StringBuilder() | 
 |     def javaHomeErr = new StringBuilder() | 
 |     def javaHomeProc = './tools/jdk.py'.execute([], projectDir) | 
 |     javaHomeProc.waitForProcessOutput(javaHomeOut, javaHomeErr) | 
 |     def jdkHome = new File(javaHomeOut.toString().trim()) | 
 |     if (!jdkHome.exists()) { | 
 |         println "WARNING: Failed to find the ./tools/jdk.py specified JDK: " + jdkHome | 
 |     } else if (jdkHome != org.gradle.internal.jvm.Jvm.current().javaHome) { | 
 |         println("WARNING: Gradle is running in a non-pinned Java" | 
 |                 + ". Gradle Java Home: " + org.gradle.internal.jvm.Jvm.current().javaHome | 
 |                 + ". Expected: " + jdkHome) | 
 |     } else { | 
 |         println("NOTE: Running with jdk from tools/jdk.py: " + jdkHome) | 
 |     } | 
 | } | 
 |  | 
 | compileJava.dependsOn downloadCloudDeps | 
 |  | 
 | sourceSets.configureEach { sourceSet -> | 
 |     tasks.named(sourceSet.compileJavaTaskName).configure { | 
 |         // Default disable errorprone (enabled and setup below). | 
 |         options.errorprone.enabled = false | 
 |         options.compilerArgs << '-Xlint:unchecked' | 
 |         // Run all compilation tasks in a forked subprocess. | 
 |         options.fork = true | 
 |         // Javac often runs out of stack space when compiling the tests. | 
 |         // Increase the stack size for the javac process. | 
 |         options.forkOptions.jvmArgs << "-Xss256m" | 
 |         // Test compilation is sometimes hitting the default limit at 1g, increase it. | 
 |         options.forkOptions.jvmArgs << "-Xmx3g" | 
 |         // Set the bootclass path so compilation is consistent with 1.8 target compatibility. | 
 |         options.forkOptions.jvmArgs << "-Xbootclasspath/a:third_party/openjdk/openjdk-rt-1.8/rt.jar" | 
 |     } | 
 | } | 
 |  | 
 | def setJdkCompilationWithCompatibility(String sourceSet, String javaHome, JavaVersion compatibility, boolean enablePreview) { | 
 |     tasks.named(sourceSet).get().configure { | 
 |         def jdkDir = "third_party/openjdk/${javaHome}/" | 
 |         options.fork = true | 
 |         options.forkOptions.jvmArgs = [] | 
 |         if (enablePreview) { | 
 |             options.compilerArgs.add('--enable-preview') | 
 |         } | 
 |         if (OperatingSystem.current().isLinux()) { | 
 |             dependsOn getDownloadDepsTaskName("third_party", "openjdk/" + javaHome + "/linux") | 
 |             options.forkOptions.javaHome = file(jdkDir + 'linux') | 
 |         } else if (OperatingSystem.current().isMacOsX()) { | 
 |             dependsOn getDownloadDepsTaskName("third_party", "openjdk/" + javaHome + "/osx") | 
 |             options.forkOptions.javaHome = compatibility > JavaVersion.VERSION_1_9 | 
 |                     ? file(jdkDir + 'osx/Contents/Home') | 
 |                     : file(jdkDir + 'osx') | 
 |         } else { | 
 |             dependsOn getDownloadDepsTaskName("third_party", "openjdk/" + javaHome + "/windows") | 
 |             options.forkOptions.javaHome = file(jdkDir + 'windows') | 
 |         } | 
 |         sourceCompatibility = compatibility | 
 |         targetCompatibility = compatibility | 
 |     } | 
 | } | 
 |  | 
 | setJdkCompilationWithCompatibility( | 
 |         sourceSets.main.compileJavaTaskName, | 
 |         'jdk-11', | 
 |         JavaVersion.VERSION_11, | 
 |         false); | 
 |  | 
 | setJdkCompilationWithCompatibility( | 
 |         sourceSets.examplesJava9.compileJavaTaskName, | 
 |         'openjdk-9.0.4', | 
 |         JavaVersion.VERSION_1_9, | 
 |         false) | 
 | setJdkCompilationWithCompatibility( | 
 |         sourceSets.examplesJava10.compileJavaTaskName, | 
 |         'jdk-11', | 
 |         JavaVersion.VERSION_1_10, | 
 |         false) | 
 | setJdkCompilationWithCompatibility( | 
 |         sourceSets.main17.compileJavaTaskName, | 
 |         'jdk-17', | 
 |         JavaVersion.VERSION_17, | 
 |         false) | 
 | setJdkCompilationWithCompatibility( | 
 |         sourceSets.examplesJava11.compileJavaTaskName, | 
 |         'jdk-11', | 
 |         JavaVersion.VERSION_11, | 
 |         false) | 
 | setJdkCompilationWithCompatibility( | 
 |         sourceSets.examplesTestNGRunner.compileJavaTaskName, | 
 |         'jdk-11', | 
 |         JavaVersion.VERSION_11, | 
 |         false) | 
 | setJdkCompilationWithCompatibility( | 
 |         sourceSets.examplesJava17.compileJavaTaskName, | 
 |         'jdk-17', | 
 |         JavaVersion.VERSION_17, | 
 |         false) | 
 | setJdkCompilationWithCompatibility( | 
 |         sourceSets.examplesJava18.compileJavaTaskName, | 
 |         'jdk-18', | 
 |         // TODO(b/218293990): Update Gradle to get JavaVersion.VERSION_18. | 
 |         JavaVersion.VERSION_17, | 
 |         false) | 
 |  | 
 | task provideJdk11TestsDependencies(type: org.gradle.api.tasks.Copy) { | 
 |     from sourceSets.examplesTestNGRunner.compileClasspath | 
 |     include "**/**.jar" | 
 |     into file("$buildDir/test/jdk11Tests") | 
 | } | 
 |  | 
 | task compileTestNGRunner (type: JavaCompile) { | 
 |     dependsOn provideJdk11TestsDependencies | 
 |     destinationDir = file("$buildDir/classes/java/examplesTestNGRunner") | 
 |     source = sourceSets.examplesTestNGRunner.allSource | 
 |     classpath = sourceSets.examplesTestNGRunner.compileClasspath | 
 | } | 
 |  | 
 | if (!project.hasProperty('without_error_prone') && | 
 |         // Don't enable error prone on Java 8 as the plugin setup does not support it. | 
 |         !org.gradle.internal.jvm.Jvm.current().javaVersion.java8) { | 
 |     compileJava { | 
 |  | 
 |         // Enable error prone for D8/R8 main sources and make all warnings errors. | 
 |         // Warnings that we have chosen not to fix (or suppress) are disabled outright below. | 
 |         options.compilerArgs << "-Werror" | 
 |         options.errorprone.enabled = true | 
 |  | 
 |         // Non-default / Experimental checks - explicitly enforced. | 
 |         options.errorprone.check('RemoveUnusedImports', CheckSeverity.ERROR) | 
 |         options.errorprone.check('InconsistentOverloads', CheckSeverity.ERROR) | 
 |         options.errorprone.check('MissingDefault', CheckSeverity.ERROR) | 
 |         options.errorprone.check('MultipleTopLevelClasses', CheckSeverity.ERROR) | 
 |         options.errorprone.check('NarrowingCompoundAssignment', CheckSeverity.ERROR) | 
 |  | 
 |         // TODO(b/270510095): These should likely be fixed/suppressed and become hard failures. | 
 |         options.errorprone.check('UnusedVariable', CheckSeverity.OFF) | 
 |         options.errorprone.check('EqualsUnsafeCast', CheckSeverity.OFF) | 
 |         options.errorprone.check('TypeParameterUnusedInFormals', CheckSeverity.OFF) | 
 |         options.errorprone.check('ImmutableEnumChecker', CheckSeverity.OFF) | 
 |         options.errorprone.check('BadImport', CheckSeverity.OFF) | 
 |         options.errorprone.check('ComplexBooleanConstant', CheckSeverity.OFF) | 
 |         options.errorprone.check('StreamToIterable', CheckSeverity.OFF) | 
 |         options.errorprone.check('HidingField', CheckSeverity.OFF) | 
 |         options.errorprone.check('StreamResourceLeak', CheckSeverity.OFF) | 
 |         options.errorprone.check('CatchAndPrintStackTrace', CheckSeverity.OFF) | 
 |         options.errorprone.check('NonCanonicalType', CheckSeverity.OFF) | 
 |         options.errorprone.check('UnusedNestedClass', CheckSeverity.OFF) | 
 |         options.errorprone.check('AmbiguousMethodReference', CheckSeverity.OFF) | 
 |         options.errorprone.check('InvalidParam', CheckSeverity.OFF) | 
 |         options.errorprone.check('CharacterGetNumericValue', CheckSeverity.OFF) | 
 |         options.errorprone.check('ModifyCollectionInEnhancedForLoop', CheckSeverity.OFF) | 
 |         options.errorprone.check('EmptyCatch', CheckSeverity.OFF) | 
 |         options.errorprone.check('ArgumentSelectionDefectChecker', CheckSeverity.OFF) | 
 |         options.errorprone.check('ImmutableAnnotationChecker', CheckSeverity.OFF) | 
 |         options.errorprone.check('ObjectToString', CheckSeverity.OFF) | 
 |         options.errorprone.check('DoNotClaimAnnotations', CheckSeverity.OFF) | 
 |         options.errorprone.check('AnnotateFormatMethod', CheckSeverity.OFF) | 
 |  | 
 |         // TODO(b/270537614): Remove finalize uses. | 
 |         options.errorprone.check('Finalize', CheckSeverity.OFF) | 
 |  | 
 |         // The following warnings could/should be active but are hit by R8 now so silence them. | 
 |         options.errorprone.check('EqualsGetClass', CheckSeverity.OFF) | 
 |         options.errorprone.check('MixedMutabilityReturnType', CheckSeverity.OFF) | 
 |         options.errorprone.check('UnnecessaryParentheses', CheckSeverity.OFF) | 
 |         options.errorprone.check('DoNotCallSuggester', CheckSeverity.OFF) | 
 |         options.errorprone.check('InlineMeSuggester', CheckSeverity.OFF) | 
 |         options.errorprone.check('MutablePublicArray', CheckSeverity.OFF) | 
 |         options.errorprone.check('DefaultCharset', CheckSeverity.OFF) | 
 |         options.errorprone.check('InconsistentCapitalization', CheckSeverity.OFF) | 
 |         options.errorprone.check('InlineFormatString', CheckSeverity.OFF) | 
 |         options.errorprone.check('MissingImplementsComparable', CheckSeverity.OFF) | 
 |  | 
 |         // Warnings that cause unwanted edits (e.g., inability to write informative asserts). | 
 |         options.errorprone.check('AlreadyChecked', CheckSeverity.OFF) | 
 |  | 
 |         // JavaDoc related warnings. Would be nice to resolve but of no real consequence. | 
 |         options.errorprone.check('InvalidLink', CheckSeverity.OFF) | 
 |         options.errorprone.check('InvalidBlockTag', CheckSeverity.OFF) | 
 |         options.errorprone.check('InvalidInlineTag', CheckSeverity.OFF) | 
 |         options.errorprone.check('EmptyBlockTag', CheckSeverity.OFF) | 
 |         options.errorprone.check('MissingSummary', CheckSeverity.OFF) | 
 |         options.errorprone.check('UnrecognisedJavadocTag', CheckSeverity.OFF) | 
 |         options.errorprone.check('AlmostJavadoc', CheckSeverity.OFF) | 
 |  | 
 |         // Moving away from identity and canonical items is not planned. | 
 |         options.errorprone.check('ReferenceEquality', CheckSeverity.OFF) | 
 |         options.errorprone.check('IdentityHashMapUsage', CheckSeverity.OFF) | 
 |     } | 
 | } | 
 |  | 
 | task consolidatedLicense { | 
 |     def license = new File(new File(buildDir, 'generatedLicense'), 'LICENSE') | 
 |  | 
 |     inputs.files files('LICENSE', 'LIBRARY-LICENSE') + fileTree(dir: 'library-licensing') | 
 |     def runtimeClasspath = configurations.findByName("runtimeClasspath") | 
 |     inputs.files { runtimeClasspath.getResolvedConfiguration().files } | 
 |  | 
 |     outputs.files license | 
 |  | 
 |     doLast { | 
 |         def dependencies = [] | 
 |         runtimeClasspath.resolvedConfiguration.resolvedArtifacts.each { | 
 |             def identifier = (ModuleComponentIdentifier) it.id.componentIdentifier | 
 |             dependencies.add("${identifier.group}:${identifier.module}") | 
 |         } | 
 |         def libraryLicenses = file('LIBRARY-LICENSE').text | 
 |         dependencies.each { | 
 |             if (!libraryLicenses.contains("- artifact: $it")) { | 
 |                  throw new GradleException("No license for $it in LIBRARY_LICENSE") | 
 |             } | 
 |         } | 
 |  | 
 |         license.getParentFile().mkdirs() | 
 |         license.createNewFile() | 
 |         license.text = "This file lists all licenses for code distributed.\n" | 
 |         license.text += "All non-library code has the following 3-Clause BSD license.\n" | 
 |         license.text += "\n" | 
 |         license.text += "\n" | 
 |         license.text += file('LICENSE').text | 
 |         license.text += "\n" | 
 |         license.text += "\n" | 
 |         license.text += "Summary of distributed libraries:\n" | 
 |         license.text += "\n" | 
 |         license.text += libraryLicenses | 
 |         license.text += "\n" | 
 |         license.text += "\n" | 
 |         license.text += "Licenses details:\n" | 
 |         fileTree(dir: 'library-licensing').getFiles().stream().sorted().forEach { file -> | 
 |             license.text += "\n" | 
 |             license.text += "\n" | 
 |             license.text += file.text | 
 |         } | 
 |     } | 
 | } | 
 |  | 
 | def repackageDepFile(file) { | 
 |     if (file.getName().endsWith('.jar')) { | 
 |         return zipTree(file).matching { | 
 |             exclude '**/module-info.class' | 
 |             exclude 'META-INF/maven/**' | 
 |             exclude 'META-INF/LICENSE.txt' | 
 |             exclude 'META-INF/MANIFEST.MF' | 
 |         } | 
 |     } else { | 
 |         return fileTree(file) | 
 |     } | 
 | } | 
 |  | 
 | task repackageDeps(type: Jar) { | 
 |     dependsOn downloadCloudDeps | 
 |     dependsOn project.configurations.runtimeClasspath | 
 |     project.configurations.runtimeClasspath.forEach { | 
 |         from repackageDepFile(it) | 
 |     } | 
 |     archiveFileName = 'deps_all.jar' | 
 | } | 
 |  | 
 | task repackageTestDeps(type: Jar) { | 
 |     dependsOn downloadCloudDeps | 
 |     dependsOn project.configurations.testCompile | 
 |     project.configurations.testCompile.forEach { | 
 |         from repackageDepFile(it) | 
 |     } | 
 |     archiveFileName = 'test_deps_all.jar' | 
 | } | 
 |  | 
 | task repackageSources(type: Jar) { | 
 |     // If this fails then remove all generated folders from | 
 |     // build/classes/java/test that is not {com,dalvik} | 
 |     from sourceSets.main.output | 
 |     archiveFileName = 'sources_main.jar' | 
 | } | 
 |  | 
 | task repackageSources17(type: Jar) { | 
 |     from sourceSets.main17.output | 
 |     archiveFileName = 'sources_main_17.jar' | 
 | } | 
 |  | 
 | def r8CreateTask(name, baseName, sources, includeLibraryLicenses, includeSwissArmyKnife) { | 
 |     return tasks.create("r8Create${name}", Jar) { | 
 |         entryCompression ZipEntryCompression.STORED | 
 |         dependsOn sources | 
 |         dependsOn files('LICENSE') | 
 |         if (includeLibraryLicenses) { | 
 |             from consolidatedLicense.outputs.files | 
 |         } else { | 
 |             from files('LICENSE') | 
 |         } | 
 |         from sources.collect { zipTree(it) } | 
 |         exclude "$buildDir/classes/**" | 
 |         archiveFileName = baseName | 
 |         if (includeSwissArmyKnife) { | 
 |             manifest { | 
 |                 attributes 'Main-Class': 'com.android.tools.r8.SwissArmyKnife' | 
 |             } | 
 |         } | 
 |         exclude "META-INF/*.kotlin_module" | 
 |         exclude "**/*.kotlin_metadata" | 
 |     } | 
 | } | 
 |  | 
 | def r8RelocateTask(r8Task, output) { | 
 |     return tasks.create("r8Relocate_${r8Task.name}", Exec) { | 
 |         dependsOn r8WithDeps | 
 |         dependsOn r8Task | 
 |         outputs.file output | 
 |         workingDir = projectDir | 
 |         inputs.files r8Task.outputs.files + r8WithDeps.outputs.files | 
 |         commandLine baseCompilerCommandLine([ | 
 |                 "relocator", | 
 |                 "--input", | 
 |                 r8Task.outputs.files[0], | 
 |                 "--output", | 
 |                 output, | 
 |                 "--map", | 
 |                 "com.google.common->com.android.tools.r8.com.google.common", | 
 |                 "--map", | 
 |                 "com.google.gson->com.android.tools.r8.com.google.gson", | 
 |                 "--map", | 
 |                 "com.google.thirdparty->com.android.tools.r8.com.google.thirdparty", | 
 |                 "--map", | 
 |                 "joptsimple->com.android.tools.r8.joptsimple", | 
 |                 "--map", | 
 |                 "org.objectweb.asm->com.android.tools.r8.org.objectweb.asm", | 
 |                 "--map", | 
 |                 "it.unimi.dsi.fastutil->com.android.tools.r8.it.unimi.dsi.fastutil", | 
 |                 "--map", | 
 |                 "kotlin->com.android.tools.r8.jetbrains.kotlin", | 
 |                 "--map", | 
 |                 "kotlinx->com.android.tools.r8.jetbrains.kotlinx", | 
 |                 "--map", | 
 |                 "org.jetbrains->com.android.tools.r8.org.jetbrains", | 
 |                 "--map", | 
 |                 "org.intellij->com.android.tools.r8.org.intellij", | 
 |                 "--map", | 
 |                 "org.checkerframework->com.android.tools.r8.org.checkerframework" | 
 |         ]) | 
 |     } | 
 | } | 
 |  | 
 | task r8WithDeps { | 
 |     dependsOn repackageSources | 
 |     dependsOn repackageDeps | 
 |     inputs.files ([repackageSources.outputs, repackageDeps.outputs]) | 
 |     def r8Task = r8CreateTask( | 
 |             'WithDeps', | 
 |             'r8_with_deps.jar', | 
 |             repackageSources.outputs.files + repackageDeps.outputs.files, | 
 |             true, | 
 |             true) | 
 |     dependsOn r8Task | 
 |     outputs.files r8Task.outputs.files | 
 | } | 
 |  | 
 | task r8WithDeps17 { | 
 |     dependsOn repackageSources17 | 
 |     dependsOn repackageDeps | 
 |     inputs.files ([repackageSources17.outputs, repackageDeps.outputs]) | 
 |     def r8Task = r8CreateTask( | 
 |             'WithDeps17', | 
 |             'r8_with_deps_17.jar', | 
 |             repackageSources17.outputs.files + repackageDeps.outputs.files, | 
 |             true, | 
 |             true) | 
 |     dependsOn r8Task | 
 |     outputs.files r8Task.outputs.files | 
 | } | 
 |  | 
 | task r8WithRelocatedDeps { | 
 |     def output = "${buildDir}/libs/r8_with_relocated_deps.jar" | 
 |     dependsOn r8RelocateTask(r8WithDeps, output) | 
 |     inputs.files r8WithDeps.outputs.files | 
 |     outputs.file output | 
 | } | 
 |  | 
 | task r8WithRelocatedDeps17 { | 
 |     def output = "${buildDir}/libs/r8_with_relocated_deps_17.jar" | 
 |     dependsOn r8RelocateTask(r8WithDeps17, output) | 
 |     inputs.files r8WithDeps17.outputs.files | 
 |     outputs.file output | 
 | } | 
 |  | 
 | task r8WithoutDeps { | 
 |     dependsOn repackageSources | 
 |     inputs.files repackageSources.outputs | 
 |     def r8Task = r8CreateTask( | 
 |             'WithoutDeps', | 
 |             'r8_without_deps.jar', | 
 |             repackageSources.outputs.files, | 
 |             false, | 
 |             true) | 
 |     dependsOn r8Task | 
 |     outputs.files r8Task.outputs.files | 
 | } | 
 |  | 
 | task r8(type: Copy) { | 
 |     def r8Task = project.hasProperty("exclude_deps") | 
 |             ? r8WithoutDeps : r8WithRelocatedDeps | 
 |     dependsOn r8Task | 
 |     from r8Task.outputs.files[0] | 
 |     into file("${buildDir}/libs") | 
 |     rename { String fileName -> "r8.jar" } | 
 |     outputs.file "${buildDir}/libs/r8.jar" | 
 | } | 
 |  | 
 | task r8NoManifestWithoutDeps { | 
 |     dependsOn repackageSources | 
 |     inputs.files repackageSources.outputs | 
 |     def r8Task = r8CreateTask( | 
 |             'NoManifestWithoutDeps', | 
 |             'r8_no_manifest_without_deps.jar', | 
 |             repackageSources.outputs.files, | 
 |             false, | 
 |             false) | 
 |     dependsOn r8Task | 
 |     outputs.files r8Task.outputs.files | 
 | } | 
 |  | 
 | task r8NoManifestWithDeps { | 
 |     dependsOn repackageSources | 
 |     inputs.files ([repackageSources.outputs, repackageDeps.outputs]) | 
 |     def r8Task = r8CreateTask( | 
 |             'NoManifestWithDeps', | 
 |             'r8_no_manifest_with_deps.jar', | 
 |             repackageSources.outputs.files + repackageDeps.outputs.files, | 
 |             true, | 
 |             false) | 
 |     dependsOn r8Task | 
 |     outputs.files r8Task.outputs.files | 
 | } | 
 |  | 
 | task r8NoManifestWithRelocatedDeps { | 
 |     def output = "${buildDir}/libs/r8_no_manifest_with_relocated_deps.jar" | 
 |     dependsOn r8RelocateTask(r8NoManifestWithDeps, output) | 
 |     inputs.files r8NoManifestWithDeps.outputs.files | 
 |     outputs.file output | 
 | } | 
 |  | 
 | task r8NoManifest(type: Copy) { | 
 |     def r8Task = project.hasProperty("exclude_deps") | 
 |             ? r8NoManifestWithoutDeps : r8NoManifestWithRelocatedDeps | 
 |     dependsOn r8Task | 
 |     from r8Task.outputs.files[0] | 
 |     into file("${buildDir}/libs") | 
 |     rename { String fileName -> "r8_no_manifest.jar" } | 
 |     outputs.file "${buildDir}/libs/r8_no_manifest.jar" | 
 | } | 
 |  | 
 | def baseCompilerCommandLine(compiler, args = []) { | 
 |     // Execute r8 commands against a stable r8 with dependencies. | 
 |     // TODO(b/139725780): See if we can remove or lower the heap size (-Xmx8g). | 
 |     return [org.gradle.internal.jvm.Jvm.current().getJavaExecutable(), | 
 |             "-Xmx8g", "-ea", "-jar", r8WithDeps.outputs.files[0]] + compiler + args | 
 | } | 
 |  | 
 | def baseR8CommandLine(args = []) { | 
 |     // Execute r8 commands against a stable r8 with dependencies. | 
 |     return baseCompilerCommandLine("r8", args) | 
 | } | 
 |  | 
 | def baseD8CommandLine(args = []) { | 
 |     // Execute r8 commands against a stable r8 with dependencies. | 
 |     return baseCompilerCommandLine("d8", args) | 
 | } | 
 |  | 
 | def r8CfCommandLine(input, output, pgConfs = [], args = ["--release"], libs = []) { | 
 |     def allArgs = [ | 
 |             "--classfile", | 
 |             input, | 
 |             "--output", output, | 
 |             "--pg-map-output", output + ".map", | 
 |             "--lib", org.gradle.internal.jvm.Jvm.current().javaHome, | 
 |     ] + args + libs.collectMany { ["--lib", it] } + pgConfs.collectMany { ["--pg-conf", it] } | 
 |     return baseR8CommandLine(allArgs) | 
 | } | 
 |  | 
 | def d8CfCommandLine(input, output, args = ["--release"], libs = []) { | 
 |     def allArgs = [ | 
 |             "--classfile", | 
 |             input, | 
 |             "--output", output, | 
 |             "--lib", "third_party/openjdk/openjdk-rt-1.8/rt.jar" | 
 |     ] + args + libs.collectMany { ["--lib", it] } | 
 |     return baseD8CommandLine(allArgs) | 
 | } | 
 |  | 
 | def r8LibCreateTask(name, pgConfs = [], r8Task, output, libs = [], classpath = [], excldeps=false) { | 
 |     return tasks.create("r8Lib${name}", Exec) { | 
 |         inputs.files ([pgConfs, r8WithRelocatedDeps.outputs, r8Task.outputs]) | 
 |         outputs.file output | 
 |         dependsOn downloadOpenJDKrt | 
 |         dependsOn r8WithRelocatedDeps | 
 |         dependsOn r8Task | 
 |         commandLine ([ | 
 |                 "python3", "tools/create_r8lib.py", | 
 |                 "--r8jar", r8Task.outputs.files[0], | 
 |                 "--output", output] | 
 |                 + (excldeps ? ['--excldeps-variant'] : []) | 
 |                 + (pgConfs.collectMany { ["--pg-conf", it] }) | 
 |                 + (libs.collectMany { ["--lib", it] }) | 
 |                 + (classpath.collectMany { ["--classpath", it] })) | 
 |         workingDir = projectDir | 
 |     } | 
 | } | 
 |  | 
 | task rawBuildLibraryDesugarConversions(type: Zip, dependsOn: downloadDeps) { | 
 |     from sourceSets.libraryDesugarConversions.output | 
 |     include "java/**/*.class" | 
 |     baseName 'library_desugar_conversions_raw' | 
 |     destinationDir file('build/tmp/desugaredlibrary') | 
 | } | 
 |  | 
 | task buildLibraryDesugarConversions(type: CustomConversionAsmRewriterTask, dependsOn: rawBuildLibraryDesugarConversions) { | 
 |     rawJar = file("build/tmp/desugaredlibrary/library_desugar_conversions_raw.zip") | 
 |     outputDirectory = file("build/libs") | 
 | } | 
 |  | 
 | task testJarSources(type: Jar, dependsOn: [testClasses, buildLibraryDesugarConversions]) { | 
 |     archiveFileName = "r8testsbase.jar" | 
 |     from sourceSets.test.output | 
 |     // We only want to include tests that use R8 when generating keep rules for applymapping. | 
 |     include "com/android/tools/r8/**" | 
 |     include "android/**" | 
 |     include "dalvik/**" | 
 | } | 
 |  | 
 | task testJar(type: Exec) { | 
 |     dependsOn r8WithDeps | 
 |     dependsOn testJarSources | 
 |     def output = "$buildDir/libs/r8tests.jar" | 
 |     outputs.file output | 
 |     workingDir = projectDir | 
 |     inputs.files (testJarSources.outputs.files + r8WithDeps.outputs.files) | 
 |     commandLine baseCompilerCommandLine([ | 
 |             "relocator", | 
 |             "--input", | 
 |             testJarSources.outputs.files[0], | 
 |             "--output", | 
 |             output, | 
 |             "--map", | 
 |             "kotlinx.metadata->com.android.tools.r8.jetbrains.kotlinx.metadata" | 
 |     ]) | 
 | } | 
 |  | 
 | task generateR8LibKeepRules(type: Exec) { | 
 |     // Depend on r8WithRelocatedDeps to ensure that we do not have external | 
 |     // dependencies crossing the boundary. | 
 |     dependsOn r8WithDeps | 
 |     dependsOn r8NoManifestWithRelocatedDeps | 
 |     dependsOn testJar | 
 |     dependsOn repackageTestDeps | 
 |     dependsOn downloadOpenJDKrt | 
 |     inputs.files ([ | 
 |             r8WithDeps.outputs, | 
 |             r8NoManifestWithRelocatedDeps.outputs, | 
 |             repackageDeps.outputs, | 
 |             repackageTestDeps.outputs, | 
 |             testJar.outputs]) | 
 |     outputs.file r8LibGeneratedKeepRulesPath | 
 |     commandLine baseCompilerCommandLine([ | 
 |             "tracereferences", | 
 |             "--keep-rules", | 
 |             "--allowobfuscation", | 
 |             "--lib", | 
 |             "third_party/openjdk/openjdk-rt-1.8/rt.jar", | 
 |             "--lib", | 
 |             repackageDeps.outputs.files[0], | 
 |             "--lib", | 
 |             repackageTestDeps.outputs.files[0], | 
 |             "--target", | 
 |             r8NoManifestWithRelocatedDeps.outputs.files[0], | 
 |             "--source", | 
 |             testJar.outputs.files[0], | 
 |             "--output", | 
 |             r8LibGeneratedKeepRulesPath]) | 
 |     workingDir = projectDir | 
 | } | 
 |  | 
 | task R8Lib { | 
 |     dependsOn r8LibCreateTask( | 
 |             "Main", | 
 |             ["src/main/keep.txt", generateR8LibKeepRules.outputs.files[0]], | 
 |             r8NoManifestWithRelocatedDeps, | 
 |             r8LibPath, | 
 |     ).dependsOn(generateR8LibKeepRules) | 
 |     inputs.files r8NoManifestWithRelocatedDeps.outputs.files | 
 |     outputs.file r8LibPath | 
 | } | 
 |  | 
 | task R8LibNoDeps { | 
 |     dependsOn r8LibCreateTask( | 
 |             "MainNoDeps", | 
 |             ["src/main/keep.txt"], | 
 |             r8NoManifestWithoutDeps, | 
 |             r8LibExludeDepsPath, | 
 |             [], | 
 |             repackageDeps.outputs.files, | 
 |             true, | 
 |     ).dependsOn(repackageDeps) | 
 |     inputs.files ([r8NoManifestWithoutDeps.outputs, repackageDeps.outputs]) | 
 |     outputs.file r8LibExludeDepsPath | 
 | } | 
 |  | 
 | task R8Desugared(type: Exec) { | 
 |     dependsOn downloadOpenJDKrt | 
 |     dependsOn r8NoManifestWithRelocatedDeps | 
 |     inputs.files r8NoManifestWithRelocatedDeps.outputs.files | 
 |     commandLine d8CfCommandLine( | 
 |             r8NoManifestWithRelocatedDeps.outputs.files[0], | 
 |             r8DesugaredPath, | 
 |             ["--release"]) | 
 |     workingDir = projectDir | 
 |     outputs.file r8DesugaredPath | 
 | } | 
 |  | 
 | task R8Retrace { | 
 |     dependsOn R8Lib | 
 |     dependsOn r8LibCreateTask( | 
 |             "Retrace", | 
 |             ["src/main/keep_retrace.txt"], | 
 |             R8Lib, | 
 |             r8RetracePath, | 
 |     ).dependsOn(R8Lib) | 
 |     outputs.file r8RetracePath | 
 | } | 
 |  | 
 | task R8RetraceNoDeps { | 
 |     dependsOn R8LibNoDeps | 
 |     dependsOn r8LibCreateTask( | 
 |             "RetraceNoDeps", | 
 |             ["src/main/keep_retrace.txt"], | 
 |             R8LibNoDeps, | 
 |             r8RetraceExludeDepsPath, | 
 |             [], | 
 |             repackageDeps.outputs.files, | 
 |             true, | 
 |     ).dependsOn(R8LibNoDeps) | 
 |     outputs.file r8RetraceExludeDepsPath | 
 | } | 
 |  | 
 | task sourceJar(type: Jar, dependsOn: classes) { | 
 |     classifier = 'src' | 
 |     from sourceSets.main.allSource | 
 | } | 
 |  | 
 | task keepAnnoJar(type: Jar) { | 
 |     archiveFileName = "keepanno-annotations.jar" | 
 |     from sourceSets.keepanno.output | 
 | } | 
 |  | 
 | artifacts { | 
 |     archives sourceJar | 
 | } | 
 |  | 
 | task createArtTests(type: Exec) { | 
 |     def outputDir = "build/generated/test/java/com/android/tools/r8/art" | 
 |     def createArtTestsScript = "tools/create_art_tests.py" | 
 |     inputs.files files("tests/2017-10-04/art.tar.gz", createArtTestsScript) | 
 |     outputs.dir outputDir | 
 |     dependsOn downloadDeps | 
 |     commandLine "python3", createArtTestsScript | 
 |     workingDir = projectDir | 
 | } | 
 |  | 
 | compileTestJava { | 
 |     dependsOn createArtTests | 
 | } | 
 |  | 
 | task buildCfSegments(type: Jar, dependsOn: downloadDeps) { | 
 |     from sourceSets.cfSegments.output | 
 |     archiveFileName = 'cf_segments.jar' | 
 |     destinationDir file('build/libs') | 
 | } | 
 |  | 
 | task buildR8ApiUsageSample(type: Jar) { | 
 |     from sourceSets.apiUsageSample.output | 
 |     archiveFileName = 'r8_api_usage_sample.jar' | 
 |     destinationDir file('tests') | 
 | } | 
 |  | 
 | task buildApiSampleJars { | 
 |     dependsOn buildR8ApiUsageSample | 
 | } | 
 |  | 
 | task buildDebugTestResourcesJars { | 
 |     def resourcesDir = file("src/test/debugTestResources") | 
 |     def hostJar = "debug_test_resources.jar" | 
 |     task "compile_debugTestResources"(type: JavaCompile) { | 
 |         source = fileTree(dir: resourcesDir, include: '**/*.java') | 
 |         destinationDir = file("build/test/debugTestResources/classes") | 
 |         classpath = sourceSets.main.compileClasspath | 
 |         sourceCompatibility = JavaVersion.VERSION_1_7 | 
 |         targetCompatibility = JavaVersion.VERSION_1_7 | 
 |         options.compilerArgs += ["-g", "-Xlint:-options"] | 
 |     } | 
 |     task "jar_debugTestResources"(type: Jar, dependsOn: "compile_debugTestResources") { | 
 |         archiveName = hostJar | 
 |         destinationDir = file("build/test/") | 
 |         from "build/test/debugTestResources/classes" | 
 |         include "**/*.class" | 
 |     } | 
 |     def java8ResourcesDir = file("src/test/debugTestResourcesJava8") | 
 |     def java8HostJar = "debug_test_resources_java8.jar" | 
 |     task "compile_debugTestResourcesJava8"(type: JavaCompile) { | 
 |         source = fileTree(dir: java8ResourcesDir, include: '**/*.java') | 
 |         destinationDir = file("build/test/debugTestResourcesJava8/classes") | 
 |         classpath = sourceSets.main.compileClasspath | 
 |         sourceCompatibility = JavaVersion.VERSION_1_8 | 
 |         targetCompatibility = JavaVersion.VERSION_1_8 | 
 |         options.compilerArgs += ["-g", "-Xlint:-options"] | 
 |     } | 
 |     task "jar_debugTestResourcesJava8"(type: Jar, dependsOn: "compile_debugTestResourcesJava8") { | 
 |         archiveName = java8HostJar | 
 |         destinationDir = file("build/test/") | 
 |         from "build/test/debugTestResourcesJava8/classes" | 
 |         include "**/*.class" | 
 |     } | 
 |     dependsOn downloadDeps | 
 |     dependsOn jar_debugTestResources | 
 |     dependsOn jar_debugTestResourcesJava8 | 
 | } | 
 |  | 
 | // Examples used by tests, where Android specific APIs are used. | 
 | task buildExampleAndroidApi(type: JavaCompile) { | 
 |     source = fileTree(dir: file("src/test/examplesAndroidApi"), include: "**/*.java") | 
 |     destinationDir = file("build/test/examplesAndroidApi/classes") | 
 |     classpath = files("third_party/android_jar/lib-v26/android.jar") | 
 |     sourceCompatibility = JavaVersion.VERSION_1_8 | 
 |     targetCompatibility = JavaVersion.VERSION_1_8 | 
 | } | 
 |  | 
 | task buildProtoGeneratedSources { | 
 |     def examplesProtoDir = file("src/test/examplesProto") | 
 |     examplesProtoDir.eachDir { dir -> | 
 |         def name = dir.getName() | 
 |         task "compile_proto_generated_source_${name}"(type: JavaCompile) { | 
 |             source = { | 
 |                 file('third_party/proto').listFiles() | 
 |                         .findAll { it.name.startsWith(name) && it.name.endsWith('-src.jar') } | 
 |                         .collect { zipTree(it) } | 
 |             } | 
 |             destinationDir = file("build/generated/test/proto/${name}_classes") | 
 |             classpath = files("third_party/protobuf-lite/libprotobuf_lite.jar") | 
 |             sourceCompatibility = JavaVersion.VERSION_1_8 | 
 |             targetCompatibility = JavaVersion.VERSION_1_8 | 
 |         } | 
 |         task "jar_proto_generated_source_${name}"(type: Jar, dependsOn: "compile_proto_generated_source_${name}") { | 
 |             archiveName = "${name}.jar" | 
 |             destinationDir = file("build/generated/test/proto") | 
 |             from "build/generated/test/proto/${name}_classes" | 
 |             include "/**/*.class" | 
 |         } | 
 |         dependsOn "jar_proto_generated_source_${name}" | 
 |     } | 
 | } | 
 |  | 
 | task buildExamplesProto { | 
 |     def examplesProtoDir = file("src/test/examplesProto") | 
 |     def examplesProtoOutputDir = file("build/test/examplesProto"); | 
 |     dependsOn buildProtoGeneratedSources | 
 |     task "compile_examples_proto"(type: JavaCompile) { | 
 |         source = fileTree(dir: examplesProtoDir, include: "**/*.java") | 
 |         destinationDir = file("build/test/examplesProto/classes") | 
 |         classpath = files("third_party/protobuf-lite/libprotobuf_lite.jar") | 
 |         classpath += fileTree(dir: "build/generated/test/proto", include: "*.jar") | 
 |         sourceCompatibility = JavaVersion.VERSION_1_8 | 
 |         targetCompatibility = JavaVersion.VERSION_1_8 | 
 |     } | 
 |     examplesProtoDir.eachDir { dir -> | 
 |         def name = dir.getName() | 
 |         task "jar_examples_proto_${name}"(type: Jar, dependsOn: "compile_examples_proto") { | 
 |             archiveName = "${name}.jar" | 
 |             destinationDir = examplesProtoOutputDir | 
 |             from "build/test/examplesProto/classes" | 
 |             include name + "/**/*.class" | 
 |         } | 
 |         dependsOn "jar_examples_proto_${name}" | 
 |     } | 
 | } | 
 |  | 
 | // Proto lite generated code yields warnings when compiling with javac. | 
 | // We change the options passed to javac to ignore it. | 
 | compileExamplesJava.options.compilerArgs = ["-Xlint:none"] | 
 |  | 
 |  | 
 | task buildExampleJars { | 
 |     dependsOn downloadProguard | 
 |     def examplesDir = file("src/test/examples") | 
 |     def proguardScript | 
 |     if (OperatingSystem.current().isWindows()) { | 
 |         proguardScript = "third_party/proguard/proguard5.2.1/bin/proguard.bat" | 
 |     } else { | 
 |         proguardScript = "third_party/proguard/proguard5.2.1/bin/proguard.sh" | 
 |     } | 
 |     task extractExamplesRuntime(type: Sync) { | 
 |         dependsOn configurations.examplesRuntime | 
 |         from { configurations.examplesRuntime.collect { zipTree(it) } } | 
 |         include "**/*.class" | 
 |         includeEmptyDirs false | 
 |         into "$buildDir/runtime/examples/" | 
 |     } | 
 |  | 
 |     task "copy_examples_resources"(type: org.gradle.api.tasks.Copy) { | 
 |         from examplesDir | 
 |         exclude "**/*.java" | 
 |         exclude "**/keep-rules*.txt" | 
 |         into file("build/test/examples/classes") | 
 |     } | 
 |  | 
 |     task "compile_examples"(type: JavaCompile) { | 
 |         dependsOn "copy_examples_resources" | 
 |         source examplesDir | 
 |         include "**/*.java" | 
 |         destinationDir = file("build/test/examples/classes") | 
 |         classpath = sourceSets.examples.compileClasspath | 
 |         sourceCompatibility = JavaVersion.VERSION_1_7 | 
 |         targetCompatibility = JavaVersion.VERSION_1_7 | 
 |         options.compilerArgs = ["-g:source,lines", "-Xlint:none"] | 
 |     } | 
 |     task "compile_examples_debuginfo_all"(type: JavaCompile) { | 
 |         source examplesDir | 
 |         include "**/*.java" | 
 |         destinationDir = file("build/test/examples/classes_debuginfo_all") | 
 |         classpath = sourceSets.examples.compileClasspath | 
 |         sourceCompatibility = JavaVersion.VERSION_1_7 | 
 |         targetCompatibility = JavaVersion.VERSION_1_7 | 
 |         options.compilerArgs = ["-g", "-Xlint:none"] | 
 |     } | 
 |     task "compile_examples_debuginfo_none"(type: JavaCompile) { | 
 |         source examplesDir | 
 |         include "**/*.java" | 
 |         destinationDir = file("build/test/examples/classes_debuginfo_none") | 
 |         classpath = sourceSets.examples.compileClasspath | 
 |         sourceCompatibility = JavaVersion.VERSION_1_7 | 
 |         targetCompatibility = JavaVersion.VERSION_1_7 | 
 |         options.compilerArgs = ["-g:none", "-Xlint:none"] | 
 |     } | 
 |     examplesDir.eachDir { dir -> | 
 |         def name = dir.getName(); | 
 |         def exampleOutputDir = file("build/test/examples"); | 
 |         def jarName = "${name}.jar" | 
 |         dependsOn "jar_example_${name}" | 
 |         dependsOn "jar_example_${name}_debuginfo_all" | 
 |         dependsOn "jar_example_${name}_debuginfo_none" | 
 |         dependsOn "extractExamplesRuntime" | 
 |         def runtimeDependencies = copySpec { } | 
 |         // The "throwing" test verifies debugging/stack info on the post-proguarded output. | 
 |         def proguardConfigPath = "${dir}/proguard.cfg" | 
 |         if (new File(proguardConfigPath).exists()) { | 
 |             task "pre_proguard_example_${name}"(type: Jar, dependsOn: "compile_examples") { | 
 |                 archiveName = "${name}_pre_proguard.jar" | 
 |                 destinationDir = exampleOutputDir | 
 |                 from "build/test/examples/classes" | 
 |                 include name + "/**/*.class" | 
 |                 with runtimeDependencies | 
 |                 includeEmptyDirs false | 
 |             } | 
 |             def jarPath = files(tasks.getByPath("pre_proguard_example_${name}")).files.first(); | 
 |             def proguardJarPath = "${exampleOutputDir}/${jarName}" | 
 |             def proguardMapPath = "${exampleOutputDir}/${name}/${name}.map" | 
 |             task "jar_example_${name}"(type: Exec, dependsOn: "pre_proguard_example_${name}") { | 
 |                 inputs.files files( | 
 |                         tasks.getByPath("pre_proguard_example_${name}"), | 
 |                         proguardConfigPath) | 
 |                 // Enable these to get stdout and stderr redirected to files... | 
 |                 // standardOutput = new FileOutputStream('proguard.stdout') | 
 |                 // errorOutput = new FileOutputStream('proguard.stderr') | 
 |                 def proguardArguments = "-verbose -dontwarn java.** -injars ${jarPath}" + | 
 |                         " -outjars ${proguardJarPath}" + | 
 |                         " -include ${proguardConfigPath}" + | 
 |                         " -printmapping ${proguardMapPath}" | 
 |                 if (OperatingSystem.current().isWindows()) { | 
 |                     executable "${proguardScript}" | 
 |                     args "${proguardArguments}" | 
 |                 } else { | 
 |                     executable "bash" | 
 |                     args "-c", "${proguardScript} '${proguardArguments}'" | 
 |                 } | 
 |                 outputs.file proguardJarPath | 
 |             } | 
 |             // TODO: Consider performing distinct proguard compilations. | 
 |             task "jar_example_${name}_debuginfo_all"(type: Copy, dependsOn: "jar_example_${name}") { | 
 |                 from "${exampleOutputDir}/${name}.jar" | 
 |                 into "${exampleOutputDir}" | 
 |                 rename(".*", "${name}_debuginfo_all.jar") | 
 |             } | 
 |             task "jar_example_${name}_debuginfo_none"(type: Copy, dependsOn: "jar_example_${name}") { | 
 |                 from "${exampleOutputDir}/${name}.jar" | 
 |                 into "${exampleOutputDir}" | 
 |                 rename(".*", "${name}_debuginfo_none.jar") | 
 |             } | 
 |         } else { | 
 |             task "jar_example_${name}"(type: Jar, dependsOn: "compile_examples") { | 
 |                 archiveName = "${name}.jar" | 
 |                 destinationDir = exampleOutputDir | 
 |                 from "build/test/examples/classes" | 
 |                 include name + "/**/*" | 
 |                 with runtimeDependencies | 
 |                 includeEmptyDirs true | 
 |             } | 
 |             task "jar_example_${name}_debuginfo_all"(type: Jar, dependsOn: "compile_examples_debuginfo_all") { | 
 |                 archiveName = "${name}_debuginfo_all.jar" | 
 |                 destinationDir = exampleOutputDir | 
 |                 from "build/test/examples/classes_debuginfo_all" | 
 |                 include name + "/**/*.class" | 
 |                 with runtimeDependencies | 
 |                 includeEmptyDirs false | 
 |             } | 
 |             task "jar_example_${name}_debuginfo_none"(type: Jar, dependsOn: "compile_examples_debuginfo_none") { | 
 |                 archiveName = "${name}_debuginfo_none.jar" | 
 |                 destinationDir = exampleOutputDir | 
 |                 from "build/test/examples/classes_debuginfo_none" | 
 |                 include name + "/**/*.class" | 
 |                 with runtimeDependencies | 
 |                 includeEmptyDirs false | 
 |             } | 
 |         } | 
 |     } | 
 | } | 
 |  | 
 | task buildExampleAndroidNJars { | 
 |     dependsOn downloadDeps | 
 |     def examplesDir = file("src/test/examplesAndroidN") | 
 |     task "compile_examplesAndroidN"(type: JavaCompile) { | 
 |         source = fileTree(dir: examplesDir, include: '**/*.java') | 
 |         destinationDir = file("build/test/examplesAndroidN/classes") | 
 |         classpath = sourceSets.main.compileClasspath | 
 |         sourceCompatibility = JavaVersion.VERSION_1_8 | 
 |         targetCompatibility = JavaVersion.VERSION_1_8 | 
 |         options.compilerArgs += ["-Xlint:-options"] | 
 |     } | 
 |     examplesDir.eachDir { dir -> | 
 |         def name = dir.getName(); | 
 |         def exampleOutputDir = file("build/test/examplesAndroidN"); | 
 |         def jarName = "${name}.jar" | 
 |         dependsOn "jar_examplesAndroidN_${name}" | 
 |         task "jar_examplesAndroidN_${name}"(type: Jar, dependsOn: "compile_examplesAndroidN") { | 
 |             archiveName = jarName | 
 |             destinationDir = exampleOutputDir | 
 |             from "build/test/examplesAndroidN/classes" | 
 |             include "**/" + name + "/**/*.class" | 
 |         } | 
 |     } | 
 | } | 
 |  | 
 |  | 
 | task buildExampleAndroidOJars { | 
 |     dependsOn downloadDeps | 
 |     def examplesDir = file("src/test/examplesAndroidO") | 
 |     // NOTE: we want to enable a scenario when test needs to reference some | 
 |     // classes generated by legacy (1.6) Java compiler to test some specific | 
 |     // behaviour. To do so we compile all the java files located in sub-directory | 
 |     // called 'legacy' with Java 1.6, then compile the rest of the files with | 
 |     // Java 1.8 and a reference to previously generated 1.6 classes. | 
 |  | 
 |     // Compiling all classes in dirs 'legacy' with old Java version. | 
 |     task "compile_examplesAndroidO_Legacy"(type: JavaCompile) { | 
 |         source = fileTree(dir: examplesDir, include: '**/legacy/**/*.java') | 
 |         destinationDir = file("build/test/examplesAndroidOLegacy/classes") | 
 |         classpath = sourceSets.main.compileClasspath | 
 |         sourceCompatibility = JavaVersion.VERSION_1_6 | 
 |         targetCompatibility = JavaVersion.VERSION_1_6 | 
 |         options.compilerArgs += ["-Xlint:-options", "-parameters"] | 
 |     } | 
 |     // Compiling the rest of the files as Java 1.8 code. | 
 |     task "compile_examplesAndroidO"(type: JavaCompile) { | 
 |         dependsOn "compile_examplesAndroidO_Legacy" | 
 |         source = fileTree(dir: examplesDir, include: '**/*.java', exclude: '**/legacy/**/*.java') | 
 |         destinationDir = file("build/test/examplesAndroidO/classes") | 
 |         classpath = sourceSets.main.compileClasspath | 
 |         classpath += files("build/test/examplesAndroidOLegacy/classes") | 
 |         sourceCompatibility = JavaVersion.VERSION_1_8 | 
 |         targetCompatibility = JavaVersion.VERSION_1_8 | 
 |         options.compilerArgs += ["-Xlint:-options", "-parameters"] | 
 |     } | 
 |     examplesDir.eachDir { dir -> | 
 |         def name = dir.getName(); | 
 |         def destinationDir = file("build/test/examplesAndroidO/classes"); | 
 |         if (file("src/test/examplesAndroidO/" + name + "/TestGenerator.java").isFile()) { | 
 |             task "generate_examplesAndroidO_${name}"(type: JavaExec, | 
 |                     dependsOn: "compile_examplesAndroidO") { | 
 |                 main = name + ".TestGenerator" | 
 |                 classpath = files(destinationDir, sourceSets.main.compileClasspath) | 
 |                 args destinationDir | 
 |             } | 
 |         } else { | 
 |             task "generate_examplesAndroidO_${name}" () {} | 
 |         } | 
 |     } | 
 |     examplesDir.eachDir { dir -> | 
 |         def name = dir.getName(); | 
 |         def exampleOutputDir = file("build/test/examplesAndroidO"); | 
 |         def jarName = "${name}.jar" | 
 |         dependsOn "jar_examplesAndroidO_${name}" | 
 |         task "jar_examplesAndroidO_${name}"(type: Jar, dependsOn: ["compile_examplesAndroidO", | 
 |                 "generate_examplesAndroidO_${name}"]) { | 
 |             archiveName = jarName | 
 |             destinationDir = exampleOutputDir | 
 |             from "build/test/examplesAndroidO/classes"        // Java 1.8 classes | 
 |             from "build/test/examplesAndroidOLegacy/classes"  // Java 1.6 classes | 
 |             include "**/" + name + "/**/*.class" | 
 |             // Do not include generator into the test runtime jar, it is not useful. | 
 |             // Otherwise, shrinking will need ASM jars. | 
 |             exclude "**/TestGenerator*" | 
 |         } | 
 |     } | 
 | } | 
 |  | 
 | task buildExampleAndroidPJars { | 
 |     dependsOn downloadDeps | 
 |     def examplesDir = file("src/test/examplesAndroidP") | 
 |  | 
 |     task "compile_examplesAndroidP"(type: JavaCompile) { | 
 |         source = fileTree(dir: examplesDir, include: '**/*.java') | 
 |         destinationDir = file("build/test/examplesAndroidP/classes") | 
 |         classpath = sourceSets.main.compileClasspath | 
 |         sourceCompatibility = JavaVersion.VERSION_1_8 | 
 |         targetCompatibility = JavaVersion.VERSION_1_8 | 
 |         options.compilerArgs += ["-Xlint:-options"] | 
 |     } | 
 |     examplesDir.eachDir { dir -> | 
 |         def name = dir.getName(); | 
 |         def destinationDir = file("build/test/examplesAndroidP/classes"); | 
 |         if (file("src/test/examplesAndroidP/" + name + "/TestGenerator.java").isFile()) { | 
 |             task "generate_examplesAndroidP_${name}"(type: JavaExec, | 
 |                     dependsOn: "compile_examplesAndroidP") { | 
 |                 main = name + ".TestGenerator" | 
 |                 classpath = files(destinationDir, sourceSets.main.compileClasspath) | 
 |                 args destinationDir | 
 |             } | 
 |         } else { | 
 |             task "generate_examplesAndroidP_${name}" () {} | 
 |         } | 
 |     } | 
 |     examplesDir.eachDir { dir -> | 
 |         def name = dir.getName(); | 
 |         def exampleOutputDir = file("build/test/examplesAndroidP"); | 
 |         def jarName = "${name}.jar" | 
 |         dependsOn "jar_examplesAndroidP_${name}" | 
 |         task "jar_examplesAndroidP_${name}"(type: Jar, | 
 |                 dependsOn: ["compile_examplesAndroidP", | 
 |                             "generate_examplesAndroidP_${name}"]) { | 
 |             archiveName = jarName | 
 |             destinationDir = exampleOutputDir | 
 |             from "build/test/examplesAndroidP/classes"  // Java 1.8 classes | 
 |             include "**/" + name + "/**/*.class" | 
 |             // Do not include generator into the test runtime jar, it is not useful. | 
 |             // Otherwise, shrinking will need ASM jars. | 
 |             exclude "**/TestGenerator*" | 
 |         } | 
 |     } | 
 | } | 
 |  | 
 | def buildExampleJarsCreateTask(javaVersion, sourceSet) { | 
 |     return tasks.create("buildExample${javaVersion}Jars") { | 
 |         def examplesDir = file("src/test/examples${javaVersion}") | 
 |         examplesDir.eachDir { dir -> | 
 |             def name = dir.getName(); | 
 |             def exampleOutputDir = file("build/test/examples${javaVersion}"); | 
 |             def jarName = "${name}.jar" | 
 |             dependsOn "jar_examples${javaVersion}_${name}" | 
 |             task "jar_examples${javaVersion}_${name}"(type: Jar) { | 
 |                 archiveName = jarName | 
 |                 destinationDir = exampleOutputDir | 
 |                 from sourceSet.output | 
 |                 include "**/" + name + "/**/*.class" | 
 |             } | 
 |         } | 
 |     } | 
 | } | 
 |  | 
 | buildExampleJarsCreateTask("Java9", sourceSets.examplesJava9) | 
 | buildExampleJarsCreateTask("Java10", sourceSets.examplesJava10) | 
 | buildExampleJarsCreateTask("Java11", sourceSets.examplesJava11) | 
 | buildExampleJarsCreateTask("Java17", sourceSets.examplesJava17) | 
 | buildExampleJarsCreateTask("Java18", sourceSets.examplesJava18) | 
 |  | 
 | task provideArtFrameworksDependencies { | 
 |     cloudDependencies.tools.forEach({ art -> | 
 |         if (art.contains("art")) { | 
 |             def taskName = art.replace('/','_') | 
 |             dependsOn "patch_${taskName}" | 
 |             task "patch_${taskName}"(type: org.gradle.api.tasks.Copy){ | 
 |                 from "tools/${art}/framework" | 
 |                 include "**.jar" | 
 |                 into file("tools/${art}/out/host/linux-x86/framework") | 
 |             } | 
 |         } | 
 |     }) | 
 | } | 
 |  | 
 | task buildKotlinR8TestResources { | 
 |     def examplesDir = file("src/test/kotlinR8TestResources") | 
 |     examplesDir.eachDir { dir -> | 
 |         kotlin.Kotlinc.KotlinTargetVersion.values().each { kotlinTargetVersion -> | 
 |             def name = dir.getName() | 
 |             def taskName = "jar_kotlinR8TestResources_${name}_${kotlinTargetVersion}" | 
 |             def javaOutput = "build/test/kotlinR8TestResources/${kotlinTargetVersion}/${name}/java" | 
 |             def javaOutputJarName = "${name}.java.jar" | 
 |             def javaOutputJarDir = "build/test/kotlinR8TestResources/${kotlinTargetVersion}" | 
 |             task "${taskName}Java"(type: JavaCompile) { | 
 |                 source = fileTree(dir: file("${examplesDir}/${name}"), include: '**/*.java') | 
 |                 destinationDir = file(javaOutput) | 
 |                 classpath = sourceSets.main.compileClasspath | 
 |                 sourceCompatibility = JavaVersion.VERSION_1_6 | 
 |                 targetCompatibility = JavaVersion.VERSION_1_6 | 
 |                 options.compilerArgs += ["-g", "-Xlint:-options"] | 
 |             } | 
 |             task "${taskName}JavaJar"(type: Jar, dependsOn: "${taskName}Java") { | 
 |                 archiveName = javaOutputJarName | 
 |                 destinationDir = file(javaOutputJarDir) | 
 |                 from javaOutput | 
 |                 include "**/*.class" | 
 |             } | 
 |             dependsOn "${taskName}JavaJar" | 
 |         } | 
 |     } | 
 | } | 
 |  | 
 | task buildExamples { | 
 |     if (OperatingSystem.current().isMacOsX() || OperatingSystem.current().isWindows()) { | 
 |         logger.lifecycle("WARNING: Testing (including building examples) is only partially supported on your " + | 
 |                 "platform (" + OperatingSystem.current().getName() + ").") | 
 |     } else if (!OperatingSystem.current().isLinux()) { | 
 |       logger.lifecycle("WARNING: Testing (including building examples) is not supported on your platform. " + | 
 |           "It is fully supported on Linux and partially supported on Mac OS and Windows") | 
 |       return; | 
 |     } | 
 |     dependsOn buildDebugTestResourcesJars | 
 |     dependsOn buildExampleJars | 
 |     dependsOn buildExampleAndroidNJars | 
 |     dependsOn buildExampleAndroidOJars | 
 |     dependsOn buildExampleAndroidPJars | 
 |     dependsOn buildExampleJava9Jars | 
 |     dependsOn buildExampleJava10Jars | 
 |     dependsOn buildExampleJava11Jars | 
 |     dependsOn buildExampleJava17Jars | 
 |     dependsOn buildExampleJava18Jars | 
 |     dependsOn buildExampleAndroidApi | 
 |     def examplesDir = file("src/test/examples") | 
 |     examplesDir.eachDir { dir -> | 
 |         def exampleOutputDir = file("build/test/examples/" + dir.getName()); | 
 |         if (!exampleOutputDir.exists()) { | 
 |           exampleOutputDir.mkdirs() | 
 |         } | 
 |     } | 
 | } | 
 |  | 
 | task buildSmali { | 
 |     def smaliDir = file("src/test/smali") | 
 |     smaliDir.eachDirRecurse() { dir -> | 
 |         def name = dir.getName(); | 
 |         def relativeDir = smaliDir.toPath().relativize(dir.toPath()); | 
 |         def smaliOutputDir = file("build/test/smali/" + relativeDir); | 
 |         smaliOutputDir.mkdirs() | 
 |         outputs.dir smaliOutputDir | 
 |         def taskName = "smali_build_${relativeDir.toString().replace('/', '_').replace('\\', '_')}" | 
 |         def smaliFiles = fileTree(dir: dir, include: '*.smali') | 
 |         def javaFiles = fileTree(dir: dir, include: '*.java') | 
 |         def destDir = smaliOutputDir; | 
 |         def destFile = destDir.toPath().resolve("${name}.dex").toFile() | 
 |         def intermediateFileName = "${name}-intermediate.dex"; | 
 |         def intermediateFile = destDir.toPath().resolve(intermediateFileName).toFile() | 
 |         if (javaFiles.empty) { | 
 |             if (!smaliFiles.empty) { | 
 |                 dependsOn "${taskName}_smali" | 
 |                 task "${taskName}_smali"(type: SmaliTask) { | 
 |                     source = smaliFiles | 
 |                     destination = destFile | 
 |                 } | 
 |             } | 
 |         } else { | 
 |             dependsOn "${taskName}_smali" | 
 |             dependsOn "${taskName}_jar" | 
 |             task "${taskName}_smali"(type: SmaliTask) { | 
 |                 source = smaliFiles | 
 |                 destination = destFile | 
 |             } | 
 |             task "${taskName}_java"(type: JavaCompile) { | 
 |                 source = javaFiles | 
 |                 destinationDir destDir | 
 |                 classpath = sourceSets.main.compileClasspath | 
 |                 sourceCompatibility = JavaVersion.VERSION_1_7 | 
 |                 targetCompatibility = JavaVersion.VERSION_1_7 | 
 |                 options.compilerArgs += ["-Xlint:-options"] | 
 |             } | 
 |             task "${taskName}_jar"(type: Jar, dependsOn: "${taskName}_java") { | 
 |                 archiveName = "Test.jar" | 
 |                 destinationDir = destDir | 
 |                 from fileTree(dir: destDir, include: 'Test.class') | 
 |             } | 
 |         } | 
 |     } | 
 | } | 
 |  | 
 | tasks.withType(Test) { | 
 |     println("NOTE: Number of processors " + Runtime.runtime.availableProcessors()) | 
 |     def userDefinedCoresPerFork = System.getenv('R8_GRADLE_CORES_PER_FORK') | 
 |     def processors = Runtime.runtime.availableProcessors() | 
 |     // See https://docs.gradle.org/current/dsl/org.gradle.api.tasks.testing.Test.html. | 
 |     if (userDefinedCoresPerFork) { | 
 |       maxParallelForks = processors.intdiv(userDefinedCoresPerFork.toInteger()) ?: 1 | 
 |     } else { | 
 |       // On normal work machines this seems to give the best test execution time (without freezing) | 
 |       maxParallelForks = processors.intdiv(3) ?: 1 | 
 |       // On low cpu count machines (bots) we under subscribe, so increase the count. | 
 |       if (processors == 8) { | 
 |         maxParallelForks = 3 | 
 |       } | 
 |     } | 
 |     println("NOTE: Max parallel forks " + maxParallelForks) | 
 |  | 
 |     forkEvery = 0 | 
 |     if (project.hasProperty('disable_assertions')) { | 
 |         enableAssertions = false | 
 |     } | 
 |     // TODO(b/124091860): Increase the max heap size to avoid OOM when running tests. | 
 |     if (project.hasProperty('test_xmx')) { | 
 |       maxHeapSize = project.property('test_xmx') | 
 |     } else { | 
 |       maxHeapSize = "4G" | 
 |     } | 
 | } | 
 |  | 
 | task buildPreNJdwpTestsJar(type: Jar) { | 
 |     archiveFileName = 'jdwp-tests-preN.jar' | 
 |     from zipTree('third_party/jdwp-tests/apache-harmony-jdwp-tests-host.jar') | 
 |     // Exclude the classes containing java8 | 
 |     exclude 'org/apache/harmony/jpda/tests/jdwp/InterfaceType/*.class' | 
 |     exclude 'org/apache/harmony/jpda/tests/jdwp/ObjectReference/InvokeMethodDefault*.class' | 
 |     includeEmptyDirs = false | 
 | } | 
 |  | 
 | task getJarsFromSupportLibs(type: GetJarsFromConfiguration) { | 
 |     setConfiguration(configurations.supportLibs) | 
 | } | 
 |  | 
 | task generateR8TestKeepRules { | 
 |     def path = "build/generated/r8tests-keep.txt" | 
 |     outputs.file path | 
 |     dependsOn R8Lib | 
 |     doLast { | 
 |         file(path).write """-keep class ** { *; } | 
 | -dontshrink | 
 | -dontoptimize | 
 | -keepattributes * | 
 | -applymapping ${R8Lib.outputs.files[0]}.map | 
 | """ | 
 |     } | 
 | } | 
 |  | 
 | task buildR8LibCfTestDeps(type: Exec) { | 
 |     def outputPath = "build/libs/r8libtestdeps-cf.jar" | 
 |     dependsOn downloadDeps | 
 |     dependsOn r8NoManifest | 
 |     dependsOn R8Lib | 
 |     dependsOn generateR8TestKeepRules | 
 |     dependsOn testJar | 
 |     // Take all .jar files as libraries and append the generated test classes in classes/java/test. | 
 |     def addedLibraries = sourceSets.test.runtimeClasspath.findAll { pkg -> | 
 |         return pkg.toString().endsWith(".jar") | 
 |     } + ["${buildDir}/classes/java/test"] | 
 |     inputs.files testJar.outputs.files + | 
 |             generateR8TestKeepRules.outputs.files + | 
 |             R8Lib.outputs | 
 |     commandLine = r8CfCommandLine( | 
 |             testJar.outputs.files[0], | 
 |             outputPath, | 
 |             [generateR8TestKeepRules.outputs.files[0]], | 
 |             ["--debug", "--classpath", r8NoManifest.outputs.files[0]], | 
 |             r8NoManifest.outputs.files + addedLibraries) | 
 |     workingDir = projectDir | 
 |     outputs.file outputPath | 
 | } | 
 |  | 
 | task configureTestForR8Lib(type: Copy) { | 
 |     dependsOn testJar | 
 |     inputs.files buildR8LibCfTestDeps.outputs | 
 |     dependsOn R8Lib | 
 |     delete r8LibTestPath | 
 |     from zipTree(buildR8LibCfTestDeps.outputs.files[0]) | 
 |     def examplesDir = file("build/test") | 
 |     examplesDir.eachDir { dir -> | 
 |         from ("${buildDir}/test/${dir.getName()}/classes") | 
 |     } | 
 |     from ("${buildDir}/runtime/examples") | 
 |     into r8LibTestPath | 
 |     outputs.dir r8LibTestPath | 
 | } | 
 |  | 
 | def shouldRetrace() { | 
 |     return project.hasProperty('r8lib') || project.hasProperty('r8lib_no_deps') | 
 | } | 
 |  | 
 | def retrace(Throwable exception) { | 
 |     def out = new StringBuffer() | 
 |     def err = new StringBuffer() | 
 |     def command = "python3 tools/retrace.py --quiet" | 
 |     def header = "RETRACED STACKTRACE"; | 
 |     out.append("\n--------------------------------------\n") | 
 |     out.append("${header}\n") | 
 |     out.append("--------------------------------------\n") | 
 |     Process process = command.execute() | 
 |     def processIn = new PrintStream(process.getOut()) | 
 |     process.consumeProcessOutput(out, err) | 
 |     exception.printStackTrace(processIn) | 
 |     processIn.flush() | 
 |     processIn.close() | 
 |     def errorDuringRetracing = process.waitFor() != 0 | 
 |     if (errorDuringRetracing) { | 
 |         out.append("ERROR DURING RETRACING\n") | 
 |         out.append(err.toString()) | 
 |     } | 
 |     if (project.hasProperty('print_obfuscated_stacktraces') || errorDuringRetracing) { | 
 |         out.append("\n\n--------------------------------------\n") | 
 |         out.append("OBFUSCATED STACKTRACE\n") | 
 |         out.append("--------------------------------------\n") | 
 |     } | 
 |     return out.toString() | 
 | } | 
 |  | 
 | def printStackTrace(TestResult result) { | 
 |     filterStackTraces(result) | 
 |     if (shouldRetrace()) { | 
 |         def exception = new Exception(retrace(result.exception)) | 
 |         exception.setStackTrace([] as StackTraceElement[]) | 
 |         result.exceptions.add(0, exception) | 
 |     } | 
 | } | 
 |  | 
 | def filterStackTraces(TestResult result) { | 
 |     for (Throwable throwable : result.getExceptions()) { | 
 |         filterStackTrace(throwable) | 
 |     } | 
 | } | 
 |  | 
 | // It would be nice to do this in a non-destructive way... | 
 | def filterStackTrace(Throwable exception) { | 
 |     if (!project.hasProperty('print_full_stacktraces')) { | 
 |         def elements = [] | 
 |         def skipped = [] | 
 |         for (StackTraceElement element : exception.getStackTrace()) { | 
 |             if (element.toString().contains("com.android.tools.r8")) { | 
 |                 elements.addAll(skipped) | 
 |                 elements.add(element) | 
 |                 skipped.clear() | 
 |             } else { | 
 |                 skipped.add(element) | 
 |             } | 
 |         } | 
 |         exception.setStackTrace(elements as StackTraceElement[]) | 
 |     } | 
 | } | 
 |  | 
 | def printAllStackTracesToFile(List<Throwable> exceptions, File out) { | 
 |     new PrintStream(new FileOutputStream(out)).withCloseable {printer -> | 
 |         exceptions.forEach { it.printStackTrace(printer) } | 
 |     } | 
 | } | 
 |  | 
 | static def escapeHtml(String string) { | 
 |     return string.replace("&", "&").replace("<", "<").replace(">", ">") | 
 | } | 
 |  | 
 | static def urlEncode(String string) { | 
 |     // Not sure why, but the + also needs to be converted to have working links. | 
 |     return URLEncoder.encode(string, "UTF-8").replace("+","%20") | 
 | } | 
 |  | 
 | def ensureDir(File dir) { | 
 |     dir.mkdirs() | 
 |     return dir | 
 | } | 
 |  | 
 | // Some of our test parameters have new lines :-( We really don't want test names to span lines. | 
 | static def sanitizedTestName(testDesc) { | 
 |     if (testDesc.getName().contains("\n")) { | 
 |         throw new RuntimeException("Unsupported use of newline in test name: '${testDesc.getName()}'") | 
 |     } | 
 |     return testDesc.getName() | 
 | } | 
 |  | 
 | static def desanitizedTestName(testName) { | 
 |     return testName | 
 | } | 
 |  | 
 | def getTestReportEntryDir(reportDir, testDesc) { | 
 |     return ensureDir(reportDir.toPath() | 
 |             .resolve(testDesc.getClassName()) | 
 |             .resolve(sanitizedTestName(testDesc)) | 
 |             .toFile()) | 
 | } | 
 |  | 
 | def getTestReportEntryURL(reportDir, testDesc) { | 
 |     def classDir = urlEncode(testDesc.getClassName()) | 
 |     def testDir = urlEncode(sanitizedTestName(testDesc)) | 
 |     return "file://${reportDir}/${classDir}/${testDir}" | 
 | } | 
 |  | 
 | def getTestResultEntryOutputFile(reportDir, testDesc, fileName) { | 
 |     def dir = getTestReportEntryDir(reportDir, testDesc).toPath() | 
 |     return dir.resolve(fileName).toFile() | 
 | } | 
 |  | 
 | def withTestResultEntryWriter(reportDir, testDesc, fileName, append, fn) { | 
 |     def file = getTestResultEntryOutputFile(reportDir, testDesc, fileName) | 
 |     new FileWriter(file, append).withCloseable fn | 
 | } | 
 |  | 
 | static def getGitBranchName() { | 
 |     def out = new StringBuilder() | 
 |     def err = new StringBuilder() | 
 |     def proc = "git rev-parse --abbrev-ref HEAD".execute() | 
 |     proc.waitForProcessOutput(out, err) | 
 |     return out.toString().trim() | 
 | } | 
 |  | 
 | static def getFreshTestReportIndex(File reportDir) { | 
 |     def number = 0 | 
 |     while (true) { | 
 |         def freshIndex = reportDir.toPath().resolve("index.${number++}.html").toFile() | 
 |         if (!freshIndex.exists()) { | 
 |             return freshIndex | 
 |         } | 
 |     } | 
 | } | 
 |  | 
 | def forEachTestReportAlreadyX(File reportDir, fileName, onTest) { | 
 |     def out = new StringBuilder() | 
 |     def err = new StringBuilder() | 
 |     def proc = "find . -name ${fileName}".execute([], reportDir) | 
 |     proc.waitForProcessOutput(out, err) | 
 |     def outString = out.toString() | 
 |     outString.eachLine { | 
 |         // Lines are of the form: ./<class>/<name>/FAILURE | 
 |         def clazz = null | 
 |         def name = null | 
 |         try { | 
 |             def trimmed = it.trim() | 
 |             def line = trimmed.substring(2) | 
 |             def sep = line.indexOf("/") | 
 |             clazz = line.substring(0, sep) | 
 |             name = line.substring(sep + 1, line.length() - fileName.length() - 1) | 
 |         } catch (Exception e) { | 
 |             logger.lifecycle("WARNING: failed attempt to read test description from: '${it}'") | 
 |             return | 
 |         } | 
 |         onTest(clazz, desanitizedTestName(name)) | 
 |     } | 
 |     return !outString.trim().isEmpty() | 
 | } | 
 |  | 
 | def forEachTestReportAlreadyFailing(File reportDir, onFailureTest) { | 
 |     return forEachTestReportAlreadyX(reportDir, TestResult.ResultType.FAILURE.name(), onFailureTest) | 
 | } | 
 |  | 
 | def forEachTestReportAlreadyPassing(File reportDir, onSucceededTest) { | 
 |     return forEachTestReportAlreadyX(reportDir, TestResult.ResultType.SUCCESS.name(), onSucceededTest) | 
 | } | 
 |  | 
 | def forEachTestReportAlreadySkipped(File reportDir, onSucceededTest) { | 
 |     return forEachTestReportAlreadyX(reportDir, TestResult.ResultType.SKIPPED.name(), onSucceededTest) | 
 | } | 
 |  | 
 | def setUpTestingState(Test task) { | 
 |     // Hide all test events from the console, they are written to the report. | 
 |     task.testLogging { events = [] } | 
 |  | 
 |     def branch = project.hasProperty('testing-state-name') | 
 |         ? project.getProperty('testing-state-name') | 
 |         : getGitBranchName() | 
 |     def reportDir = file("${buildDir}/test-state/${branch}") | 
 |     def index = reportDir.toPath().resolve("index.html").toFile() | 
 |     def resetState = project.hasProperty('reset-testing-state') | 
 |     def reportDirExists = reportDir.exists() | 
 |     def resuming = !resetState && reportDirExists | 
 |  | 
 |     def hasFailingTests = false; | 
 |     if (resuming) { | 
 |         // Test filtering happens before the test execution is initiated so compute it here. | 
 |         // If there are still failing tests in the report, include only those. | 
 |         hasFailingTests = forEachTestReportAlreadyFailing(reportDir, { | 
 |             clazz, name -> task.filter.includeTestsMatching("$clazz.$name") | 
 |         }) | 
 |         // Otherwise exclude all of the test already marked as succeeding. | 
 |         if (!hasFailingTests) { | 
 |             // Also allow the test to overall succeed if there are no remaining tests that match, | 
 |             // which is natural if the state already succeeded in full. | 
 |             task.filter.failOnNoMatchingTests = false | 
 |             forEachTestReportAlreadyPassing(reportDir, { | 
 |                 clazz, name -> task.filter.excludeTestsMatching("$clazz.$name") | 
 |             }) | 
 |             forEachTestReportAlreadySkipped(reportDir, { | 
 |                 clazz, name -> task.filter.excludeTestsMatching("$clazz.$name") | 
 |             }) | 
 |         } | 
 |     } | 
 |  | 
 |     task.beforeSuite { desc -> | 
 |         if (!desc.parent) { | 
 |             def parentReport = null | 
 |             if (resetState && reportDirExists) { | 
 |                 delete reportDir | 
 |             } | 
 |             if (resuming) { | 
 |                 if (index.exists()) { | 
 |                     parentReport = getFreshTestReportIndex(reportDir) | 
 |                     index.renameTo(parentReport) | 
 |                 } | 
 |             } else { | 
 |                 reportDir.mkdirs() | 
 |             } | 
 |             def runPrefix = resuming ? "Resuming" : "Starting" | 
 |             def title =  "${runPrefix} @ ${branch}" | 
 |             // Print a console link to the test report for easy access. | 
 |             println "${runPrefix} test, report written to:" | 
 |             println "  file://${index}" | 
 |             // Print the new index content. | 
 |             index << "<html><head><title>${title}</title>" | 
 |             index << "<style> * { font-family: monospace; }</style>" | 
 |             index << "<meta http-equiv='refresh' content='10' />" | 
 |             index << "</head><body><h1>${title}</h1>" | 
 |             index << "<p>Run on: ${new Date()}</p>" | 
 |             index << "<p>Git branch: ${branch}</p>" | 
 |             if (parentReport != null) { | 
 |                 index << "<p><a href=\"file://${parentReport}\">Previous result index</a></p>" | 
 |             } | 
 |             index << "<p><a href=\"file://${index}\">Most recent result index</a></p>" | 
 |             index << "<p><a href=\"file://${reportDir}\">Test directories</a></p>" | 
 |             index << "<h2>Failing tests (refreshing automatically every 10 seconds)</h2><ul>" | 
 |         } | 
 |     } | 
 |  | 
 |     task.afterSuite { desc, result -> | 
 |         if (!desc.parent) { | 
 |             // Update the final test results in the index. | 
 |             index << "</ul>" | 
 |             if (result.resultType == TestResult.ResultType.SUCCESS) { | 
 |                 if (hasFailingTests) { | 
 |                     index << "<h2>Rerun of failed tests now pass!</h2>" | 
 |                     index << "<h2>Rerun again to continue with outstanding tests!</h2>" | 
 |                 } else { | 
 |                     index << "<h2 style=\"background-color:#62D856\">GREEN BAR == YOU ROCK!</h2>" | 
 |                 } | 
 |             } else if (result.resultType == TestResult.ResultType.FAILURE) { | 
 |                 index << "<h2 style=\"background-color:#6D130A\">Some tests failed: ${result.resultType.name()}</h2><ul>" | 
 |             } else { | 
 |                 index << "<h2>Tests finished: ${result.resultType.name()}</h2><ul>" | 
 |             } | 
 |             index << "<li>Number of tests: ${result.testCount}" | 
 |             index << "<li>Failing tests: ${result.failedTestCount}" | 
 |             index << "<li>Successful tests: ${result.successfulTestCount}" | 
 |             index << "<li>Skipped tests: ${result.skippedTestCount}" | 
 |             index << "</ul></body></html>" | 
 |         } | 
 |     } | 
 |  | 
 |     // Events to stdout/err are appended to the files in the test directories. | 
 |     task.onOutput { desc, event -> | 
 |         withTestResultEntryWriter(reportDir, desc, event.getDestination().name(), true, { | 
 |             it.append(event.getMessage()) | 
 |         }) | 
 |     } | 
 |  | 
 |     task.beforeTest { desc -> | 
 |         // Remove any stale output files before running the test. | 
 |         for (def destType : TestOutputEvent.Destination.values()) { | 
 |             def destFile = getTestResultEntryOutputFile(reportDir, desc, destType.name()) | 
 |             if (destFile.exists()) { | 
 |                 delete destFile | 
 |             } | 
 |         } | 
 |     } | 
 |  | 
 |     task.afterTest { desc, result -> | 
 |         if (result.getTestCount() != 1) { | 
 |             throw new IllegalStateException("Unexpected test with more than one result: ${desc}") | 
 |         } | 
 |         // Clear any previous result files. | 
 |         for (def resultType : TestResult.ResultType.values()) { | 
 |             delete getTestResultEntryOutputFile(reportDir, desc, resultType.name()) | 
 |         } | 
 |         // Emit the result type status in a file of the same name: SUCCESS, FAILURE or SKIPPED. | 
 |         withTestResultEntryWriter(reportDir, desc, result.getResultType().name(), false, { | 
 |             it.append(result.getResultType().name()) | 
 |         }) | 
 |         // Emit the test time. | 
 |         withTestResultEntryWriter(reportDir, desc, "time", false, { | 
 |             it.append("${result.getEndTime() - result.getStartTime()}") | 
 |         }) | 
 |         // For failed tests, update the index and emit stack trace information. | 
 |         if (result.resultType == TestResult.ResultType.FAILURE) { | 
 |             def title = escapeHtml("${desc.className}.${desc.name}") | 
 |             def link = getTestReportEntryURL(reportDir, desc) | 
 |             index << "<li><a href=\"${link}\">${title}</a></li>" | 
 |             if (!result.exceptions.isEmpty()) { | 
 |                 printAllStackTracesToFile( | 
 |                         result.exceptions, | 
 |                         getTestResultEntryOutputFile( | 
 |                                 reportDir, | 
 |                                 desc, | 
 |                                 "exceptions-raw.txt")) | 
 |                 filterStackTraces(result) | 
 |                 printAllStackTracesToFile( | 
 |                         result.exceptions, | 
 |                         getTestResultEntryOutputFile( | 
 |                                 reportDir, | 
 |                                 desc, | 
 |                                 "exceptions-filtered.txt")) | 
 |                 if (shouldRetrace()) { | 
 |                     withTestResultEntryWriter(reportDir, desc, "exceptions-retraced.txt", false, { writer -> | 
 |                         result.exceptions.forEach { writer.append(retrace(it)) } | 
 |                     }) | 
 |                 } | 
 |             } | 
 |         } | 
 |     } | 
 | } | 
 |  | 
 | def testTimes = [:] | 
 | def numberOfTestTimesToPrint = 100 | 
 |  | 
 | test { task -> | 
 |  | 
 |     dependsOn sourceSets.keepanno.output | 
 |     dependsOn buildLibraryDesugarConversions | 
 |     dependsOn getJarsFromSupportLibs | 
 |     // R8.jar is required for running bootstrap tests. | 
 |     dependsOn r8 | 
 |  | 
 |     def useTestingState = project.hasProperty('testing-state') | 
 |     if (useTestingState) { | 
 |         setUpTestingState(task) | 
 |     } | 
 |  | 
 |     if (project.hasProperty('generate_golden_files_to')) { | 
 |         systemProperty 'generate_golden_files_to', project.property('generate_golden_files_to') | 
 |         assert project.hasProperty('HEAD_sha1') | 
 |         systemProperty 'test_git_HEAD_sha1', project.property('HEAD_sha1') | 
 |     } | 
 |  | 
 |     if (project.hasProperty('use_golden_files_in')) { | 
 |         systemProperty 'use_golden_files_in', project.property('use_golden_files_in') | 
 |         assert project.hasProperty('HEAD_sha1') | 
 |         systemProperty 'test_git_HEAD_sha1', project.property('HEAD_sha1') | 
 |     } | 
 |  | 
 |     if (project.hasProperty('kotlin_compiler_dev')) { | 
 |         systemProperty 'com.android.tools.r8.kotlincompilerdev', '1'; | 
 |     } | 
 |  | 
 |     if (project.hasProperty('kotlin_compiler_old')) { | 
 |         systemProperty 'com.android.tools.r8.kotlincompilerold', '1'; | 
 |     } | 
 |  | 
 |     if (!useTestingState) { | 
 |         testLogging.exceptionFormat = 'full' | 
 |         if (project.hasProperty('print_test_stdout')) { | 
 |             testLogging.showStandardStreams = true | 
 |         } | 
 |     } | 
 |     if (project.hasProperty('dex_vm') && project.property('dex_vm') != 'default') { | 
 |         println "NOTE: Running with non default vm: " + project.property('dex_vm') | 
 |         systemProperty 'dex_vm', project.property('dex_vm') | 
 |     } | 
 |  | 
 |     // Forward runtime configurations for test parameters. | 
 |     if (project.hasProperty('runtimes')) { | 
 |         println "NOTE: Running with runtimes: " + project.property('runtimes') | 
 |         systemProperty 'runtimes', project.property('runtimes') | 
 |     } | 
 |  | 
 |     if (project.hasProperty('art_profile_rewriting_completeness_check')) { | 
 |         String key = 'com.android.tools.r8.artprofilerewritingcompletenesscheck' | 
 |         String value = project.property('art_profile_rewriting_completeness_check') | 
 |         systemProperty key, value | 
 |     } | 
 |  | 
 |     if (project.hasProperty('slow_tests')) { | 
 |         systemProperty 'slow_tests', project.property('slow_tests') | 
 |     } | 
 |  | 
 |  | 
 |     if (project.hasProperty('desugar_jdk_json_dir')) { | 
 |         systemProperty 'desugar_jdk_json_dir', project.property('desugar_jdk_json_dir') | 
 |     } | 
 |     if (project.hasProperty('desugar_jdk_libs')) { | 
 |         systemProperty 'desugar_jdk_libs', project.property('desugar_jdk_libs') | 
 |     } | 
 |  | 
 |     if (!useTestingState) { | 
 |         if (project.hasProperty('print_times') || project.hasProperty('one_line_per_test')) { | 
 |             afterTest { desc, result -> | 
 |                 def executionTime = (result.endTime - result.startTime) / 1000 | 
 |                 testTimes["${desc.name} [${desc.className}]"] = executionTime | 
 |             } | 
 |             afterSuite { desc, result -> | 
 |                 // parent is null if all tests are done. | 
 |                 if (desc.parent == null) { | 
 |                     def sortedTimes = testTimes.sort({ e1, e2 -> e2.value <=> e1.value }) | 
 |                     sortedTimes.eachWithIndex { key, value, i -> | 
 |                         println "$key: $value" | 
 |                     } | 
 |                 } | 
 |             } | 
 |         } | 
 |  | 
 |         if (project.hasProperty('one_line_per_test')) { | 
 |             beforeTest { desc -> | 
 |                 println "Start executing test ${desc.name} [${desc.className}]" | 
 |             } | 
 |  | 
 |             afterTest { desc, result -> | 
 |                 if (result.resultType == TestResult.ResultType.FAILURE) { | 
 |                     printStackTrace(result) | 
 |                 } | 
 |                 if (project.hasProperty('update_test_timestamp')) { | 
 |                     file(project.getProperty('update_test_timestamp')).text = new Date().getTime() | 
 |                 } | 
 |                 println "Done executing test ${desc.name} [${desc.className}] with result: ${result.resultType}" | 
 |             } | 
 |         } else { | 
 |             afterTest { desc, result -> | 
 |                 if (result.resultType == TestResult.ResultType.FAILURE) { | 
 |                     printStackTrace(result) | 
 |                 } | 
 |             } | 
 |         } | 
 |     } | 
 |     if (project.hasProperty('no_internal')) { | 
 |         exclude "com/android/tools/r8/internal/**" | 
 |     } else { | 
 |         dependsOn buildExamplesProto | 
 |     } | 
 |     if (project.hasProperty('only_internal')) { | 
 |         include "com/android/tools/r8/internal/**" | 
 |     } | 
 |  | 
 |     if (project.hasProperty('test_namespace')) { | 
 |         include "com/android/tools/r8/" + project.getProperty('test_namespace') + "/**" | 
 |     } | 
 |  | 
 |     if (project.hasProperty('tool') && project.property('tool') == 'd8') { | 
 |         // Don't run anything, deprecated | 
 |         println "Running with deprecated tool d8, not running any tests" | 
 |         include "" | 
 |     } | 
 |     if (project.hasProperty('no_arttests')) { | 
 |         exclude "com/android/tools/r8/art/**" | 
 |     } | 
 |     if (project.hasProperty('shard_count') ) { | 
 |       assert project.hasProperty('shard_number') | 
 |       int shard_count = project.getProperty('shard_count') as Integer | 
 |       int shard_number = project.getProperty('shard_number') as Integer | 
 |       assert shard_count < 65536 | 
 |       assert shard_number < shard_count | 
 |       exclude { | 
 |         entry -> | 
 |           // Don't leave out directories. Leaving out a directory means all entries below. | 
 |           if (entry.file.isDirectory()) { | 
 |            return false | 
 |           } | 
 |           def first4 = entry.getRelativePath().toString().md5().substring(0, 4) | 
 |           int hash = Integer.parseInt(first4, 16) | 
 |           return hash % shard_count != shard_number | 
 |       } | 
 |     } | 
 |     if (project.hasProperty('test_dir')) { | 
 |         systemProperty 'test_dir', project.property('test_dir') | 
 |     } | 
 |     if (project.hasProperty('r8lib')) { | 
 |         dependsOn configureTestForR8Lib | 
 |         // R8lib should be used instead of the main output and all the tests in | 
 |         // r8 should be mapped and exists in r8LibTestPath. | 
 |         classpath = sourceSets.test.runtimeClasspath.filter { | 
 |             !it.getAbsolutePath().contains("/build/") | 
 |         } | 
 |         classpath += files([r8LibPath, r8LibTestPath]) | 
 |         testClassesDirs = files(r8LibTestPath) | 
 |     } | 
 |     if (OperatingSystem.current().isLinux() | 
 |             || OperatingSystem.current().isMacOsX() | 
 |             || OperatingSystem.current().isWindows()) { | 
 |         if (OperatingSystem.current().isMacOsX()) { | 
 |             logger.lifecycle("WARNING: Testing in only partially supported on Mac OS. " + | 
 |                 "Art only runs on Linux and tests requiring Art runs in a Docker container, which must be present. " + | 
 |                 "See tools/docker/README.md for details.") | 
 |         } | 
 |         if (OperatingSystem.current().isWindows()) { | 
 |             logger.lifecycle("WARNING: Testing in only partially supported on Windows. " + | 
 |                     "Art only runs on Linux and tests requiring Art will be skipped") | 
 |         } | 
 |         dependsOn downloadDeps | 
 |         dependsOn buildExamples | 
 |         dependsOn buildKotlinR8TestResources | 
 |         dependsOn buildSmali | 
 |         dependsOn buildPreNJdwpTestsJar | 
 |         dependsOn compileTestNGRunner | 
 |         dependsOn provideArtFrameworksDependencies | 
 |     } else { | 
 |         logger.lifecycle("WARNING: Testing in not supported on your platform. Testing is only fully supported on " + | 
 |             "Linux and partially supported on Mac OS and Windows. Art does not run on other platforms.") | 
 |     } | 
 | } | 
 |  | 
 |  | 
 | task javadocD8(type: Javadoc) { | 
 |   title "D8 API" | 
 |   classpath = sourceSets.main.compileClasspath | 
 |   source = sourceSets.main.allJava | 
 |   include '**/com/android/tools/r8/ArchiveClassFileProvider.java' | 
 |   include '**/com/android/tools/r8/ArchiveProgramResourceProvider.java' | 
 |   include '**/com/android/tools/r8/BaseCommand.java' | 
 |   include '**/com/android/tools/r8/BaseCompilerCommand.java' | 
 |   include '**/com/android/tools/r8/ClassFileResourceProvider.java' | 
 |   include '**/com/android/tools/r8/CompilationFailedException.java' | 
 |   include '**/com/android/tools/r8/CompilationMode.java' | 
 |   include '**/com/android/tools/r8/D8.java' | 
 |   include '**/com/android/tools/r8/D8Command.java' | 
 |   include '**/com/android/tools/r8/DexIndexedConsumer.java' | 
 |   include '**/com/android/tools/r8/DexFilePerClassFileConsumer.java' | 
 |   include '**/com/android/tools/r8/Diagnostic.java' | 
 |   include '**/com/android/tools/r8/DiagnosticsHandler.java' | 
 |   include '**/com/android/tools/r8/DirectoryClassFileProvider.java' | 
 |   include '**/com/android/tools/r8/OutputMode.java' | 
 |   include '**/com/android/tools/r8/ProgramConsumer.java' | 
 |   include '**/com/android/tools/r8/ProgramResource.java' | 
 |   include '**/com/android/tools/r8/ProgramResourceProvider.java' | 
 |   include '**/com/android/tools/r8/Resource.java' | 
 |   include '**/com/android/tools/r8/ResourceException.java' | 
 |   include '**/com/android/tools/r8/StringConsumer.java' | 
 |   include '**/com/android/tools/r8/StringResource.java' | 
 |   include '**/com/android/tools/r8/Version.java' | 
 |   include '**/com/android/tools/r8/origin/*.java' | 
 | } | 
 |  | 
 | task javadocR8(type: Javadoc) { | 
 |   title "R8 API" | 
 |   classpath = sourceSets.main.compileClasspath | 
 |   source = sourceSets.main.allJava | 
 |   include '**/com/android/tools/r8/ArchiveClassFileProvider.java' | 
 |   include '**/com/android/tools/r8/ArchiveProgramResourceProvider.java' | 
 |   include '**/com/android/tools/r8/BaseCommand.java' | 
 |   include '**/com/android/tools/r8/BaseCompilerCommand.java' | 
 |   include '**/com/android/tools/r8/ClassFileConsumer.java' | 
 |   include '**/com/android/tools/r8/ClassFileResourceProvider.java' | 
 |   include '**/com/android/tools/r8/CompilationFailedException.java' | 
 |   include '**/com/android/tools/r8/CompilationMode.java' | 
 |   include '**/com/android/tools/r8/R8.java' | 
 |   include '**/com/android/tools/r8/R8Command.java' | 
 |   include '**/com/android/tools/r8/DexIndexedConsumer.java' | 
 |   include '**/com/android/tools/r8/Diagnostic.java' | 
 |   include '**/com/android/tools/r8/DiagnosticsHandler.java' | 
 |   include '**/com/android/tools/r8/DirectoryClassFileProvider.java' | 
 |   include '**/com/android/tools/r8/OutputMode.java' | 
 |   include '**/com/android/tools/r8/ProgramConsumer.java' | 
 |   include '**/com/android/tools/r8/ProgramResource.java' | 
 |   include '**/com/android/tools/r8/ProgramResourceProvider.java' | 
 |   include '**/com/android/tools/r8/Resource.java' | 
 |   include '**/com/android/tools/r8/ResourceException.java' | 
 |   include '**/com/android/tools/r8/StringConsumer.java' | 
 |   include '**/com/android/tools/r8/StringResource.java' | 
 |   include '**/com/android/tools/r8/Version.java' | 
 |   include '**/com/android/tools/r8/origin/*.java' | 
 | } | 
 |  | 
 | task copyMavenDeps(type: Copy) { | 
 |     from configurations.compile into "$buildDir/deps" | 
 |     from configurations.compileClasspath into "$buildDir/deps" | 
 |     from configurations.testCompile into "$buildDir/deps" | 
 | } | 
 |  | 
 | task printMavenDeps { | 
 |     // Only actually print to stdout when we are updating. | 
 |     if (project.hasProperty('updatemavendeps')) { | 
 |         for (Configuration config : configurations) { | 
 |             if (!config.isCanBeResolved()) { | 
 |                 continue | 
 |             } | 
 |             def componentIds = config.incoming.resolutionResult.allDependencies.collect { | 
 |                 it.selected.id | 
 |             } | 
 |             def result = dependencies.createArtifactResolutionQuery() | 
 |                 .forComponents(componentIds) | 
 |                 .withArtifacts(MavenModule, MavenPomArtifact) | 
 |                 .execute() | 
 |             for (component in result.resolvedComponents) { | 
 |                 component.getArtifacts(MavenPomArtifact).each { | 
 |                     println "POM: ${it.file} ${component.id}" | 
 |                 } | 
 |             } | 
 |             config.each { | 
 |                 println "JAR: ${it}" | 
 |             } | 
 |         } | 
 |     } | 
 | } | 
 |  | 
 | allprojects { | 
 |   tasks.withType(Exec) { | 
 |     doFirst { | 
 |       println commandLine.join(' ') | 
 |     } | 
 |   } | 
 | } |