Add a pinned JDK 9 to third_party and update Gradle to 5.2
This CL makes various changes to update our build to JDK 9 and Gradle 5.2. The
build will by default use third_party/{gradle/gradle, openjdk/openjdk-9.0.4} to
build. This is done by directly using third_party/gradle/gradle and reading the
location of the JDK from tools/jdk.py. That value is then set as JAVA_HOME for
the subprocess in tools/gradle.py and picked up by the running tests via
Syste.getProperty("java.home"). To override the JDK to use, both tools/gradle.py
and tools/test.py take a --java-home argument which is used to define
-Dorg.gradle.java.home which will take precedence over JAVA_HOME in gradle.
FYI, the build.gradle is configured to issue a warning if the current Java Home
differes from the expected pinned version, but will not change it.
The summary of changes needed to update are:
- Add tools/jdk.py which is the canonical place to update the current default JDK.
- Add --java-home flag for running with a non-pinned JDK (eg, JDK 8) to gradle.py.
- Add various max-heap-size settings to control heap size (for example, running
JDK 8 requires manually increasing size of the gradle instance for compilation).
- Update the inner-classes tests which are no longer considered malformed on JDK 9.
- Update path to classes build dir (changed in gradle 4+).
Change-Id: I28789c0eaacb865b31b46e8daec0da8e62bb24a3
diff --git a/.gitignore b/.gitignore
index c04d9dd..b8248ed 100644
--- a/.gitignore
+++ b/.gitignore
@@ -85,6 +85,12 @@
third_party/ddmlib.tar.gz
third_party/core-lambda-stubs
third_party/core-lambda-stubs.tar.gz
+third_party/openjdk/openjdk-9.0.4/linux
+third_party/openjdk/openjdk-9.0.4/linux.tar.gz
+third_party/openjdk/openjdk-9.0.4/osx
+third_party/openjdk/openjdk-9.0.4/osx.tar.gz
+third_party/openjdk/openjdk-9.0.4/windows
+third_party/openjdk/openjdk-9.0.4/windows.tar.gz
third_party/openjdk/openjdk-rt-1.8
third_party/openjdk/openjdk-rt-1.8.tar.gz
third_party/r8
@@ -98,6 +104,7 @@
*.iml
r8.ipr
r8.iws
+local.properties
#*#
*~
.#*
diff --git a/build.gradle b/build.gradle
index 4ce2e18..053bbfb 100644
--- a/build.gradle
+++ b/build.gradle
@@ -1,12 +1,33 @@
// 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 com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
-import net.ltgt.gradle.errorprone.ErrorProneToolChain
+import net.ltgt.gradle.errorprone.CheckSeverity
import org.gradle.internal.os.OperatingSystem
import tasks.GetJarsFromConfiguration
import utils.Utils
+buildscript {
+ repositories {
+ mavenCentral()
+ jcenter()
+ maven {
+ url "https://plugins.gradle.org/m2/"
+ }
+ }
+ dependencies {
+ classpath 'com.github.jengelman.gradle.plugins:shadow:2.0.4'
+ }
+}
+
+plugins {
+ id "net.ltgt.errorprone" version "0.7"
+}
+
+apply plugin: 'java'
+apply plugin: 'idea'
+
ext {
androidSupportVersion = '25.4.0'
asmVersion = '6.2.1'
@@ -20,32 +41,9 @@
kotlinVersion = '1.3.11'
kotlinExtMetadataJVMVersion = '0.0.4'
smaliVersion = '2.2b4'
+ errorproneVersion = '2.3.2'
}
-def errorProneConfiguration = [
- '-XepDisableAllChecks',
- // D8 want to use reference equality, thus disable the checker explicitly
- '-Xep:ReferenceEquality:OFF',
- '-Xep:ClassCanBeStatic:ERROR',
- '-Xep:OperatorPrecedence:ERROR',
- '-Xep:RemoveUnusedImports:ERROR',
- '-Xep:MissingOverride:ERROR',
- '-Xep:IntLongMath:ERROR',
- '-Xep:EqualsHashCode:ERROR',
- '-Xep:InconsistentOverloads:ERROR',
- '-Xep:ArrayHashCode:ERROR',
- '-Xep:EqualsIncompatibleType:ERROR',
- '-Xep:NonOverridingEquals:ERROR',
- '-Xep:FallThrough:ERROR',
- '-Xep:MissingCasesInEnumSwitch:ERROR',
- '-Xep:MissingDefault:ERROR',
- '-Xep:MultipleTopLevelClasses:ERROR',
- '-Xep:NarrowingCompoundAssignment:ERROR',
- '-Xep:BoxedPrimitiveConstructor:ERROR',
- '-Xep:LogicalAssignment:ERROR',
- '-Xep:FloatCast:ERROR',
- '-Xep:ReturnValueIgnored:ERROR']
-
apply from: 'copyAdditionalJctfCommonFiles.gradle'
repositories {
@@ -54,32 +52,6 @@
mavenCentral()
}
-buildscript {
- repositories {
- mavenCentral()
- jcenter()
- maven {
- url "https://plugins.gradle.org/m2/"
- }
- }
- dependencies {
- classpath 'com.github.jengelman.gradle.plugins:shadow:2.0.4'
- classpath "net.ltgt.gradle:gradle-errorprone-plugin:0.0.13"
- classpath "com.gradle:build-scan-plugin:1.14"
- }
-}
-
-apply plugin: "com.gradle.build-scan"
-
-buildScan {
- licenseAgreementUrl = 'https://gradle.com/terms-of-service'
- licenseAgree = 'yes'
-}
-
-apply plugin: 'java'
-apply plugin: 'idea'
-apply plugin: 'net.ltgt.errorprone-base'
-
if (project.hasProperty('with_code_coverage')) {
apply plugin: 'jacoco'
}
@@ -206,10 +178,10 @@
module {
if (sources.name == "main") {
sourceDirs += sources.java.srcDirs
- outputDir sources.output.classesDir
+ outputDir sources.output.classesDirs[0]
} else {
testSourceDirs += sources.java.srcDirs
- testOutputDir sources.output.classesDir
+ testOutputDir sources.output.classesDirs[0]
}
}
}
@@ -262,6 +234,7 @@
debugTestResourcesKotlinCompileOnly "org.jetbrains.kotlin:kotlin-stdlib:$kotlinVersion"
examplesKotlinCompileOnly "org.jetbrains.kotlin:kotlin-stdlib:$kotlinVersion"
kotlinR8TestResourcesCompileOnly "org.jetbrains.kotlin:kotlin-stdlib:$kotlinVersion"
+ errorprone("com.google.errorprone:error_prone_core:$errorproneVersion")
}
def r8LibPath = "$buildDir/libs/r8lib.jar"
@@ -320,9 +293,41 @@
]
]
+def cloudSystemDependencies = [
+ linux: [
+ "third_party": ["openjdk/openjdk-9.0.4/linux"],
+ ],
+ osx: [
+ "third_party": ["openjdk/openjdk-9.0.4/osx"],
+ ],
+ windows: [
+ "third_party": ["openjdk/openjdk-9.0.4/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 "download_deps_${entry.key}/${entryFile}"(type: Exec) {
+ task "${getDownloadDepsTaskName(entry.key, entryFile)}"(type: Exec) {
def outputDir = "${entry.key}/${entryFile}"
def gzFile = "${outputDir}.tar.gz"
def sha1File = "${gzFile}.sha1"
@@ -372,7 +377,7 @@
x20Dependencies.each { entry ->
entry.value.each { entryFile ->
- task "download_deps_${entry.key}/${entryFile}"(type: Exec) {
+ task "${getDownloadDepsTaskName(entry.key, entryFile)}"(type: Exec) {
def outputDir = "${entry.key}/${entryFile}"
def gzFile = "${outputDir}.tar.gz"
def sha1File = "${gzFile}.sha1"
@@ -388,7 +393,7 @@
cloudDependencies.each { entry ->
entry.value.each { entryFile ->
if (entryFile.contains("proguard")) {
- dependsOn "download_deps_${entry.key}/${entryFile}"
+ dependsOn "${getDownloadDepsTaskName(entry.key, entryFile)}"
}
}
}
@@ -398,7 +403,7 @@
cloudDependencies.each { entry ->
entry.value.each { entryFile ->
if (entryFile.contains("openjdk-rt")) {
- dependsOn "download_deps_${entry.key}/${entryFile}"
+ dependsOn "${getDownloadDepsTaskName(entry.key, entryFile)}"
}
}
}
@@ -408,7 +413,7 @@
cloudDependencies.each { entry ->
entry.value.each { entryFile ->
if (entryFile.endsWith("/dx")) {
- dependsOn "download_deps_${entry.key}/${entryFile}"
+ dependsOn "${getDownloadDepsTaskName(entry.key, entryFile)}"
}
}
}
@@ -418,7 +423,7 @@
cloudDependencies.each { entry ->
entry.value.each { entryFile ->
if (entryFile.contains("android_cts_baseline")) {
- dependsOn "download_deps_${entry.key}/${entryFile}"
+ dependsOn "${getDownloadDepsTaskName(entry.key, entryFile)}"
}
}
}
@@ -427,13 +432,13 @@
task downloadDeps {
cloudDependencies.each { entry ->
entry.value.each { entryFile ->
- dependsOn "download_deps_${entry.key}/${entryFile}"
+ dependsOn "${getDownloadDepsTaskName(entry.key, entryFile)}"
}
}
if (!project.hasProperty('no_internal')) {
x20Dependencies.each { entry ->
entry.value.each { entryFile ->
- dependsOn "download_deps_${entry.key}/${entryFile}"
+ dependsOn "${getDownloadDepsTaskName(entry.key, entryFile)}"
}
}
}
@@ -444,22 +449,63 @@
targetCompatibility = JavaVersion.VERSION_1_8
}
-// Javac often runs out of stack space when compiling the tests.
-// Increase the stack size for the javac process.
-tasks.withType(JavaCompile) {
- options.fork = true
- options.forkOptions.jvmArgs = ["-Xss4m"]
+// 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
+} else {
+ def javaHomeOut = new StringBuilder()
+ def javaHomeErr = new StringBuilder()
+ def javaHomeProc = './tools/jdk.py'.execute()
+ 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)
+ }
}
-tasks.withType(JavaCompile) {
- options.compilerArgs << '-Xlint:unchecked'
+sourceSets.configureEach { sourceSet ->
+ tasks.named(sourceSet.compileJavaTaskName).configure {
+ // Default disable errorprone (enabled and setup below).
+ options.errorprone.enabled = false
+ options.compilerArgs << '-Xlint:unchecked'
+ // Javac often runs out of stack space when compiling the tests.
+ // Increase the stack size for the javac process.
+ options.forkOptions.jvmArgs << "-Xss4m"
+ // 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"
+ }
}
-if (!project.hasProperty('without_error_prone')) {
+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 sources.
- toolChain ErrorProneToolChain.create(project)
- options.compilerArgs += errorProneConfiguration
+ options.errorprone.enabled = true
+ options.errorprone.disableAllChecks = true
+ options.errorprone.check('ClassCanBeStatic', CheckSeverity.ERROR)
+ options.errorprone.check('OperatorPrecedence', CheckSeverity.ERROR)
+ options.errorprone.check('RemoveUnusedImports', CheckSeverity.ERROR)
+ options.errorprone.check('MissingOverride', CheckSeverity.ERROR)
+ options.errorprone.check('IntLongMath', CheckSeverity.ERROR)
+ options.errorprone.check('EqualsHashCode', CheckSeverity.ERROR)
+ options.errorprone.check('InconsistentOverloads', CheckSeverity.ERROR)
+ options.errorprone.check('ArrayHashCode', CheckSeverity.ERROR)
+ options.errorprone.check('EqualsIncompatibleType', CheckSeverity.ERROR)
+ options.errorprone.check('NonOverridingEquals', CheckSeverity.ERROR)
+ options.errorprone.check('FallThrough', CheckSeverity.ERROR)
+ options.errorprone.check('MissingCasesInEnumSwitch', CheckSeverity.ERROR)
+ options.errorprone.check('MissingDefault', CheckSeverity.ERROR)
+ options.errorprone.check('MultipleTopLevelClasses', CheckSeverity.ERROR)
+ options.errorprone.check('NarrowingCompoundAssignment', CheckSeverity.ERROR)
+ options.errorprone.check('BoxedPrimitiveConstructor', CheckSeverity.ERROR)
+ options.errorprone.check('LogicalAssignment', CheckSeverity.ERROR)
+ options.errorprone.check('FloatCast', CheckSeverity.ERROR)
+ options.errorprone.check('ReturnValueIgnored', CheckSeverity.ERROR)
}
}
@@ -788,8 +834,7 @@
task createArtTests(type: Exec) {
def outputDir = "build/generated/test/java/com/android/tools/r8/art"
def createArtTestsScript = "tools/create_art_tests.py"
- inputs.file "tests/2017-10-04/art.tar.gz"
- inputs.file createArtTestsScript
+ inputs.files files("tests/2017-10-04/art.tar.gz", createArtTestsScript)
outputs.dir outputDir
dependsOn downloadDeps
commandLine "python", createArtTestsScript
@@ -864,7 +909,7 @@
args "--dex"
args "--output=build/test/${hostDexJar}"
args "build/test/${hostJar}"
- inputs.file file("build/test/${hostJar}")
+ inputs.files files("build/test/${hostJar}")
outputs.file file("build/test/${hostDexJar}")
}
dependsOn dex_debuginfo_examples
@@ -1017,8 +1062,9 @@
def proguardJarPath = "${exampleOutputDir}/${jarName}"
def proguardMapPath = "${exampleOutputDir}/${name}/${name}.map"
task "jar_example_${name}"(type: Exec, dependsOn: "pre_proguard_example_${name}") {
- inputs.files tasks.getByPath("pre_proguard_example_${name}")
- inputs.file proguardConfigPath
+ 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')
@@ -1338,7 +1384,7 @@
def smaliOutputDir = file("build/test/smali/" + relativeDir);
smaliOutputDir.mkdirs()
outputs.dir smaliOutputDir
- def taskName = "smali_build_${relativeDir.toString().replace('/', '_')}"
+ 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;
@@ -1410,7 +1456,7 @@
task buildPreNJdwpTestsDex(type: Exec, dependsOn: "buildPreNJdwpTestsJar") {
def inFile = buildPreNJdwpTestsJar.archivePath
def outFile = new File(buildPreNJdwpTestsJar.destinationDir, buildPreNJdwpTestsJar.baseName + '-dex.jar')
- inputs.file inFile
+ inputs.files files(inFile)
outputs.file outFile
if (OperatingSystem.current().isWindows()) {
executable file("tools/windows/dx/bin/dx.bat")
@@ -1431,7 +1477,7 @@
task AospJarTest(type: Exec) {
dependsOn CompatDx, downloadDeps
def script = "tools/test_aosp_jar.py"
- inputs.file script
+ inputs.files files(script)
commandLine "python", script, "--no-build"
workingDir = projectDir
}
@@ -1447,7 +1493,7 @@
task configureTestForR8Lib(type: Copy) {
dependsOn testJar
- inputs.file "$buildDir/libs/r8tests.jar"
+ inputs.files files("$buildDir/libs/r8tests.jar")
if (getR8LibTask() != null) {
dependsOn getR8LibTask()
delete r8LibTestPath
@@ -1489,6 +1535,9 @@
}
test {
+ // TODO(b/124091860): Increase the max heap size to avoid OOM when running tests.
+ maxHeapSize = "3g"
+
if (project.hasProperty('generate_golden_files_to')) {
systemProperty 'generate_golden_files_to', project.property('generate_golden_files_to')
assert project.hasProperty('HEAD_sha1')
@@ -1591,7 +1640,7 @@
sourceSets.test.runtimeClasspath -
sourceSets.main.output -
files(['build/classes/test'])
- testClassesDir = new File(r8LibTestPath)
+ testClassesDirs = files(r8LibTestPath)
}
if (OperatingSystem.current().isLinux()
|| OperatingSystem.current().isMacOsX()
diff --git a/buildSrc/build.gradle b/buildSrc/build.gradle
index 0f172d6..74c5cfd 100644
--- a/buildSrc/build.gradle
+++ b/buildSrc/build.gradle
@@ -12,3 +12,6 @@
compile group: 'com.google.guava', name: 'guava', version: '19.0'
compile group: 'org.smali', name: 'smali', version: '2.2b4'
}
+
+sourceCompatibility = JavaVersion.VERSION_1_8
+targetCompatibility = JavaVersion.VERSION_1_8
diff --git a/buildSrc/src/main/java/dx/DexMerger.java b/buildSrc/src/main/java/dx/DexMerger.java
index d3d8427..6303009 100644
--- a/buildSrc/src/main/java/dx/DexMerger.java
+++ b/buildSrc/src/main/java/dx/DexMerger.java
@@ -8,34 +8,38 @@
import org.gradle.api.Action;
import org.gradle.api.DefaultTask;
import org.gradle.api.UncheckedIOException;
+import org.gradle.api.file.FileCollection;
import org.gradle.api.file.FileTree;
+import org.gradle.api.tasks.InputFiles;
+import org.gradle.api.tasks.OutputDirectory;
+import org.gradle.api.tasks.OutputFile;
import org.gradle.api.tasks.TaskAction;
import org.gradle.process.ExecSpec;
import utils.Utils;
public class DexMerger extends DefaultTask {
- private FileTree source;
+ private FileCollection source;
private File destination;
private File dexMergerExecutable;
private boolean debug;
- public FileTree getSource() {
+ @InputFiles
+ public FileCollection getSource() {
return source;
}
- public void setSource(FileTree source) {
+ public void setSource(FileCollection source) {
this.source = source;
- getInputs().file(source);
}
+ @OutputFile
public File getDestination() {
return destination;
}
public void setDestination(File destination) {
this.destination = destination;
- getOutputs().file(destination);
}
public File getDexMergerExecutable() {
diff --git a/buildSrc/src/main/java/dx/Dx.java b/buildSrc/src/main/java/dx/Dx.java
index 86d1bce..b03ad0f 100644
--- a/buildSrc/src/main/java/dx/Dx.java
+++ b/buildSrc/src/main/java/dx/Dx.java
@@ -8,37 +8,38 @@
import org.gradle.api.Action;
import org.gradle.api.DefaultTask;
import org.gradle.api.UncheckedIOException;
+import org.gradle.api.file.FileCollection;
import org.gradle.api.file.FileTree;
+import org.gradle.api.tasks.InputFiles;
+import org.gradle.api.tasks.OutputDirectory;
+import org.gradle.api.tasks.OutputFile;
import org.gradle.api.tasks.TaskAction;
import org.gradle.process.ExecSpec;
import utils.Utils;
public class Dx extends DefaultTask {
- private FileTree source;
+ private FileCollection source;
private File destination;
private File dxExecutable;
private boolean debug;
- public FileTree getSource() {
+ @InputFiles
+ public FileCollection getSource() {
return source;
}
- public void setSource(FileTree source) {
+ public void setSource(FileCollection source) {
this.source = source;
- getInputs().file(source);
}
+ @OutputDirectory
public File getDestination() {
return destination;
}
public void setDestination(File destination) {
this.destination = destination;
- File classesFile = destination.toPath().resolve("classes.dex").toFile();
- // The output from running DX is classes.dex in the destination directory.
- // TODO(sgjesse): Handle multidex?
- getOutputs().file(classesFile);
}
public File getDxExecutable() {
diff --git a/buildSrc/src/main/java/smali/Smali.java b/buildSrc/src/main/java/smali/Smali.java
index bd217d7..7a5241e 100644
--- a/buildSrc/src/main/java/smali/Smali.java
+++ b/buildSrc/src/main/java/smali/Smali.java
@@ -10,6 +10,9 @@
import org.gradle.api.DefaultTask;
import org.gradle.api.UncheckedIOException;
import org.gradle.api.file.FileTree;
+import org.gradle.api.tasks.InputFiles;
+import org.gradle.api.tasks.OutputDirectory;
+import org.gradle.api.tasks.OutputFile;
import org.gradle.api.tasks.TaskAction;
public class Smali extends DefaultTask {
@@ -18,22 +21,22 @@
private File destination;
private File smaliScript;
+ @InputFiles
public FileTree getSource() {
return source;
}
public void setSource(FileTree source) {
this.source = source;
- getInputs().file(source);
}
+ @OutputFile
public File getDestination() {
return destination;
}
public void setDestination(File destination) {
this.destination = destination;
- getOutputs().file(destination);
}
public File getSmaliScript() {
diff --git a/settings.gradle b/settings.gradle
new file mode 100644
index 0000000..9924d92
--- /dev/null
+++ b/settings.gradle
@@ -0,0 +1,6 @@
+// Copyright (c) 2019, 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.
+
+rootProject.name = 'r8'
+
diff --git a/src/test/java/com/android/tools/r8/ToolHelper.java b/src/test/java/com/android/tools/r8/ToolHelper.java
index e4a809c..a12ba39 100644
--- a/src/test/java/com/android/tools/r8/ToolHelper.java
+++ b/src/test/java/com/android/tools/r8/ToolHelper.java
@@ -778,6 +778,10 @@
return getPlatform().startsWith("Windows");
}
+ public static boolean isJava8Runtime() {
+ return System.getProperty("java.specification.version").equals("8");
+ }
+
public static boolean isJava9Runtime() {
return System.getProperty("java.specification.version").equals("9");
}
@@ -804,7 +808,7 @@
}
public static Path getClassPathForTests() {
- return Paths.get(BUILD_DIR, "classes", "test");
+ return Paths.get(BUILD_DIR, "classes", "java", "test");
}
private static List<String> getNamePartsForTestPackage(Package pkg) {
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/reflection/GetSimpleNameTest.java b/src/test/java/com/android/tools/r8/ir/optimize/reflection/GetSimpleNameTest.java
index e4ef08e..2a28a71 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/reflection/GetSimpleNameTest.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/reflection/GetSimpleNameTest.java
@@ -234,8 +234,8 @@
.addOptionsModification(this::configure)
.run(MAIN);
if (enableMinification) {
- if (backend == Backend.CF) {
- // TODO(b/120639028): Incorrect inner-class structure fails on JVM.
+ if (backend == Backend.CF && ToolHelper.isJava8Runtime()) {
+ // TODO(b/120639028): Incorrect inner-class structure fails on JVM prior to JDK 9.
result.assertFailureWithErrorThatMatches(containsString("Malformed class name"));
return;
} else {
diff --git a/src/test/java/com/android/tools/r8/ir/optimize/reflection/InnerClassNameTestRunner.java b/src/test/java/com/android/tools/r8/ir/optimize/reflection/InnerClassNameTestRunner.java
index 0a71fe6..167d953 100644
--- a/src/test/java/com/android/tools/r8/ir/optimize/reflection/InnerClassNameTestRunner.java
+++ b/src/test/java/com/android/tools/r8/ir/optimize/reflection/InnerClassNameTestRunner.java
@@ -171,7 +171,7 @@
if (backend == Backend.CF && minify) {
// TODO(b/120639028) R8 does not keep the structure of inner classes.
r8RunResult.assertFailureWithErrorThatMatches(containsString("Malformed class name"));
- } else if (backend == Backend.CF) {
+ } else if (backend == Backend.CF && ToolHelper.isJava8Runtime()) {
// $$ as separator and InnerClass as name, results in $InnerClass from getSimpleName...
String expectedWithDollarOnInnerName =
getExpectedNonMinified("$" + config.getInnerClassName());
@@ -182,20 +182,21 @@
r8RunResult.assertSuccessWithOutput(
minify ? getExpectedMinified(inspector) : expectedWithDollarOnInnerName);
} else {
- // $$ in DEX will not change the InnerName/getSimpleName.
+ // $$ in DEX or JDK 9+ will not change the InnerName/getSimpleName.
r8RunResult.assertSuccessWithOutput(getExpectedMinified(inspector));
}
break;
case EMTPY_SEPARATOR:
case UNDERBAR_SEPARATOR:
case NON_NESTED_INNER:
- if (backend == Backend.CF) {
+ if (backend == Backend.CF && ToolHelper.isJava8Runtime()) {
// NOTE(b/120597515): These cases should fail, but if they succeed, we have recovered via
// minification, likely by not using the same separator from output in input.
// Any non-$ separator results in a runtime exception in getCanonicalName.
+ // NOTE: Behavior changed in JDK 9 so the class is no longer considered malformed.
r8RunResult.assertFailureWithErrorThatMatches(containsString("Malformed class name"));
} else {
- assert backend == Backend.DEX;
+ assert backend == Backend.DEX || !ToolHelper.isJava8Runtime();
r8RunResult.assertSuccessWithOutput(getExpectedMinified(inspector));
}
break;
diff --git a/third_party/gradle/gradle.tar.gz.sha1 b/third_party/gradle/gradle.tar.gz.sha1
index c9f900a..a219d61 100644
--- a/third_party/gradle/gradle.tar.gz.sha1
+++ b/third_party/gradle/gradle.tar.gz.sha1
@@ -1 +1 @@
-2d9bb7b50771ad8252cdcf83a1a9648af7eee837
\ No newline at end of file
+4a07bcbff312d890bc1b96c39aaffdcab882cd3a
\ No newline at end of file
diff --git a/third_party/openjdk/jdk9.tar.gz.sha1 b/third_party/openjdk/jdk9.tar.gz.sha1
new file mode 100644
index 0000000..fe944e4
--- /dev/null
+++ b/third_party/openjdk/jdk9.tar.gz.sha1
@@ -0,0 +1 @@
+b7fd72327317977e4221244115bdbbac4edd3444
\ No newline at end of file
diff --git a/third_party/openjdk/openjdk-9.0.4/linux.tar.gz.sha1 b/third_party/openjdk/openjdk-9.0.4/linux.tar.gz.sha1
new file mode 100644
index 0000000..4670484
--- /dev/null
+++ b/third_party/openjdk/openjdk-9.0.4/linux.tar.gz.sha1
@@ -0,0 +1 @@
+ed9e71246f8bba2d7ec0c4d56813c241d8315960
\ No newline at end of file
diff --git a/third_party/openjdk/openjdk-9.0.4/osx.tar.gz.sha1 b/third_party/openjdk/openjdk-9.0.4/osx.tar.gz.sha1
new file mode 100644
index 0000000..7db6817
--- /dev/null
+++ b/third_party/openjdk/openjdk-9.0.4/osx.tar.gz.sha1
@@ -0,0 +1 @@
+a68b718365f7ce214eec2f6bb89311885940b10e
\ No newline at end of file
diff --git a/third_party/openjdk/openjdk-9.0.4/windows.tar.gz.sha1 b/third_party/openjdk/openjdk-9.0.4/windows.tar.gz.sha1
new file mode 100644
index 0000000..dedab10
--- /dev/null
+++ b/third_party/openjdk/openjdk-9.0.4/windows.tar.gz.sha1
@@ -0,0 +1 @@
+d9d352dfa1484bc1b7eaff0e013f720a120ff963
\ No newline at end of file
diff --git a/tools/gradle.py b/tools/gradle.py
index ff90779..374f885 100755
--- a/tools/gradle.py
+++ b/tools/gradle.py
@@ -7,9 +7,12 @@
# Will make sure we pulled down gradle before running, and will use the pulled
# down version to have a consistent developer experience.
+import optparse
import os
import subprocess
import sys
+
+import jdk
import utils
GRADLE_DIR = os.path.join(utils.REPO_ROOT, 'third_party', 'gradle')
@@ -21,6 +24,15 @@
else:
GRADLE = os.path.join(GRADLE_DIR, 'gradle', 'bin', 'gradle')
+def ParseOptions():
+ result = optparse.OptionParser()
+ result.add_option('--java-home', '--java_home',
+ help='Use a custom java version to run gradle.')
+ return result.parse_args()
+
+def GetJavaEnv(env):
+ return dict(env if env else os.environ, JAVA_HOME = jdk.GetJdkHome())
+
def PrintCmd(s):
if type(s) is list:
s = ' '.join(s)
@@ -29,17 +41,12 @@
sys.stdout.flush()
def EnsureGradle():
- if not os.path.exists(GRADLE) or os.path.getmtime(GRADLE_TGZ) < os.path.getmtime(GRADLE_SHA1):
- # Bootstrap or update gradle, everything else is controlled using gradle.
- utils.DownloadFromGoogleCloudStorage(GRADLE_SHA1)
- # Update the mtime of the tar file to make sure we do not run again unless
- # there is an update.
- os.utime(GRADLE_TGZ, None)
- else:
- print 'gradle.py: Gradle binary present'
+ utils.EnsureDepFromGoogleCloudStorage(
+ GRADLE, GRADLE_TGZ, GRADLE_SHA1, 'Gradle binary')
def EnsureDeps():
EnsureGradle()
+ jdk.EnsureJdk()
def RunGradleIn(gradleCmd, args, cwd, throw_on_failure=True, env=None):
EnsureDeps()
@@ -47,7 +54,7 @@
cmd.extend(args)
utils.PrintCmd(cmd)
with utils.ChangedWorkingDirectory(cwd):
- return_value = subprocess.call(cmd, env=env)
+ return_value = subprocess.call(cmd, env=GetJavaEnv(env))
if throw_on_failure and return_value != 0:
raise Exception('Failed to execute gradle')
return return_value
@@ -69,7 +76,7 @@
cmd.extend(args)
utils.PrintCmd(cmd)
with utils.ChangedWorkingDirectory(cwd):
- return subprocess.check_output(cmd, env=env)
+ return subprocess.check_output(cmd, env=GetJavaEnv(env))
def RunGradleWrapperInGetOutput(args, cwd, env=None):
return RunGradleInGetOutput('./gradlew', args, cwd, env=env)
@@ -78,7 +85,11 @@
return RunGradleInGetOutput(GRADLE, args, utils.REPO_ROOT, env=env)
def Main():
- RunGradle(sys.argv[1:])
+ (options, args) = ParseOptions()
+ gradle_args = sys.argv[1:]
+ if options.java_home:
+ gradle_args.append('-Dorg.gradle.java.home=' + options.java_home)
+ return RunGradle(gradle_args)
if __name__ == '__main__':
sys.exit(Main())
diff --git a/tools/java.py b/tools/java.py
new file mode 100755
index 0000000..3abfcdd
--- /dev/null
+++ b/tools/java.py
@@ -0,0 +1,28 @@
+#!/usr/bin/env python
+# Copyright (c) 2019, 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 jdk
+import utils
+import subprocess
+import sys
+
+def run(args):
+ cmd = [jdk.GetJavaExecutable()] + args
+ utils.PrintCmd(cmd)
+ result = subprocess.check_output(cmd)
+ print result
+ return result
+
+def main():
+ try:
+ run(sys.argv[1:])
+ except subprocess.CalledProcessError as e:
+ # In case anything relevant was printed to stdout, normally this is already
+ # on stderr.
+ print e.output
+ return e.returncode
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/tools/javac.py b/tools/javac.py
new file mode 100755
index 0000000..0d8ac05
--- /dev/null
+++ b/tools/javac.py
@@ -0,0 +1,28 @@
+#!/usr/bin/env python
+# Copyright (c) 2019, 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 jdk
+import utils
+import subprocess
+import sys
+
+def run(args):
+ cmd = [jdk.GetJavacExecutable()] + args
+ utils.PrintCmd(cmd)
+ result = subprocess.check_output(cmd)
+ print result
+ return result
+
+def main():
+ try:
+ run(sys.argv[1:])
+ except subprocess.CalledProcessError as e:
+ # In case anything relevant was printed to stdout, normally this is already
+ # on stderr.
+ print e.output
+ return e.returncode
+
+if __name__ == '__main__':
+ sys.exit(main())
diff --git a/tools/jdk.py b/tools/jdk.py
new file mode 100755
index 0000000..5a20901
--- /dev/null
+++ b/tools/jdk.py
@@ -0,0 +1,44 @@
+#!/usr/bin/env python
+# Copyright (c) 2019, 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 os
+import sys
+import utils
+
+JDK_DIR = os.path.join(utils.REPO_ROOT, 'third_party', 'openjdk')
+
+def GetJdkHome():
+ root = os.path.join(JDK_DIR, 'openjdk-9.0.4')
+ if utils.IsLinux():
+ return os.path.join(root, 'linux')
+ elif utils.IsOsX():
+ return os.path.join(root, 'osx')
+ elif utils.IsWindows():
+ return os.path.join(root, 'windows')
+ else:
+ return os.environ['JAVA_HOME']
+ return jdkHome
+
+def GetJavaExecutable(jdkHome=None):
+ jdkHome = jdkHome if jdkHome else GetJdkHome()
+ executable = 'java.exe' if utils.IsWindows() else 'java'
+ return os.path.join(jdkHome, 'bin', executable) if jdkHome else executable
+
+def GetJavacExecutable(jdkHome=None):
+ jdkHome = jdkHome if jdkHome else GetJdkHome()
+ executable = 'javac.exe' if utils.IsWindows() else 'javac'
+ return os.path.join(jdkHome, 'bin', executable) if jdkHome else executable
+
+def EnsureJdk():
+ jdkHome = GetJdkHome()
+ jdkTgz = jdkHome + '.tar.gz'
+ jdkSha1 = jdkTgz + '.sha1'
+ utils.EnsureDepFromGoogleCloudStorage(jdkHome, jdkTgz, jdkSha1, 'JDK')
+
+def Main():
+ print GetJdkHome()
+
+if __name__ == '__main__':
+ sys.exit(Main())
diff --git a/tools/test.py b/tools/test.py
index bb6a98a..d296496 100755
--- a/tools/test.py
+++ b/tools/test.py
@@ -7,16 +7,17 @@
# if an argument is given, run only tests with that pattern. This script will
# force the tests to run, even if no input changed.
-import os
-import gradle
import optparse
+import os
import subprocess
import sys
import thread
import time
-import utils
import uuid
+
+import gradle
import notify
+import utils
ALL_ART_VMS = [
"default",
@@ -96,6 +97,8 @@
' Note that the directory will not be cleared before the test.')
result.add_option('--java-home', '--java_home',
help='Use a custom java version to run tests.')
+ result.add_option('--java-max-memory-size', '--java_max_memory_size',
+ help='Use a custom max memory size for the gradle java instance, eg, 4g')
result.add_option('--generate-golden-files-to', '--generate_golden_files_to',
help='Store dex files produced by tests in the specified directory.'
' It is aimed to be read on platforms with no host runtime available'
@@ -166,6 +169,8 @@
os.makedirs(options.test_dir)
if options.java_home:
gradle_args.append('-Dorg.gradle.java.home=' + options.java_home)
+ if options.java_max_memory_size:
+ gradle_args.append('-Dorg.gradle.jvmargs=-Xmx' + options.java_max_memory_size)
if options.generate_golden_files_to:
gradle_args.append('-Pgenerate_golden_files_to=' + options.generate_golden_files_to)
if not os.path.exists(options.generate_golden_files_to):
diff --git a/tools/utils.py b/tools/utils.py
index 08faec6..20d7bc7 100644
--- a/tools/utils.py
+++ b/tools/utils.py
@@ -156,7 +156,22 @@
return stdout
def IsWindows():
- return os.name == 'nt'
+ return sys.platform.startswith('win')
+
+def IsLinux():
+ return sys.platform.startswith('linux')
+
+def IsOsX():
+ return sys.platform.startswith('darwin')
+
+def EnsureDepFromGoogleCloudStorage(dep, tgz, sha1, msg):
+ if not os.path.exists(dep) or os.path.getmtime(tgz) < os.path.getmtime(sha1):
+ DownloadFromGoogleCloudStorage(sha1)
+ # Update the mtime of the tar file to make sure we do not run again unless
+ # there is an update.
+ os.utime(tgz, None)
+ else:
+ print 'Ensure cloud dependency:', msg, 'present'
def DownloadFromX20(sha1_file):
download_script = os.path.join(REPO_ROOT, 'tools', 'download_from_x20.py')