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