blob: 967923c14c834e4178f72b6e89a382fe3ffe4c86 [file] [log] [blame]
Mads Ager418d1ca2017-05-22 09:35:49 +02001// Copyright (c) 2016, the R8 project authors. Please see the AUTHORS file
2// for details. All rights reserved. Use of this source code is governed by a
3// BSD-style license that can be found in the LICENSE file.
Jean-Marie Henaff34d85f72017-06-14 10:32:04 +02004import org.gradle.internal.os.OperatingSystem
5import utils.Utils;
Mads Ager418d1ca2017-05-22 09:35:49 +02006
7apply plugin: 'java'
8apply plugin: 'idea'
9apply plugin: 'jacoco'
10
11apply from: 'copyAdditionalJctfCommonFiles.gradle'
12
13repositories {
14 mavenCentral()
15}
16
17// Custom source set for example tests and generated tests.
18sourceSets {
19 test {
20 java {
21 srcDirs = [
22 'src/test/java',
23 'build/generated/test/java',
24 ]
25 }
26 }
27 debugTestResources {
28 java {
29 srcDirs = ['src/test/debugTestResources']
30 }
31 output.resourcesDir = 'build/classes/debugTestResources'
32 }
Sebastien Hertz964c5c22017-05-23 15:22:23 +020033 debugTestResourcesJava8 {
34 java {
35 srcDirs = ['src/test/debugTestResourcesJava8']
36 }
37 output.resourcesDir = 'build/classes/debugTestResourcesJava8'
38 }
Mads Ager418d1ca2017-05-22 09:35:49 +020039 examples {
40 java {
41 srcDirs = ['src/test/examples']
42 }
43 output.resourcesDir = 'build/classes/examples'
44 }
45 examplesAndroidN {
46 java {
47 srcDirs = ['src/test/examplesAndroidN']
48 }
49 output.resourcesDir = 'build/classes/examplesAndroidN'
50 }
51 examplesAndroidO {
52 java {
53 srcDirs = ['src/test/examplesAndroidO']
54 }
55 output.resourcesDir = 'build/classes/examplesAndroidO'
56 }
57 jctfCommon {
58 java {
59 srcDirs = [
60 'third_party/jctf/Harness/src',
61 'third_party/jctf/LibTests/src/com/google/jctf/test/categories',
62 'third_party/jctf/LibTests/src/com/google/jctf/test/helper',
63 'third_party/jctf/LibTests/src/com/google/jctf/testHelpers',
64 'third_party/jctf/LibTests/src/org',
65 'build/additionalJctfCommonFiles'
66 ]
67 }
68 resources {
69 srcDirs = ['third_party/jctf/LibTests/resources']
70 }
71 }
72 jctfTests {
73 java {
74 srcDirs = [
75 'third_party/jctf/LibTests/src/com/google/jctf/test/lib',
76 // 'third_party/jctf/VMTests/src',
77 ]
78 }
79 }
80}
81
82dependencies {
83 compile 'net.sf.jopt-simple:jopt-simple:4.6'
84 compile group: 'com.google.guava', name: 'guava', version: '19.0'
Stephan Herhutb17bb8d2017-05-23 12:34:55 +020085 compile group: 'it.unimi.dsi', name: 'fastutil', version: '7.2.0'
Mads Ager418d1ca2017-05-22 09:35:49 +020086 compile group: 'org.apache.commons', name: 'commons-compress', version: '1.12'
87 compile group: 'org.ow2.asm', name: 'asm', version: '5.1'
88 compile group: 'org.ow2.asm', name: 'asm-commons', version: '5.1'
89 compile group: 'org.ow2.asm', name: 'asm-tree', version: '5.1'
90 compile group: 'org.ow2.asm', name: 'asm-util', version: '5.1'
91 testCompile sourceSets.examples.output
92 testCompile 'junit:junit:4.12'
93 testCompile group: 'org.smali', name: 'smali', version: '2.2b4'
94 testCompile files('third_party/jasmin/jasmin-2.4.jar')
95 testCompile files('third_party/jdwp-tests/apache-harmony-jdwp-tests-host.jar')
96 jctfCommonCompile 'junit:junit:4.12'
97 jctfTestsCompile 'junit:junit:4.12'
98 jctfTestsCompile sourceSets.jctfCommon.output
99 examplesAndroidOCompile group: 'org.ow2.asm', name: 'asm', version: '5.1'
100}
101
Jean-Marie Henaff39587a82017-06-08 15:20:13 +0200102def osString = OperatingSystem.current().isLinux() ? "linux" :
103 OperatingSystem.current().isMacOsX() ? "mac" : "windows"
Mads Ager418d1ca2017-05-22 09:35:49 +0200104
105def cloudDependencies = [
106 "tests" : [
107 "art.tar.gz"
108 ],
109 "third_party": [
110 "android_jar/lib-v14.tar.gz",
111 "android_jar/lib-v19.tar.gz",
112 "android_jar/lib-v24.tar.gz",
113 "android_jar/lib-v25.tar.gz",
114 "android_jar/lib-v26.tar.gz",
115 "proguard/proguard5.2.1.tar.gz",
116 "gradle/gradle.tar.gz",
117 "jdwp-tests.tar.gz",
118 "jasmin.tar.gz",
119 "jctf.tar.gz",
120 "android_cts_baseline.tar.gz",
121 ],
122 // All dex-vms have a fixed OS of Linux, as they are only supported on Linux, and will be run in a Docker
123 // container on other platforms where supported.
124 "tools" : [
125 "linux/art.tar.gz",
126 "linux/art-5.1.1.tar.gz",
127 "linux/art-6.0.1.tar.gz",
128 "linux/art-7.0.0.tar.gz",
129 "linux/dalvik.tar.gz",
130 "${osString}/dx.tar.gz",
131 ]
132]
133
134cloudDependencies.each { entry ->
135 entry.value.each { entryFile ->
136 task "download_deps_${entry.key}/${entryFile}"(type: Exec) {
137 def gzFile = "${entry.key}/${entryFile}"
138 def sha1File = "${gzFile}.sha1"
139 inputs.file sha1File
140 outputs.file gzFile
Jean-Marie Henaff872e4422017-06-13 10:26:20 +0200141 List<String> dlFromStorageArgs = ["-n", "-b", "r8-deps", "-u", "-s", "${sha1File}"]
142 if (OperatingSystem.current().isWindows()) {
143 executable "download_from_google_storage.bat"
144 args dlFromStorageArgs
145 } else {
146 executable "bash"
147 args "-c", "download_from_google_storage " + String.join(" ", dlFromStorageArgs)
148 }
Mads Ager418d1ca2017-05-22 09:35:49 +0200149 }
150 }
151}
152
153def x20Dependencies = [
154 "third_party": [
Søren Gjesse5ecb04a2017-06-13 09:44:32 +0200155 "gmail/gmail_android_170604.16.tar.gz",
Mads Ager418d1ca2017-05-22 09:35:49 +0200156 "gmscore/v4.tar.gz",
157 "gmscore/v5.tar.gz",
158 "gmscore/v6.tar.gz",
159 "gmscore/v7.tar.gz",
160 "gmscore/v8.tar.gz",
161 "gmscore/gmscore_v9.tar.gz",
162 "gmscore/gmscore_v10.tar.gz",
Stephan Herhut4e743302017-06-09 13:09:03 +0200163 "gmscore/latest.tar.gz",
Mads Agerae646402017-06-07 13:32:43 +0200164 "photos/2017-06-06.tar.gz",
Mads Ager418d1ca2017-05-22 09:35:49 +0200165 "youtube/youtube.android_12.10.tar.gz",
Søren Gjessefeac2ef2017-05-22 17:09:29 +0200166 "youtube/youtube.android_12.17.tar.gz",
Søren Gjesse9be84982017-06-09 14:21:03 +0200167 "youtube/youtube.android_12.22.tar.gz",
Mads Ager418d1ca2017-05-22 09:35:49 +0200168 "proguardsettings.tar.gz",
169 ],
170]
171
172x20Dependencies.each { entry ->
173 entry.value.each { entryFile ->
174 task "download_deps_${entry.key}/${entryFile}"(type: Exec) {
175 def gzFile = "${entry.key}/${entryFile}"
176 def sha1File = "${gzFile}.sha1"
177 inputs.file sha1File
178 outputs.file gzFile
179 executable "bash"
180 args "-c", "tools/download_from_x20.py ${sha1File}"
181 }
182 }
183}
184
Rico Wind897bb712017-05-23 10:44:29 +0200185task downloadProguard {
186 cloudDependencies.each { entry ->
187 entry.value.each { entryFile ->
188 if (entryFile.contains("proguard")) {
189 dependsOn "download_deps_${entry.key}/${entryFile}"
190 }
191 }
192 }
193}
194
Tamas Kenez0e10c562017-06-08 10:00:34 +0200195task downloadAndroidCts {
196 cloudDependencies.each { entry ->
197 entry.value.each { entryFile ->
198 if (entryFile.contains("android_cts_baseline")) {
199 dependsOn "download_deps_${entry.key}/${entryFile}"
200 }
201 }
202 }
203}
204
Mads Ager418d1ca2017-05-22 09:35:49 +0200205task downloadDeps {
206 cloudDependencies.each { entry ->
207 entry.value.each { entryFile ->
208 dependsOn "download_deps_${entry.key}/${entryFile}"
209 }
210 }
211 if (!project.hasProperty('no_internal')) {
212 x20Dependencies.each { entry ->
213 entry.value.each { entryFile ->
214 dependsOn "download_deps_${entry.key}/${entryFile}"
215 }
216 }
217 }
218}
219
220allprojects {
221 sourceCompatibility = JavaVersion.VERSION_1_8
222 targetCompatibility = JavaVersion.VERSION_1_8
223}
224
225tasks.withType(JavaCompile) {
226 options.compilerArgs << '-Xlint:unchecked'
227}
228
229compileJctfCommonJava {
230 dependsOn 'copyAdditionalJctfCommonFiles'
231 options.compilerArgs = ['-Xlint:none']
232}
233
234compileJctfTestsJava {
235 dependsOn 'jctfCommonClasses'
236 options.compilerArgs = ['-Xlint:none']
237}
238
239task R8(type: Jar) {
240 from sourceSets.main.output
241 baseName 'r8'
242 manifest {
243 attributes 'Main-Class': 'com.android.tools.r8.R8'
244 }
245 // In order to build without dependencies, pass the exclude_deps property using:
246 // gradle -Pexclude_deps R8
247 if (!project.hasProperty('exclude_deps')) {
248 // Also include dependencies
249 from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
250 }
251}
252
253task D8(type: Jar) {
254 from sourceSets.main.output
255 baseName 'd8'
256 manifest {
257 attributes 'Main-Class': 'com.android.tools.r8.D8'
258 }
259 // In order to build without dependencies, pass the exclude_deps property using:
260 // gradle -Pexclude_deps D8
261 if (!project.hasProperty('exclude_deps')) {
262 // Also include dependencies
263 from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
264 }
265}
266
267task CompatDx(type: Jar) {
268 from sourceSets.main.output
269 baseName 'compatdx'
270 manifest {
271 attributes 'Main-Class': 'com.android.tools.r8.compatdx.CompatDx'
272 }
273 // In order to build without dependencies, pass the exclude_deps property using:
274 // gradle -Pexclude_deps CompatDx
275 if (!project.hasProperty('exclude_deps')) {
276 // Also include dependencies
277 from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
278 }
279}
280
Tamas Kenez971eec62017-05-24 11:08:40 +0200281task D8Logger(type: Jar) {
282 from sourceSets.main.output
283 baseName 'd8logger'
284 manifest {
285 attributes 'Main-Class': 'com.android.tools.r8.D8Logger'
286 }
287 // In order to build without dependencies, pass the exclude_deps property using:
288 // gradle -Pexclude_deps D8Logger
289 if (!project.hasProperty('exclude_deps')) {
290 // Also include dependencies
291 from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
292 }
293}
294
Mads Ager418d1ca2017-05-22 09:35:49 +0200295task disasm(type: Jar) {
296 from sourceSets.main.output
297 baseName 'disasm'
298 manifest {
299 attributes 'Main-Class': 'com.android.tools.r8.Disassemble'
300 }
301 // In order to build without dependencies, pass the exclude_deps property using:
302 // gradle -Pexclude_deps D8
303 if (!project.hasProperty('exclude_deps')) {
304 // Also include dependencies
305 from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
306 }
307}
308
309task bisect(type: Jar) {
310 from sourceSets.main.output
311 baseName 'bisect'
312 manifest {
313 attributes 'Main-Class': 'com.android.tools.r8.bisect.Bisect'
314 }
315 // In order to build without dependencies, pass the exclude_deps property using:
316 // gradle -Pexclude_deps R8
317 if (!project.hasProperty('exclude_deps')) {
318 // Also include dependencies
319 from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }
320 }
321}
322
323task sourceJar(type: Jar, dependsOn: classes) {
324 classifier = 'src'
325 from sourceSets.main.allSource
326}
327
328task jctfCommonJar(type: Jar) {
329 from sourceSets.jctfCommon.output
330 baseName 'jctfCommon'
331}
332
333artifacts {
334 archives sourceJar
335}
336
337task createArtTests(type: Exec) {
338 def outputDir = "build/generated/test/java/com/android/tools/r8/art"
Mads Ager7e5bd722017-05-24 07:17:27 +0200339 def createArtTestsScript = "tools/create_art_tests.py"
Mads Ager418d1ca2017-05-22 09:35:49 +0200340 inputs.file "tests/art.tar.gz"
341 inputs.file createArtTestsScript
342 outputs.dir outputDir
343 dependsOn downloadDeps
Mads Ager677e3002017-05-24 07:54:51 +0200344 commandLine "python", createArtTestsScript
Mads Ager418d1ca2017-05-22 09:35:49 +0200345 workingDir = projectDir
346}
347
348task createJctfTests(type: Exec) {
Stephan Herhutea6ee582017-05-23 13:14:34 +0200349 def outputDir = "build/generated/test/java/com/android/tools/r8/jctf"
Tamas Kenez25a99e92017-05-29 10:15:30 +0200350 def script = "tools/create_jctf_tests.py"
Mads Ager418d1ca2017-05-22 09:35:49 +0200351 inputs.file script
352 outputs.dir outputDir
353 dependsOn downloadDeps
Tamas Kenez25a99e92017-05-29 10:15:30 +0200354 commandLine "python", script
Mads Ager418d1ca2017-05-22 09:35:49 +0200355 workingDir = projectDir
356}
357
358compileTestJava {
359 dependsOn createArtTests
360 dependsOn createJctfTests
361}
362
363task buildDebugInfoExamplesDex {
364 def examplesDir = file("src/test/java")
365 def hostJar = "debuginfo_examples.jar"
366 def hostDexJar = "debuginfo_examples_dex.jar"
367 task "compile_debuginfo_examples"(type: JavaCompile) {
368 source = fileTree(dir: examplesDir, include: "com/android/tools/r8/debuginfo/*Test.java")
369 destinationDir = file("build/test/debuginfo_examples/classes")
370 classpath = sourceSets.main.compileClasspath
371 sourceCompatibility = JavaVersion.VERSION_1_7
372 targetCompatibility = JavaVersion.VERSION_1_7
373 options.compilerArgs += ["-Xlint:-options"]
374 }
375 task "jar_debuginfo_examples"(type: Jar, dependsOn: "compile_debuginfo_examples") {
376 archiveName = hostJar
377 destinationDir = file("build/test/")
378 from "build/test/debuginfo_examples/classes"
379 include "**/*.class"
380 }
381 task "dex_debuginfo_examples"(type: Exec,
382 dependsOn: ["jar_debuginfo_examples", "downloadDeps"]) {
Jean-Marie Henaff39587a82017-06-08 15:20:13 +0200383 if (OperatingSystem.current().isWindows()) {
384 executable file("tools/windows/dx/bin/dx.bat")
385 } else {
386 executable file("tools/linux/dx/bin/dx");
387 }
Mads Ager418d1ca2017-05-22 09:35:49 +0200388 args "--dex"
389 args "--output=build/test/${hostDexJar}"
390 args "build/test/${hostJar}"
391 inputs.file file("build/test/${hostJar}")
392 outputs.file file("build/test/${hostDexJar}")
393 }
394 dependsOn dex_debuginfo_examples
395}
396
397task buildDebugTestResourcesJars {
Mads Ager418d1ca2017-05-22 09:35:49 +0200398 def resourcesDir = file("src/test/debugTestResources")
399 def hostJar = "debug_test_resources.jar"
400 task "compile_debugTestResources"(type: JavaCompile) {
401 source = fileTree(dir: resourcesDir, include: '**/*.java')
402 destinationDir = file("build/test/debugTestResources/classes")
403 classpath = sourceSets.main.compileClasspath
404 sourceCompatibility = JavaVersion.VERSION_1_7
405 targetCompatibility = JavaVersion.VERSION_1_7
406 options.compilerArgs += ["-g", "-Xlint:-options"]
407 }
408 task "jar_debugTestResources"(type: Jar, dependsOn: "compile_debugTestResources") {
409 archiveName = hostJar
410 destinationDir = file("build/test/")
411 from "build/test/debugTestResources/classes"
412 include "**/*.class"
413 }
Sebastien Hertz964c5c22017-05-23 15:22:23 +0200414 def java8ResourcesDir = file("src/test/debugTestResourcesJava8")
415 def java8HostJar = "debug_test_resources_java8.jar"
416 task "compile_debugTestResourcesJava8"(type: JavaCompile) {
417 source = fileTree(dir: java8ResourcesDir, include: '**/*.java')
418 destinationDir = file("build/test/debugTestResourcesJava8/classes")
419 classpath = sourceSets.main.compileClasspath
420 sourceCompatibility = JavaVersion.VERSION_1_8
421 targetCompatibility = JavaVersion.VERSION_1_8
422 options.compilerArgs += ["-g", "-Xlint:-options"]
423 }
424 task "jar_debugTestResourcesJava8"(type: Jar, dependsOn: "compile_debugTestResourcesJava8") {
425 archiveName = java8HostJar
426 destinationDir = file("build/test/")
427 from "build/test/debugTestResourcesJava8/classes"
428 include "**/*.class"
429 }
430 dependsOn downloadDeps
Mads Ager418d1ca2017-05-22 09:35:49 +0200431 dependsOn jar_debugTestResources
Sebastien Hertz964c5c22017-05-23 15:22:23 +0200432 dependsOn jar_debugTestResourcesJava8
Mads Ager418d1ca2017-05-22 09:35:49 +0200433}
434
435task buildExampleJars {
Rico Wind897bb712017-05-23 10:44:29 +0200436 dependsOn downloadProguard
Mads Ager418d1ca2017-05-22 09:35:49 +0200437 def examplesDir = file("src/test/examples")
Jean-Marie Henaff872e4422017-06-13 10:26:20 +0200438 def proguardScript
439 if (OperatingSystem.current().isWindows()) {
440 proguardScript = "third_party/proguard/proguard5.2.1/bin/proguard.bat"
441 } else {
442 proguardScript = "third_party/proguard/proguard5.2.1/bin/proguard.sh"
443 }
Mads Ager418d1ca2017-05-22 09:35:49 +0200444 task "compile_examples"(type: JavaCompile) {
445 source = fileTree(dir: examplesDir, include: '**/*.java')
446 destinationDir = file("build/test/examples/classes")
447 classpath = sourceSets.main.compileClasspath
448 sourceCompatibility = JavaVersion.VERSION_1_7
449 targetCompatibility = JavaVersion.VERSION_1_7
450 options.compilerArgs += ["-Xlint:-options"]
451 }
452 examplesDir.eachDir { dir ->
453 def name = dir.getName();
454 def exampleOutputDir = file("build/test/examples");
455 def jarName = "${name}.jar"
456 dependsOn "jar_example_${name}"
457 // The "throwing" test verifies debugging/stack info on the post-proguarded output.
458 def proguardConfigPath = "${dir}/proguard.cfg"
459 if (new File(proguardConfigPath).exists()) {
460 task "pre_proguard_example_${name}"(type: Jar, dependsOn: "compile_examples") {
461 archiveName = "${name}_pre_proguard.jar"
462 destinationDir = exampleOutputDir
463 from "build/test/examples/classes"
464 include "**/" + name + "/**/*.class"
465 }
466 def jarPath = files(tasks.getByPath("pre_proguard_example_${name}")).files.first();
467 def proguardJarPath = "${exampleOutputDir}/${jarName}"
468 def proguardMapPath = "${exampleOutputDir}/${name}/${name}.map"
469 task "jar_example_${name}"(type: Exec, dependsOn: "pre_proguard_example_${name}") {
470 inputs.files tasks.getByPath("pre_proguard_example_${name}")
471 inputs.file proguardConfigPath
472 // Enable these to get stdout and stderr redirected to files...
473 // standardOutput = new FileOutputStream('proguard.stdout')
474 // errorOutput = new FileOutputStream('proguard.stderr')
Jean-Marie Henaff872e4422017-06-13 10:26:20 +0200475 def proguardArguments = "-verbose -dontwarn java.** -injars ${jarPath}" +
Mads Ager418d1ca2017-05-22 09:35:49 +0200476 " -outjars ${proguardJarPath}" +
477 " -include ${proguardConfigPath}" +
Jean-Marie Henaff872e4422017-06-13 10:26:20 +0200478 " -printmapping ${proguardMapPath}"
479 if (OperatingSystem.current().isWindows()) {
480 executable "${proguardScript}"
481 args "${proguardArguments}"
482 } else {
483 executable "bash"
484 args "-c", "${proguardScript} '${proguardArguments}'"
485 }
Mads Ager418d1ca2017-05-22 09:35:49 +0200486 outputs.file proguardJarPath
487 }
488 } else {
489 task "jar_example_${name}"(type: Jar, dependsOn: "compile_examples") {
490 archiveName = jarName
491 destinationDir = exampleOutputDir
492 from "build/test/examples/classes"
493 include "**/" + name + "/**/*.class"
494 }
495 }
496 }
497}
498
499task buildExampleAndroidNJars {
500 dependsOn downloadDeps
501 def examplesDir = file("src/test/examplesAndroidN")
502 task "compile_examplesAndroidN"(type: JavaCompile) {
503 source = fileTree(dir: examplesDir, include: '**/*.java')
504 destinationDir = file("build/test/examplesAndroidN/classes")
505 classpath = sourceSets.main.compileClasspath
506 sourceCompatibility = JavaVersion.VERSION_1_8
507 targetCompatibility = JavaVersion.VERSION_1_8
508 options.compilerArgs += ["-Xlint:-options"]
509 }
510 examplesDir.eachDir { dir ->
511 def name = dir.getName();
512 def exampleOutputDir = file("build/test/examplesAndroidN");
513 def jarName = "${name}.jar"
514 dependsOn "jar_examplesAndroidN_${name}"
515 task "jar_examplesAndroidN_${name}"(type: Jar, dependsOn: "compile_examplesAndroidN") {
516 archiveName = jarName
517 destinationDir = exampleOutputDir
518 from "build/test/examplesAndroidN/classes"
519 include "**/" + name + "/**/*.class"
520 }
521 }
522}
523
524
525task buildExampleAndroidOJars {
526 dependsOn downloadDeps
527 def examplesDir = file("src/test/examplesAndroidO")
528 // NOTE: we want to enable a scenario when test needs to reference some
529 // classes generated by legacy (1.6) Java compiler to test some specific
530 // behaviour. To do so we compile all the java files located in sub-directory
531 // called 'legacy' with Java 1.6, then compile the rest of the files with
532 // Java 1.8 and a reference to previously generated 1.6 classes.
533
534 // Compiling all classes in dirs 'legacy' with old Java version.
535 task "compile_examplesAndroidO_Legacy"(type: JavaCompile) {
536 source = fileTree(dir: examplesDir, include: '**/legacy/**/*.java')
537 destinationDir = file("build/test/examplesAndroidOLegacy/classes")
538 classpath = sourceSets.main.compileClasspath
539 sourceCompatibility = JavaVersion.VERSION_1_6
540 targetCompatibility = JavaVersion.VERSION_1_6
541 options.compilerArgs += ["-Xlint:-options", "-parameters"]
542 }
543 // Compiling the rest of the files as Java 1.8 code.
544 task "compile_examplesAndroidO"(type: JavaCompile) {
545 dependsOn "compile_examplesAndroidO_Legacy"
546 source = fileTree(dir: examplesDir, include: '**/*.java', exclude: '**/legacy/**/*.java')
547 destinationDir = file("build/test/examplesAndroidO/classes")
548 classpath = sourceSets.main.compileClasspath
549 classpath += files("build/test/examplesAndroidOLegacy/classes")
550 sourceCompatibility = JavaVersion.VERSION_1_8
551 targetCompatibility = JavaVersion.VERSION_1_8
552 options.compilerArgs += ["-Xlint:-options", "-parameters"]
553 }
554 examplesDir.eachDir { dir ->
555 def name = dir.getName();
556 def destinationDir = file("build/test/examplesAndroidO/classes");
557 if (file("src/test/examplesAndroidO/" + name + "/TestGenerator.java").isFile()) {
558 task "generate_examplesAndroidO_${name}"(type: JavaExec,
559 dependsOn: "compile_examplesAndroidO") {
560 main = name + ".TestGenerator"
561 classpath = files(destinationDir, sourceSets.main.compileClasspath)
562 args destinationDir
563 }
564 } else {
565 task "generate_examplesAndroidO_${name}" () {}
566 }
567 }
568 examplesDir.eachDir { dir ->
569 def name = dir.getName();
570 def exampleOutputDir = file("build/test/examplesAndroidO");
571 def jarName = "${name}.jar"
572 dependsOn "jar_examplesAndroidO_${name}"
573 task "jar_examplesAndroidO_${name}"(type: Jar, dependsOn: ["compile_examplesAndroidO",
574 "generate_examplesAndroidO_${name}"]) {
575 archiveName = jarName
576 destinationDir = exampleOutputDir
577 from "build/test/examplesAndroidO/classes" // Java 1.8 classes
578 from "build/test/examplesAndroidOLegacy/classes" // Java 1.6 classes
579 include "**/" + name + "/**/*.class"
580 // Do not include generator into the test runtime jar, it is not useful.
581 // Otherwise, shrinking will need ASM jars.
582 exclude "**/TestGenerator*"
583 }
584 }
585}
586
587task buildExamples {
Jean-Marie Henaff39587a82017-06-08 15:20:13 +0200588 if (OperatingSystem.current().isMacOsX() || OperatingSystem.current().isWindows()) {
589 logger.lifecycle("WARNING: Testing (including building examples) is only partially supported on your " +
590 "platform (" + OperatingSystem.current().getName() + ").")
Mads Ager418d1ca2017-05-22 09:35:49 +0200591 } else if (!OperatingSystem.current().isLinux()) {
592 logger.lifecycle("WARNING: Testing (including building examples) is not supported on your platform. " +
Jean-Marie Henaff39587a82017-06-08 15:20:13 +0200593 "It is fully supported on Linux and partially supported on Mac OS and Windows")
Mads Ager418d1ca2017-05-22 09:35:49 +0200594 return;
595 }
596 dependsOn buildDebugTestResourcesJars
597 dependsOn buildExampleJars
598 dependsOn buildExampleAndroidNJars
599 dependsOn buildExampleAndroidOJars
600 def examplesDir = file("src/test/examples")
Yohann Rousself820a572017-05-31 20:25:51 +0200601 def noDexTests = [
602 "multidex",
603 "multidex002",
604 "multidex004",
605 ]
Mads Ager418d1ca2017-05-22 09:35:49 +0200606 examplesDir.eachDir { dir ->
607 def name = dir.getName();
Yohann Rousself820a572017-05-31 20:25:51 +0200608 if (!(name in noDexTests)) {
609 dependsOn "dex_example_${name}"
610 def exampleOutputDir = file("build/test/examples/" + name);
611 def dexPath = file("${exampleOutputDir}")
612 def debug = (name == "throwing")
613 if (!dexPath.exists()) {
614 dexPath.mkdirs()
615 }
616 task "dex_example_${name}"(type: dx.Dx, dependsOn: "jar_example_${name}") {
617 source = files(tasks.getByPath("jar_example_${name}")).asFileTree
618 destination = dexPath
619 debug = debug
620 }
Mads Ager418d1ca2017-05-22 09:35:49 +0200621 }
622 }
623}
624
625task buildSmali {
626 def smaliDir = file("src/test/smali")
627 smaliDir.eachDirRecurse() { dir ->
628 def name = dir.getName();
629 def relativeDir = smaliDir.toPath().relativize(dir.toPath());
630 def smaliOutputDir = file("build/test/smali/" + relativeDir);
631 smaliOutputDir.mkdirs()
632 outputs.dir smaliOutputDir
633 def taskName = "smali_build_${relativeDir.toString().replace('/', '_')}"
634 def smaliFiles = fileTree(dir: dir, include: '*.smali')
635 def javaFiles = fileTree(dir: dir, include: '*.java')
636 def destDir = smaliOutputDir;
637 def destFile = destDir.toPath().resolve("${name}.dex").toFile()
638 def intermediateFileName = "${name}-intermediate.dex";
639 def intermediateFile = destDir.toPath().resolve(intermediateFileName).toFile()
640 if (javaFiles.empty) {
641 if (!smaliFiles.empty) {
642 dependsOn "${taskName}_smali"
643 task "${taskName}_smali"(type: smali.Smali) {
644 source = smaliFiles
645 destination = destFile
646 }
647 }
648 } else {
649 dependsOn "${taskName}_dexmerger"
650 task "${taskName}_smali"(type: smali.Smali) {
651 source = smaliFiles
652 destination = intermediateFile
653 }
654 task "${taskName}_java"(type: JavaCompile) {
655 source = javaFiles
656 destinationDir destDir
657 classpath = sourceSets.main.compileClasspath
658 sourceCompatibility = JavaVersion.VERSION_1_7
659 targetCompatibility = JavaVersion.VERSION_1_7
660 options.compilerArgs += ["-Xlint:-options"]
661 }
662 task "${taskName}_jar"(type: Jar, dependsOn: "${taskName}_java") {
663 archiveName = "Test.jar"
664 destinationDir = destDir
665 from fileTree(dir: destDir, include: 'Test.class')
666 }
667 task "${taskName}_dx"(type: dx.Dx, dependsOn: "${taskName}_jar") {
668 source = fileTree(dir: destDir, include: 'Test.jar')
669 destination = destDir
670 }
671 task "${taskName}_dexmerger"(
672 type: dx.DexMerger, dependsOn: ["${taskName}_dx", "${taskName}_smali"]) {
673 source = fileTree(dir: destDir, include: ["classes.dex", intermediateFileName])
674 destination = destFile
675 }
676 }
677 }
678}
679
680tasks.withType(Test) {
681 def userDefinedCoresPerFork = System.getenv('R8_GRADLE_CORES_PER_FORK')
682 def coresPerFork = userDefinedCoresPerFork ? userDefinedCoresPerFork.toInteger() : 3
683 // See https://docs.gradle.org/current/dsl/org.gradle.api.tasks.testing.Test.html.
684 maxParallelForks = Runtime.runtime.availableProcessors().intdiv(coresPerFork) ?: 1
685 forkEvery = 0
686 // Use the Concurrent Mark Sweep GC (CMS) to keep memory usage at a resonable level.
687 jvmArgs = ["-XX:+UseConcMarkSweepGC"]
688}
689
690task buildPreNJdwpTestsJar(type: Jar) {
691 baseName = 'jdwp-tests-preN'
692 from zipTree('third_party/jdwp-tests/apache-harmony-jdwp-tests-host.jar')
693 // Exclude the classes containing java8
694 exclude 'org/apache/harmony/jpda/tests/jdwp/InterfaceType/*.class'
695 exclude 'org/apache/harmony/jpda/tests/jdwp/ObjectReference/InvokeMethodDefault*.class'
696 includeEmptyDirs = false
697}
698
699test {
700 testLogging.exceptionFormat = 'full'
701 if (project.hasProperty('print_test_stdout')) {
702 testLogging.showStandardStreams = true
703 }
704 if (project.hasProperty('dex_vm')) {
705 println "Running with non default vm: " + project.property('dex_vm')
706 systemProperty 'dex_vm', project.property('dex_vm')
707 if (project.property('dex_vm') == '5.1.1' || project.property('dex_vm') == '6.0.1') {
708 // R8 and D8 compute the dex file version number based on the input.
709 // Jack generates dex files with version 37 which art 5.1.1 and 6.0.1 will not run.
710 // Therefore we skip the jack generated art tests with those art versions.
711 exclude "com/android/tools/r8/art/jack/**"
712 }
713 }
714 if (project.hasProperty('one_line_per_test')) {
715 beforeTest { desc ->
716 println "Start executing test ${desc.name} [${desc.className}]"
717 }
718 afterTest { desc, result ->
719 println "Done executing test ${desc.name} [${desc.className}] with result: ${result.resultType}"
720 }
721 }
722 if (project.hasProperty('no_internal')) {
723 exclude "com/android/tools/r8/internal/**"
724 }
725 if (project.hasProperty('only_internal')) {
726 include "com/android/tools/r8/internal/**"
727 }
728 if (project.hasProperty('tool')) {
729 if (project.property('tool') == 'r8') {
730 exclude "com/android/tools/r8/art/*/d8/**"
Tamas Kenez69c2e8b2017-05-31 13:41:07 +0200731 exclude "com/android/tools/r8/jctf/d8/**"
Mads Ager418d1ca2017-05-22 09:35:49 +0200732 } else {
733 assert(project.property('tool') == 'd8')
734 exclude "com/android/tools/r8/art/*/r8/**"
Tamas Kenez69c2e8b2017-05-31 13:41:07 +0200735 exclude "com/android/tools/r8/jctf/r8/**"
Mads Ager418d1ca2017-05-22 09:35:49 +0200736 }
737 }
738 if (!project.hasProperty('all_tests')) {
739 exclude "com/android/tools/r8/art/dx/**"
740 exclude "com/android/tools/r8/art/jack/**"
741 }
742 // TODO(tamaskenez) enable jctf on all_tests when consolidated
743 if (!project.hasProperty('jctf') && !project.hasProperty('only_jctf')) {
Stephan Herhutea6ee582017-05-23 13:14:34 +0200744 exclude "com/android/tools/r8/jctf/**"
Mads Ager418d1ca2017-05-22 09:35:49 +0200745 }
746 if (project.hasProperty('only_jctf')) {
Stephan Herhutea6ee582017-05-23 13:14:34 +0200747 include "com/android/tools/r8/jctf/**"
Mads Ager418d1ca2017-05-22 09:35:49 +0200748 }
749 if (project.hasProperty('jctf_compile_only')) {
750 println "JCTF: compiling only"
751 systemProperty 'jctf_compile_only', '1'
752 }
753
Jean-Marie Henaff39587a82017-06-08 15:20:13 +0200754 if (OperatingSystem.current().isLinux()
755 || OperatingSystem.current().isMacOsX()
756 || OperatingSystem.current().isWindows()) {
Mads Ager418d1ca2017-05-22 09:35:49 +0200757 if (OperatingSystem.current().isMacOsX()) {
758 logger.lifecycle("WARNING: Testing in only partially supported on Mac OS. " +
759 "Art only runs on Linux and tests requiring Art runs in a Docker container, which must be present. " +
760 "See tools/docker/README.md for details.")
761 }
Jean-Marie Henaff39587a82017-06-08 15:20:13 +0200762 if (OperatingSystem.current().isWindows()) {
763 logger.lifecycle("WARNING: Testing in only partially supported on Windows. " +
764 "Art only runs on Linux and tests requiring Art will be skipped")
765 }
Mads Ager418d1ca2017-05-22 09:35:49 +0200766 dependsOn downloadDeps
767 dependsOn buildExamples
768 dependsOn buildSmali
769 dependsOn jctfCommonJar
770 dependsOn jctfTestsClasses
771 dependsOn buildDebugInfoExamplesDex
772 dependsOn buildPreNJdwpTestsJar
773 } else {
774 logger.lifecycle("WARNING: Testing in not supported on your platform. Testing is only fully supported on " +
Jean-Marie Henaff39587a82017-06-08 15:20:13 +0200775 "Linux and partially supported on Mac OS and Windows. Art does not run on other platforms.")
Mads Ager418d1ca2017-05-22 09:35:49 +0200776 }
777}
778
779// The Art tests we use for R8 are pre-build and downloaded from Google Cloud Storage.
780//
781// To build and upload a new set of the Art tests for use with R8 follow these steps:
782//
783// First of all an Android checkout is required. Currently it must be located
784// in $HOME/android/master.
785//
786// TODO(ricow): simplify this
787//
788// Before: update the checked in art, see scripts/update-host-art.sh
789//
790// 1. Get an android checkout in $HOME/android/master and apply the patch from
791// https://android-review.googlesource.com/#/c/294187/
792//
793// 2. run the following commands in the Android checkout directory:
794//
795// source build/envsetup.sh
796// lunch aosp_angler-userdebug
797// make -j30 test-art-host
798//
799// 3. In the R8 project root directory, make sure we have a clean state before starting:
800// tools/gradle.py downloadDeps
801// tools/gradle.py clean
802// rm -rf tests/art
803//
804// 4. Now build in the R8 checkout (-P hack to not generate dirs when not running this target)
805// Make sure you have smali on your path, there is a build binary in the out directory of
806// the android checkout:
807//
808// tools/gradle.py -Pandroid_source buildArtTests
809//
810// 4a. If any failures are produced in step 4, figure out what went wrong and add an entry in
811// skippedTests with an explanation. Rerun from step 3.
812//
813// 5. Run the tests:
814// tools/gradle.py clean
815// tools/test.py
816//
817// 5a. If any more tests fail, either fix the issue or add them to the toBeTriaged list (note that
818// you need to change "_" to "-" from stdout). Rerun from step 3 if anything was added to
819// toBeTriaged.
820//
821// 6. To upload a new version to Google Cloud Storage
822// cd tests
823// upload_to_google_storage.py -a --bucket r8-deps art
824
825enum DexTool {
826 JACK,
827 DX
828}
829
830def androidCheckoutDir = file("${System.env.HOME}/android/master")
831def androidCheckoutJack = file("${androidCheckoutDir}/out/host/linux-x86/bin/jack");
832def androidCheckoutJackServer = file("${androidCheckoutDir}/out/host/linux-x86/bin/jack-admin");
833
834def artTestDir = file("${androidCheckoutDir}/art/test")
835
836if (project.hasProperty('android_source')) {
837 task buildArtTests {
838 outputs.upToDateWhen { false }
839 def toBeTriaged = [
840 "903-hello-tagging",
841 "904-object-allocation",
842 "905-object-free",
843 "906-iterate-heap",
844 "907-get-loaded-classes",
845 "908-gc-start-finish",
846 "954-invoke-polymorphic-verifier",
847 "955-methodhandles-smali",
848 "596-monitor-inflation",
849 ]
850 def skippedTests = toBeTriaged + [
851 // This test produces no jar.
852 "000-nop",
853 // This does not build, as it tests the error when the application exceeds more
854 // than 65536 methods
855 "089-many-methods",
856 // Requires some jack beta jar
857 "956-methodhandles",
858 ]
859
860 def skippedTestsDx = [
861 // Tests with custom build scripts, where javac is not passed the options
862 // -source 1.7 -target 1.7.
863 "462-checker-inlining-across-dex-files",
864 "556-invoke-super",
865 "569-checker-pattern-replacement",
866 // These tests use jack even when --build-with-javac-dx is specified.
867 "004-JniTest",
868 "048-reflect-v8",
869 "146-bad-interface",
870 "563-checker-invoke-super",
871 "580-checker-string-fact-intrinsics", // java.lang.StringFactory
872 "604-hot-static-interface",
873 "957-methodhandle-transforms",
874 "958-methodhandle-emulated-stackframe",
875 "959-invoke-polymorphic-accessors",
876 "961-default-iface-resolution-gen",
877 "962-iface-static",
878 "963-default-range-smali",
879 "964-default-iface-init-gen",
880 "965-default-verify",
881 "966-default-conflict",
882 "967-default-ame",
883 "968-default-partial-compile-gen",
884 "969-iface-super",
885 "970-iface-super-resolution-gen",
886 "971-iface-super",
887 // These tests does not build with --build-with-javac-dx
888 "004-NativeAllocations", // Javac error
889 "031-class-attributes",
890 "138-duplicate-classes-check",
891 "157-void-class", // Javac error
892 "580-checker-string-factory-intrinsics",
893 "612-jit-dex-cache",
894 "613-inlining-dex-cache",
895 "900-hello-plugin", // --experimental agents
896 "901-hello-ti-agent", // --experimental agents
897 "902-hello-transformation", // --experimental agents
898 "909-attach-agent", // --experimental agents
899 "946-obsolete-throw", // -source 1.7 -target 1.7, but use lambda
900 "950-redefine-intrinsic", // -source 1.7 -target 1.7, but use method references
901 "951-threaded-obsolete", // -source 1.7 -target 1.7, but use lambda
902 "960-default-smali", // --experimental default-methods
903 // These tests force the build to use jack
904 "953-invoke-polymorphic-compiler",
905 "958-methodhandle-stackframe",
906 ]
907
908 def artTestBuildDir = file("${projectDir}/tests/art")
909
910 if (androidCheckoutDir.exists()) {
911 dependsOn downloadDeps
912 artTestBuildDir.mkdirs()
913 // Ensure Jack server is running.
914 "${androidCheckoutJackServer} start-server".execute()
915 artTestDir.eachDir { dir ->
916 def name = dir.getName();
917 def markerFile = dir.toPath().resolve("info.txt").toFile();
918 if (markerFile.exists() && !(name in skippedTests)) {
919 if (!(name in skippedTestsDx)) {
920 dependsOn buildArtTest(androidCheckoutDir, artTestBuildDir, dir, DexTool.DX);
921 }
922 dependsOn buildArtTest(androidCheckoutDir, artTestBuildDir, dir, DexTool.JACK);
923 }
924 }
925 }
926 doFirst {
927 if (!androidCheckoutDir.exists()) {
928 throw new InvalidUserDataException(
929 "This task requires an Android checkout in ${androidCheckoutDir}");
930 } else if (!androidCheckoutJack.exists() ||
931 !androidCheckoutJackServer.exists()) {
932 throw new InvalidUserDataException(
933 "This task requires that tools for host testing have been build in the " +
934 "Android checkout in ${androidCheckoutDir}");
935 }
936 }
937 doLast {
938 copy {
939 from file("${androidCheckoutDir}/out/host/linux-x86/nativetest64")
940 into file("${artTestBuildDir}/lib64")
941 include 'lib*.so'
942 }
943 copy {
944 from file("${androidCheckoutDir}/out/host/linux-x86/lib64")
945 into file("${artTestBuildDir}/lib64")
946 include 'libart.so'
947 include 'libbacktrace.so'
948 include 'libbase.so'
949 include 'libc++.so'
950 include 'libcutils.so'
951 include 'liblz4.so'
952 include 'liblzma.so'
953 include 'libnativebridge.so'
954 include 'libnativeloader.so'
955 include 'libsigchain.so'
956 include 'libunwind.so'
957 include 'libziparchive.so'
958 }
959 copy {
960 from file("${androidCheckoutDir}/out/host/linux-x86/nativetest")
961 into file("${artTestBuildDir}/lib")
962 include 'lib*.so'
963 }
964 copy {
965 from file("${androidCheckoutDir}/out/host/linux-x86/lib")
966 into file("${artTestBuildDir}/lib")
967 include 'libart.so'
968 include 'libbacktrace.so'
969 include 'libbase.so'
970 include 'libc++.so'
971 include 'libcutils.so'
972 include 'liblz4.so'
973 include 'liblzma.so'
974 include 'libnativebridge.so'
975 include 'libnativeloader.so'
976 include 'libsigchain.so'
977 include 'libunwind.so'
978 include 'libziparchive.so'
979 }
980 }
981 }
982}
983
984def buildArtTest(androidCheckoutDir, artTestBuildDir, dir, dexTool) {
985 def artTestDir = file("${androidCheckoutDir}/art/test")
986 def artRunTestScript = file("${artTestDir}/run-test")
987 def dxExecutable = new File("tools/linux/dx/bin/dx");
Jean-Marie Henaff34d85f72017-06-14 10:32:04 +0200988 def dexMergerExecutable = Utils.dexMergerExecutable()
Mads Ager418d1ca2017-05-22 09:35:49 +0200989 def dexToolName = dexTool == DexTool.DX ? "dx" : "jack"
990
991 def name = dir.getName();
992 def buildTask = "build_art_test_${dexToolName}_${name}"
993 def sanitizeTask = "sanitize_art_test_${dexToolName}_${name}"
994 def copyCheckTask = "copy_check_art_test_${dexToolName}_${name}"
995 def smaliToDexTask = "smali_to_dex_${dexToolName}_${name}"
996
997 def buildInputs = fileTree(dir: dir, include: '**/*')
998 def testDir = file("${artTestBuildDir}/${dexToolName}/${name}")
999 def outputJar = testDir.toPath().resolve("${name}.jar").toFile()
1000 testDir.mkdirs()
1001 if (dexTool == DexTool.DX) {
1002 task "$buildTask"(type: Exec) {
1003 outputs.upToDateWhen { false }
1004 inputs.file buildInputs
1005 executable "${artRunTestScript}"
1006 args "--host"
1007 args "--build-only"
1008 args "--build-with-javac-dx"
1009 args "--output-path", "${testDir}"
1010 args "${name}"
1011 environment DX: "${dxExecutable.absolutePath}"
1012 environment DXMERGER: "${dexMergerExecutable.absolutePath}"
1013 outputs.file outputJar
1014 }
1015 } else {
1016 assert dexTool == DexTool.JACK
1017 def javaLibs = "${androidCheckoutDir}/out/host/common/obj/JAVA_LIBRARIES"
1018 def jackClasspath = "${javaLibs}/core-libart-hostdex_intermediates/classes.jack:" +
1019 "${javaLibs}/core-oj-hostdex_intermediates/classes.jack"
1020 task "$buildTask"(type: Exec) {
1021 outputs.upToDateWhen { false }
1022 inputs.file buildInputs
1023 executable "${artRunTestScript}"
1024 args "--host"
1025 args "--build-only"
1026 args "--output-path", "${testDir}"
1027 args "${name}"
1028 environment JACK: "${androidCheckoutDir}/out/host/linux-x86/bin/jack"
1029 environment JACK_CLASSPATH: jackClasspath
1030 environment DXMERGER: "${dexMergerExecutable.absolutePath}"
1031 environment ANDROID_BUILD_TOP: "${androidCheckoutDir}"
1032 outputs.file outputJar
1033 }
1034 }
1035 task "${sanitizeTask}"(type: Exec, dependsOn: buildTask) {
1036 outputs.upToDateWhen { false }
1037 executable "/bin/bash"
1038 args "-c"
1039 args "rm -rf ${testDir}/smali_*.dex ${testDir}/*-ex.dex ${testDir}/*-ex.jar" +
1040 " ${testDir}/classes-ex ${testDir}/check"
1041 }
1042
1043 task "${smaliToDexTask}"(type: Exec) {
1044 workingDir "${testDir}/smali"
1045 executable "/bin/bash"
1046 args "-c", "smali -o out.dex *.smali"
1047 }
1048
1049 task "${copyCheckTask}"(type: Copy, dependsOn: sanitizeTask) {
1050 def smali_dir = file("${dir}/smali")
1051 outputs.upToDateWhen { false }
1052 if (smali_dir.exists() && dexTool == DexTool.DX) {
1053 dependsOn smaliToDexTask
1054 }
1055 from("${artTestDir}/${name}") {
1056 include 'check'
1057 }
1058 into testDir
1059 }
1060
1061 return copyCheckTask
1062}
1063
1064task javadocD8(type: Javadoc) {
1065 classpath = sourceSets.main.compileClasspath
1066 source = sourceSets.main.allJava
1067 include '**/com/android/tools/r8/BaseCommand.java'
1068 include '**/com/android/tools/r8/BaseOutput.java'
1069 include '**/com/android/tools/r8/CompilationException.java'
1070 include '**/com/android/tools/r8/CompilationMode.java'
1071 include '**/com/android/tools/r8/D8.java'
1072 include '**/com/android/tools/r8/D8Command.java'
1073 include '**/com/android/tools/r8/D8Output.java'
1074 include '**/com/android/tools/r8/Resource.java'
1075}