blob: 06a0632908890f4acad9246e39b2879deac81d6b [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.
Ivan Gavrilovic4876d2a2017-11-30 18:57:48 +00004import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
Mikaël Peltierc9c1e8f2017-10-17 15:45:42 +02005import net.ltgt.gradle.errorprone.ErrorProneToolChain
Jean-Marie Henaff34d85f72017-06-14 10:32:04 +02006import org.gradle.internal.os.OperatingSystem
Ivan Gavrilovic635c7e52017-12-01 15:10:45 +00007import tasks.GetJarsFromConfiguration
Stephan Herhut417a72a2017-07-18 10:38:30 +02008import utils.Utils
Mads Ager418d1ca2017-05-22 09:35:49 +02009
Sebastien Hertz143ed112018-02-13 14:26:41 +010010ext {
11 androidSupportVersion = '25.4.0'
12 apacheCommonsVersion = '1.12'
Gautam Korlam39d74202018-08-29 18:09:35 -070013 asmVersion = '6.2.1'
Sebastien Hertz143ed112018-02-13 14:26:41 +010014 autoValueVersion = '1.5'
15 espressoVersion = '3.0.0'
16 fastutilVersion = '7.2.0'
17 guavaVersion = '23.0'
18 joptSimpleVersion = '4.6'
Mads Ager48dd79e2018-05-15 09:13:55 +020019 gsonVersion = '2.7'
Sebastien Hertz143ed112018-02-13 14:26:41 +010020 junitVersion = '4.12'
Sebastien Hertz6ebe39a2018-03-06 16:17:58 +010021 kotlinVersion = '1.2.30'
Jinseong Jeon40ceab02018-07-09 14:25:31 -070022 kotlinExtMetadataJVMVersion = '0.0.3'
Sebastien Hertz143ed112018-02-13 14:26:41 +010023 smaliVersion = '2.2b4'
24}
25
Mikaël Peltierc9c1e8f2017-10-17 15:45:42 +020026def errorProneConfiguration = [
27 '-XepDisableAllChecks',
28 // D8 want to use reference equality, thus disable the checker explicitly
29 '-Xep:ReferenceEquality:OFF',
Stephan Herhute4d101c2017-11-22 12:18:02 +010030 '-Xep:ClassCanBeStatic:ERROR',
31 '-Xep:OperatorPrecedence:ERROR',
32 '-Xep:RemoveUnusedImports:ERROR',
33 '-Xep:MissingOverride:ERROR',
Stephan Herhute4d101c2017-11-22 12:18:02 +010034 '-Xep:IntLongMath:ERROR',
35 '-Xep:EqualsHashCode:ERROR',
36 '-Xep:InconsistentOverloads:ERROR',
37 '-Xep:ArrayHashCode:ERROR',
38 '-Xep:EqualsIncompatibleType:ERROR',
39 '-Xep:NonOverridingEquals:ERROR',
40 '-Xep:FallThrough:ERROR',
41 '-Xep:MissingCasesInEnumSwitch:ERROR',
42 '-Xep:MissingDefault:ERROR',
43 '-Xep:MultipleTopLevelClasses:ERROR',
44 '-Xep:NarrowingCompoundAssignment:ERROR',
Mads Ager2ce4b372018-06-07 13:11:33 +020045 '-Xep:BoxedPrimitiveConstructor:ERROR',
46 '-Xep:LogicalAssignment:ERROR',
47 '-Xep:FloatCast:ERROR',
48 '-Xep:ReturnValueIgnored:ERROR']
Mads Ager418d1ca2017-05-22 09:35:49 +020049
50apply from: 'copyAdditionalJctfCommonFiles.gradle'
51
52repositories {
Yohann Roussel126f6872017-08-03 16:25:32 +020053 maven { url 'https://maven.google.com' }
Jinseong Jeon515e7582018-06-15 21:50:31 +000054 maven { url 'https://kotlin.bintray.com/kotlinx' }
Mads Ager418d1ca2017-05-22 09:35:49 +020055 mavenCentral()
56}
57
Stephan Herhut417a72a2017-07-18 10:38:30 +020058buildscript {
59 repositories {
60 mavenCentral()
mikaelpeltier80939312017-08-17 15:00:09 +020061 jcenter()
Mikaël Peltiercf3e2362017-10-16 13:45:45 +020062 maven {
63 url "https://plugins.gradle.org/m2/"
64 }
Stephan Herhut417a72a2017-07-18 10:38:30 +020065 }
66 dependencies {
Yohann Roussel7f47c032017-09-14 12:19:06 +020067 classpath 'com.cookpad.android.licensetools:license-tools-plugin:0.23.0'
Jinseong Jeon40ceab02018-07-09 14:25:31 -070068 classpath 'com.github.jengelman.gradle.plugins:shadow:2.0.4'
Mikaël Peltierc9c1e8f2017-10-17 15:45:42 +020069 classpath "net.ltgt.gradle:gradle-errorprone-plugin:0.0.13"
Stephan Herhut52cb1022017-10-24 15:10:41 +020070 classpath "net.ltgt.gradle:gradle-apt-plugin:0.12"
Jinseong Jeon05064e12018-07-03 00:21:12 -070071 classpath "com.gradle:build-scan-plugin:1.14"
Stephan Herhut417a72a2017-07-18 10:38:30 +020072 }
73}
74
Jinseong Jeon05064e12018-07-03 00:21:12 -070075apply plugin: "com.gradle.build-scan"
76
77buildScan {
78 licenseAgreementUrl = 'https://gradle.com/terms-of-service'
79 licenseAgree = 'yes'
80}
81
82apply plugin: 'java'
83apply plugin: 'idea'
Jinseong Jeon05064e12018-07-03 00:21:12 -070084apply plugin: 'com.cookpad.android.licensetools'
85apply plugin: 'net.ltgt.errorprone-base'
86apply plugin: "net.ltgt.apt"
87
88// Ensure importing into IntelliJ IDEA use the same output directories as Gradle. In tests we
89// use the output path for tests (ultimately through ToolHelper.getClassPathForTests()) and
90// therefore these paths need to be the same. See https://youtrack.jetbrains.com/issue/IDEA-175172
91// for context.
92idea {
93 module {
94 outputDir file('build/classes/main')
95 testOutputDir file('build/classes/test')
96 }
97}
98
99if (project.hasProperty('with_code_coverage')) {
100 apply plugin: 'jacoco'
101}
102
Mads Ager418d1ca2017-05-22 09:35:49 +0200103// Custom source set for example tests and generated tests.
104sourceSets {
105 test {
106 java {
107 srcDirs = [
108 'src/test/java',
109 'build/generated/test/java',
110 ]
111 }
112 }
Mads Ager22847672017-11-14 09:59:26 +0100113 bsPatch {
114 java {
115 srcDirs = [
116 'src/bspatch/java',
117 'src/main/java'
118 ]
119 }
120 }
Yohann Rousselbb571622017-11-09 10:47:36 +0100121 apiUsageSample {
122 java {
Mathias Rave3f3c522018-05-30 08:22:17 +0200123 srcDirs = ['src/test/apiUsageSample', 'src/main/java']
124 include 'com/android/tools/apiusagesample/*.java'
125 include 'com/android/tools/r8/BaseCompilerCommandParser.java'
126 include 'com/android/tools/r8/D8CommandParser.java'
127 include 'com/android/tools/r8/R8CommandParser.java'
128 include 'com/android/tools/r8/utils/FlagFile.java'
Yohann Rousselbb571622017-11-09 10:47:36 +0100129 }
Yohann Rousselbb571622017-11-09 10:47:36 +0100130 }
Mads Ager418d1ca2017-05-22 09:35:49 +0200131 debugTestResources {
132 java {
133 srcDirs = ['src/test/debugTestResources']
134 }
135 output.resourcesDir = 'build/classes/debugTestResources'
136 }
Sebastien Hertz964c5c22017-05-23 15:22:23 +0200137 debugTestResourcesJava8 {
138 java {
139 srcDirs = ['src/test/debugTestResourcesJava8']
140 }
141 output.resourcesDir = 'build/classes/debugTestResourcesJava8'
142 }
Sebastien Hertz1d7702b2017-08-18 09:07:27 +0200143 debugTestResourcesKotlin {
144 java {
145 srcDirs = ['src/test/debugTestResourcesKotlin']
146 }
147 output.resourcesDir = 'build/classes/debugTestResourcesKotlin'
148 }
Mads Ager418d1ca2017-05-22 09:35:49 +0200149 examples {
150 java {
Rico Wind40fd2c12018-09-12 12:14:44 +0200151 srcDirs = ['src/test/examples']
Mads Ager418d1ca2017-05-22 09:35:49 +0200152 }
153 output.resourcesDir = 'build/classes/examples'
154 }
Mikaël Peltier3c8b6ea2017-12-12 13:00:21 +0100155 examplesKotlin {
156 java {
157 srcDirs = ['src/test/examplesKotlin']
158 }
159 output.resourcesDir = 'build/classes/examplesKotlin'
160 }
Mads Ager418d1ca2017-05-22 09:35:49 +0200161 examplesAndroidN {
162 java {
163 srcDirs = ['src/test/examplesAndroidN']
164 }
165 output.resourcesDir = 'build/classes/examplesAndroidN'
166 }
167 examplesAndroidO {
168 java {
169 srcDirs = ['src/test/examplesAndroidO']
170 }
171 output.resourcesDir = 'build/classes/examplesAndroidO'
172 }
Mikaël Peltier7b7b53a2017-10-09 13:33:21 +0200173 examplesAndroidP {
174 java {
175 srcDirs = ['src/test/examplesAndroidP']
176 }
177 output.resourcesDir = 'build/classes/examplesAndroidP'
178 }
Mads Ager418d1ca2017-05-22 09:35:49 +0200179 jctfCommon {
180 java {
181 srcDirs = [
182 'third_party/jctf/Harness/src',
183 'third_party/jctf/LibTests/src/com/google/jctf/test/categories',
184 'third_party/jctf/LibTests/src/com/google/jctf/test/helper',
185 'third_party/jctf/LibTests/src/com/google/jctf/testHelpers',
186 'third_party/jctf/LibTests/src/org',
187 'build/additionalJctfCommonFiles'
188 ]
189 }
190 resources {
191 srcDirs = ['third_party/jctf/LibTests/resources']
192 }
193 }
194 jctfTests {
195 java {
196 srcDirs = [
197 'third_party/jctf/LibTests/src/com/google/jctf/test/lib',
198 // 'third_party/jctf/VMTests/src',
199 ]
200 }
201 }
Sebastien Hertzd3313772018-01-16 14:12:37 +0100202 kotlinR8TestResources {
203 java {
204 srcDirs = ['src/test/kotlinR8TestResources']
205 }
206 output.resourcesDir = 'build/classes/kotlinR8TestResources'
207 }
Mads Ager418d1ca2017-05-22 09:35:49 +0200208}
209
Yohann Roussel126f6872017-08-03 16:25:32 +0200210configurations {
211 supportLibs
212}
213
Mads Ager418d1ca2017-05-22 09:35:49 +0200214dependencies {
Sebastien Hertz143ed112018-02-13 14:26:41 +0100215 compile "net.sf.jopt-simple:jopt-simple:$joptSimpleVersion"
Mads Ager48dd79e2018-05-15 09:13:55 +0200216 compile "com.google.code.gson:gson:$gsonVersion"
Mads Ager0aa48052017-09-15 12:39:15 +0200217 // Include all of guava when compiling the code, but exclude annotations that we don't
218 // need from the packaging.
Sebastien Hertz143ed112018-02-13 14:26:41 +0100219 compileOnly("com.google.guava:guava:$guavaVersion")
220 compile("com.google.guava:guava:$guavaVersion", {
Mads Ager0aa48052017-09-15 12:39:15 +0200221 exclude group: 'com.google.errorprone'
222 exclude group: 'com.google.code.findbugs'
223 exclude group: 'com.google.j2objc'
224 exclude group: 'org.codehaus.mojo'
225 })
Sebastien Hertz143ed112018-02-13 14:26:41 +0100226 compile group: 'it.unimi.dsi', name: 'fastutil', version: fastutilVersion
Jinseong Jeon515e7582018-06-15 21:50:31 +0000227 compile "org.jetbrains.kotlinx:kotlinx-metadata-jvm:$kotlinExtMetadataJVMVersion"
Sebastien Hertz143ed112018-02-13 14:26:41 +0100228 compile group: 'org.ow2.asm', name: 'asm', version: asmVersion
229 compile group: 'org.ow2.asm', name: 'asm-commons', version: asmVersion
230 compile group: 'org.ow2.asm', name: 'asm-tree', version: asmVersion
231 compile group: 'org.ow2.asm', name: 'asm-analysis', version: asmVersion
232 compile group: 'org.ow2.asm', name: 'asm-util', version: asmVersion
Mads Ager418d1ca2017-05-22 09:35:49 +0200233 testCompile sourceSets.examples.output
Sebastien Hertz143ed112018-02-13 14:26:41 +0100234 testCompile "junit:junit:$junitVersion"
235 testCompile group: 'org.smali', name: 'smali', version: smaliVersion
Mads Ager418d1ca2017-05-22 09:35:49 +0200236 testCompile files('third_party/jasmin/jasmin-2.4.jar')
237 testCompile files('third_party/jdwp-tests/apache-harmony-jdwp-tests-host.jar')
Jean-Marie Henaffce162f32017-10-04 10:39:27 +0200238 testCompile files('third_party/ddmlib/ddmlib.jar')
Sebastien Hertz143ed112018-02-13 14:26:41 +0100239 bsPatchCompile "org.apache.commons:commons-compress:$apacheCommonsVersion"
240 jctfCommonCompile "junit:junit:$junitVersion"
241 jctfTestsCompile "junit:junit:$junitVersion"
Mads Ager418d1ca2017-05-22 09:35:49 +0200242 jctfTestsCompile sourceSets.jctfCommon.output
Sebastien Hertz143ed112018-02-13 14:26:41 +0100243 examplesAndroidOCompile group: 'org.ow2.asm', name: 'asm', version: asmVersion
244 examplesAndroidPCompile group: 'org.ow2.asm', name: 'asm', version: asmVersion
Stephan Herhut52cb1022017-10-24 15:10:41 +0200245 // Import Guava for @Nullable annotation
Sebastien Hertz143ed112018-02-13 14:26:41 +0100246 examplesCompile "com.google.guava:guava:$guavaVersion"
Sebastien Hertz143ed112018-02-13 14:26:41 +0100247 examplesCompileOnly "com.google.auto.value:auto-value:$autoValueVersion"
Sebastien Hertz143ed112018-02-13 14:26:41 +0100248 supportLibs "com.android.support:support-v4:$androidSupportVersion"
249 supportLibs "junit:junit:$junitVersion"
250 supportLibs "com.android.support.test.espresso:espresso-core:$espressoVersion"
Yohann Rousselbb571622017-11-09 10:47:36 +0100251 apiUsageSampleCompile sourceSets.main.output
Sebastien Hertz143ed112018-02-13 14:26:41 +0100252 debugTestResourcesKotlinCompileOnly "org.jetbrains.kotlin:kotlin-stdlib:$kotlinVersion"
253 examplesKotlinCompileOnly "org.jetbrains.kotlin:kotlin-stdlib:$kotlinVersion"
254 kotlinR8TestResourcesCompileOnly "org.jetbrains.kotlin:kotlin-stdlib:$kotlinVersion"
255 apt "com.google.auto.value:auto-value:$autoValueVersion"
Stephan Herhut417a72a2017-07-18 10:38:30 +0200256}
257
Mads Ager22847672017-11-14 09:59:26 +0100258configurations.bsPatchCompile.extendsFrom configurations.compile
259
Yohann Roussel7f47c032017-09-14 12:19:06 +0200260licenseTools {
261 licensesYaml = file('LIBRARY-LICENSE')
262}
263
Jean-Marie Henaff39587a82017-06-08 15:20:13 +0200264def osString = OperatingSystem.current().isLinux() ? "linux" :
265 OperatingSystem.current().isMacOsX() ? "mac" : "windows"
Mads Ager418d1ca2017-05-22 09:35:49 +0200266
267def cloudDependencies = [
268 "tests" : [
mikaelpeltierc2aa6652017-10-06 12:53:37 +0200269 "2017-10-04/art",
Sebastien Hertzf83b5902017-10-02 11:55:41 +0200270 "2016-12-19/art"
Mads Ager418d1ca2017-05-22 09:35:49 +0200271 ],
272 "third_party": [
Sebastien Hertzf83b5902017-10-02 11:55:41 +0200273 "android_jar/lib-v14",
Stephan Herhutb3aca8b2017-12-22 14:14:53 +0100274 "android_jar/lib-v15",
Sebastien Hertzf83b5902017-10-02 11:55:41 +0200275 "android_jar/lib-v19",
276 "android_jar/lib-v21",
Stephan Herhutd48be0d2018-01-04 15:33:10 +0100277 "android_jar/lib-v22",
278 "android_jar/lib-v23",
Sebastien Hertzf83b5902017-10-02 11:55:41 +0200279 "android_jar/lib-v24",
280 "android_jar/lib-v25",
281 "android_jar/lib-v26",
282 "proguard/proguard5.2.1",
Søren Gjessef631f482018-03-07 11:15:19 +0100283 "proguard/proguard6.0.1",
Sebastien Hertzf83b5902017-10-02 11:55:41 +0200284 "gradle/gradle",
285 "jdwp-tests",
286 "jasmin",
287 "jctf",
288 "kotlin",
289 "android_cts_baseline",
Jean-Marie Henaffce162f32017-10-04 10:39:27 +0200290 "ddmlib",
Søren Gjessec9b3fc72018-02-09 15:44:54 +0100291 "core-lambda-stubs",
Mathias Rav5285faf2018-03-20 14:16:32 +0100292 "openjdk/openjdk-rt-1.8",
Mathias Rav891831f2018-04-26 14:51:18 +0200293 "r8",
Mads Ager418d1ca2017-05-22 09:35:49 +0200294 ],
295 // All dex-vms have a fixed OS of Linux, as they are only supported on Linux, and will be run in a Docker
296 // container on other platforms where supported.
297 "tools" : [
Sebastien Hertzf83b5902017-10-02 11:55:41 +0200298 "linux/art",
299 "linux/art-5.1.1",
300 "linux/art-6.0.1",
301 "linux/art-7.0.0",
302 "linux/dalvik",
Stephan Herhut02f0f9d2018-01-04 10:27:31 +0100303 "linux/dalvik-4.0.4",
Sebastien Hertzf83b5902017-10-02 11:55:41 +0200304 "${osString}/dx",
Mads Ager418d1ca2017-05-22 09:35:49 +0200305 ]
306]
307
308cloudDependencies.each { entry ->
309 entry.value.each { entryFile ->
310 task "download_deps_${entry.key}/${entryFile}"(type: Exec) {
Sebastien Hertzf83b5902017-10-02 11:55:41 +0200311 def outputDir = "${entry.key}/${entryFile}"
312 def gzFile = "${outputDir}.tar.gz"
Mads Ager418d1ca2017-05-22 09:35:49 +0200313 def sha1File = "${gzFile}.sha1"
314 inputs.file sha1File
315 outputs.file gzFile
Sebastien Hertzf83b5902017-10-02 11:55:41 +0200316 outputs.dir outputDir
Jean-Marie Henaff872e4422017-06-13 10:26:20 +0200317 List<String> dlFromStorageArgs = ["-n", "-b", "r8-deps", "-u", "-s", "${sha1File}"]
318 if (OperatingSystem.current().isWindows()) {
319 executable "download_from_google_storage.bat"
320 args dlFromStorageArgs
321 } else {
322 executable "bash"
323 args "-c", "download_from_google_storage " + String.join(" ", dlFromStorageArgs)
324 }
Mads Ager418d1ca2017-05-22 09:35:49 +0200325 }
326 }
327}
328
329def x20Dependencies = [
330 "third_party": [
Sebastien Hertzf83b5902017-10-02 11:55:41 +0200331 "gmail/gmail_android_170604.16",
Rico Wind86bfc832018-09-18 07:48:21 +0200332 "chrome",
Sebastien Hertzf83b5902017-10-02 11:55:41 +0200333 "gmscore/v4",
334 "gmscore/v5",
335 "gmscore/v6",
336 "gmscore/v7",
337 "gmscore/v8",
338 "gmscore/gmscore_v9",
339 "gmscore/gmscore_v10",
340 "gmscore/latest",
341 "photos/2017-06-06",
342 "youtube/youtube.android_12.10",
343 "youtube/youtube.android_12.17",
344 "youtube/youtube.android_12.22",
Søren Gjessefe2de552018-09-24 16:31:10 +0200345 "youtube/youtube.android_13.37",
Sebastien Hertzf83b5902017-10-02 11:55:41 +0200346 "proguardsettings",
347 "proguard/proguard_internal_159423826",
348 "framework",
Rico Wind4304aec2018-08-24 09:33:10 +0200349 "desugar/desugar_20180308",
350 "benchmarks/kotlin-benches"
Mads Ager418d1ca2017-05-22 09:35:49 +0200351 ],
352]
353
354x20Dependencies.each { entry ->
355 entry.value.each { entryFile ->
356 task "download_deps_${entry.key}/${entryFile}"(type: Exec) {
Sebastien Hertzf83b5902017-10-02 11:55:41 +0200357 def outputDir = "${entry.key}/${entryFile}"
358 def gzFile = "${outputDir}.tar.gz"
Mads Ager418d1ca2017-05-22 09:35:49 +0200359 def sha1File = "${gzFile}.sha1"
360 inputs.file sha1File
361 outputs.file gzFile
Sebastien Hertzf83b5902017-10-02 11:55:41 +0200362 outputs.dir outputDir
Mads Ager418d1ca2017-05-22 09:35:49 +0200363 executable "bash"
364 args "-c", "tools/download_from_x20.py ${sha1File}"
365 }
366 }
367}
368
Rico Wind897bb712017-05-23 10:44:29 +0200369task downloadProguard {
370 cloudDependencies.each { entry ->
371 entry.value.each { entryFile ->
372 if (entryFile.contains("proguard")) {
373 dependsOn "download_deps_${entry.key}/${entryFile}"
374 }
375 }
376 }
377}
378
Tamas Kenez427205b2017-06-29 15:57:09 +0200379task downloadDx {
380 cloudDependencies.each { entry ->
381 entry.value.each { entryFile ->
Tamas Kenezcea7c202017-10-13 10:53:32 +0200382 if (entryFile.endsWith("/dx")) {
Tamas Kenez427205b2017-06-29 15:57:09 +0200383 dependsOn "download_deps_${entry.key}/${entryFile}"
384 }
385 }
386 }
387}
388
Tamas Kenez0e10c562017-06-08 10:00:34 +0200389task downloadAndroidCts {
390 cloudDependencies.each { entry ->
391 entry.value.each { entryFile ->
392 if (entryFile.contains("android_cts_baseline")) {
393 dependsOn "download_deps_${entry.key}/${entryFile}"
394 }
395 }
396 }
397}
398
Mads Ager418d1ca2017-05-22 09:35:49 +0200399task downloadDeps {
400 cloudDependencies.each { entry ->
401 entry.value.each { entryFile ->
402 dependsOn "download_deps_${entry.key}/${entryFile}"
403 }
404 }
405 if (!project.hasProperty('no_internal')) {
406 x20Dependencies.each { entry ->
407 entry.value.each { entryFile ->
408 dependsOn "download_deps_${entry.key}/${entryFile}"
409 }
410 }
411 }
412}
413
414allprojects {
415 sourceCompatibility = JavaVersion.VERSION_1_8
416 targetCompatibility = JavaVersion.VERSION_1_8
417}
418
Mads Agerc7d14d32018-09-27 11:09:46 +0200419// Javac often runs out of stack space when compiling the tests.
420// Increase the stack size for the javac process.
421tasks.withType(JavaCompile) {
422 options.fork = true
423 options.forkOptions.jvmArgs = ["-Xss4m"]
424}
425
Mads Ager418d1ca2017-05-22 09:35:49 +0200426tasks.withType(JavaCompile) {
427 options.compilerArgs << '-Xlint:unchecked'
428}
429
Mikaël Peltierc9c1e8f2017-10-17 15:45:42 +0200430if (!project.hasProperty('without_error_prone')) {
431 compileJava {
432 // Enable error prone for D8/R8 sources.
433 toolChain ErrorProneToolChain.create(project)
434 options.compilerArgs += errorProneConfiguration
435 }
436}
437
Mads Ager418d1ca2017-05-22 09:35:49 +0200438compileJctfCommonJava {
439 dependsOn 'copyAdditionalJctfCommonFiles'
440 options.compilerArgs = ['-Xlint:none']
441}
442
443compileJctfTestsJava {
444 dependsOn 'jctfCommonClasses'
445 options.compilerArgs = ['-Xlint:none']
446}
447
Yohann Roussel7f47c032017-09-14 12:19:06 +0200448task consolidatedLicense {
449 // checkLicenses verifies that the list of libraries referenced in 'LIBRARY-LICENSE' is
450 // corresponding to the effective list of embedded libraries.
451 dependsOn 'checkLicenses'
452 def license = new File(new File(buildDir, 'generatedLicense'), 'LICENSE')
453 inputs.files files('LICENSE', 'LIBRARY-LICENSE') + fileTree(dir: 'library-licensing')
454 outputs.files license
455 doLast {
456 license.getParentFile().mkdirs()
457 license.createNewFile()
458 license.text = "This file lists all licenses for code distributed.\n"
459 license.text += "All non-library code has the following 3-Clause BSD license.\n"
460 license.text += "\n"
461 license.text += "\n"
462 license.text += file('LICENSE').text
463 license.text += "\n"
464 license.text += "\n"
465 license.text += "Summary of distributed libraries:\n"
466 license.text += "\n"
467 license.text += file('LIBRARY-LICENSE').text
468 license.text += "\n"
469 license.text += "\n"
470 license.text += "Licenses details:\n"
471 fileTree(dir: 'library-licensing').getFiles().stream().sorted().forEach { file ->
472 license.text += "\n"
473 license.text += "\n"
474 license.text += file.text
475 }
476 }
477}
478
Ivan Gavrilovic4876d2a2017-11-30 18:57:48 +0000479static configureRelocations(ShadowJar task) {
Jinseong Jeon40ceab02018-07-09 14:25:31 -0700480 // Everything under META-INF is not included by default.
481 // Should include before 'relocate' so that the service file path and its content
482 // are properly relocated as well.
483 task.mergeServiceFiles {
484 include 'META-INF/services/*'
485 }
Ivan Gavrilovic4876d2a2017-11-30 18:57:48 +0000486 task.relocate('com.google.common', 'com.android.tools.r8.com.google.common')
Mads Ager48dd79e2018-05-15 09:13:55 +0200487 task.relocate('com.google.gson', 'com.android.tools.r8.com.google.gson')
Ivan Gavrilovic4876d2a2017-11-30 18:57:48 +0000488 task.relocate('com.google.thirdparty', 'com.android.tools.r8.com.google.thirdparty')
489 task.relocate('joptsimple', 'com.android.tools.r8.joptsimple')
490 task.relocate('org.apache.commons', 'com.android.tools.r8.org.apache.commons')
491 task.relocate('org.objectweb.asm', 'com.android.tools.r8.org.objectweb.asm')
Ivan Gavrilovic4876d2a2017-11-30 18:57:48 +0000492 task.relocate('it.unimi.dsi.fastutil', 'com.android.tools.r8.it.unimi.dsi.fastutil')
Søren Gjesse7c560852018-06-20 16:27:21 +0200493 task.relocate('kotlin', 'com.android.tools.r8.jetbrains.kotlin')
494 task.relocate('kotlinx', 'com.android.tools.r8.jetbrains.kotlinx')
495 task.relocate('org.jetbrains', 'com.android.tools.r8.org.jetbrains')
Søren Gjesse06ed1322018-06-21 11:15:07 +0200496 task.relocate('org.intellij', 'com.android.tools.r8.org.intellij')
Ivan Gavrilovic4876d2a2017-11-30 18:57:48 +0000497}
498
499task repackageDeps(type: ShadowJar) {
500 configurations = [project.configurations.compile]
501 configureRelocations(it)
Ivan Gavrilovic2afc0cc2018-07-09 14:31:55 +0100502 exclude { it.getRelativePath().getPathString() == "module-info.class" }
Jinseong Jeon40ceab02018-07-09 14:25:31 -0700503 exclude { it.getRelativePath().getPathString().startsWith("META-INF/maven/") }
Ivan Gavrilovic4876d2a2017-11-30 18:57:48 +0000504 baseName 'deps'
505}
506
507task repackageSources(type: ShadowJar) {
Mads Ager418d1ca2017-05-22 09:35:49 +0200508 from sourceSets.main.output
Ivan Gavrilovic4876d2a2017-11-30 18:57:48 +0000509 configureRelocations(it)
510 baseName 'sources'
511}
512
Ivan Gavrilovic4876d2a2017-11-30 18:57:48 +0000513task R8(type: ShadowJar) {
Yohann Roussel7f47c032017-09-14 12:19:06 +0200514 from consolidatedLicense.outputs.files
Mads Ager418d1ca2017-05-22 09:35:49 +0200515 baseName 'r8'
Mikaël Peltiere5e54722017-08-18 12:01:59 +0200516 classifier = null
517 version = null
Mads Ager418d1ca2017-05-22 09:35:49 +0200518 manifest {
Mathias Ravdd6a6de2018-05-18 10:18:33 +0200519 attributes 'Main-Class': 'com.android.tools.r8.SwissArmyKnife'
Mads Ager418d1ca2017-05-22 09:35:49 +0200520 }
521 // In order to build without dependencies, pass the exclude_deps property using:
522 // gradle -Pexclude_deps R8
523 if (!project.hasProperty('exclude_deps')) {
Gautam Korlamad356f22017-12-04 21:45:30 -0800524 from repackageSources.outputs.files
Ivan Gavrilovic4876d2a2017-11-30 18:57:48 +0000525 from repackageDeps.outputs.files
Gautam Korlamad356f22017-12-04 21:45:30 -0800526 } else {
527 from sourceSets.main.output
Mads Ager418d1ca2017-05-22 09:35:49 +0200528 }
529}
530
Ivan Gavrilovic4876d2a2017-11-30 18:57:48 +0000531task D8(type: ShadowJar) {
Mathias Ravdd6a6de2018-05-18 10:18:33 +0200532 from R8.outputs.files
Mads Ager418d1ca2017-05-22 09:35:49 +0200533 baseName 'd8'
534 manifest {
mikaelpeltier80939312017-08-17 15:00:09 +0200535 attributes 'Main-Class': 'com.android.tools.r8.D8'
Mads Ager418d1ca2017-05-22 09:35:49 +0200536 }
Mads Ager418d1ca2017-05-22 09:35:49 +0200537}
538
Mathias Ravdd6a6de2018-05-18 10:18:33 +0200539task CompatDx(type: ShadowJar) {
540 from R8.outputs.files
Mads Ager418d1ca2017-05-22 09:35:49 +0200541 baseName 'compatdx'
542 manifest {
543 attributes 'Main-Class': 'com.android.tools.r8.compatdx.CompatDx'
544 }
Mads Ager418d1ca2017-05-22 09:35:49 +0200545}
546
Mathias Ravdd6a6de2018-05-18 10:18:33 +0200547task CompatProguard(type: ShadowJar) {
548 from R8.outputs.files
Søren Gjesse1d21da72017-09-01 12:05:38 +0200549 baseName 'compatproguard'
550 manifest {
551 attributes 'Main-Class': 'com.android.tools.r8.compatproguard.CompatProguard'
552 }
Lars Bak44cef522017-08-10 16:02:39 +0200553}
554
Mads Ager22847672017-11-14 09:59:26 +0100555task bspatch(type: Jar) {
556 from sourceSets.bsPatch.output
557 baseName 'bspatch'
558 manifest {
559 attributes 'Main-Class': 'com.android.tools.r8.dex.BSPatch'
560 }
561 // In order to build without dependencies, pass the exclude_deps property using:
Mathias Ravdd6a6de2018-05-18 10:18:33 +0200562 // gradle -Pexclude_deps bspatch
Mads Ager22847672017-11-14 09:59:26 +0100563 if (!project.hasProperty('exclude_deps')) {
564 // Also include dependencies
565 from {
566 configurations.bsPatchCompile.collect { it.isDirectory() ? it : zipTree(it) }
567 }
568 }
569}
570
Mads Ager418d1ca2017-05-22 09:35:49 +0200571task sourceJar(type: Jar, dependsOn: classes) {
572 classifier = 'src'
573 from sourceSets.main.allSource
574}
575
576task jctfCommonJar(type: Jar) {
577 from sourceSets.jctfCommon.output
578 baseName 'jctfCommon'
579}
580
581artifacts {
582 archives sourceJar
583}
584
585task createArtTests(type: Exec) {
586 def outputDir = "build/generated/test/java/com/android/tools/r8/art"
Mads Ager7e5bd722017-05-24 07:17:27 +0200587 def createArtTestsScript = "tools/create_art_tests.py"
mikaelpeltierc2aa6652017-10-06 12:53:37 +0200588 inputs.file "tests/2017-10-04/art.tar.gz"
Mads Ager418d1ca2017-05-22 09:35:49 +0200589 inputs.file createArtTestsScript
590 outputs.dir outputDir
591 dependsOn downloadDeps
Mads Ager677e3002017-05-24 07:54:51 +0200592 commandLine "python", createArtTestsScript
Mads Ager418d1ca2017-05-22 09:35:49 +0200593 workingDir = projectDir
594}
595
596task createJctfTests(type: Exec) {
Stephan Herhutea6ee582017-05-23 13:14:34 +0200597 def outputDir = "build/generated/test/java/com/android/tools/r8/jctf"
Tamas Kenez25a99e92017-05-29 10:15:30 +0200598 def script = "tools/create_jctf_tests.py"
Mads Ager418d1ca2017-05-22 09:35:49 +0200599 inputs.file script
600 outputs.dir outputDir
601 dependsOn downloadDeps
Tamas Kenez25a99e92017-05-29 10:15:30 +0200602 commandLine "python", script
Mads Ager418d1ca2017-05-22 09:35:49 +0200603 workingDir = projectDir
604}
605
606compileTestJava {
607 dependsOn createArtTests
608 dependsOn createJctfTests
609}
610
Ian Zernyee23a172018-01-03 09:08:48 +0100611task buildD8ApiUsageSample(type: Jar) {
612 from sourceSets.apiUsageSample.output
613 baseName 'd8_api_usage_sample'
614 destinationDir file('tests')
615}
616
Ian Zerny923a0c12018-01-03 10:59:18 +0100617task buildR8ApiUsageSample(type: Jar) {
618 from sourceSets.apiUsageSample.output
619 baseName 'r8_api_usage_sample'
620 destinationDir file('tests')
621}
622
Yohann Roussel548ae942018-01-05 11:13:28 +0100623task buildApiSampleJars {
Yohann Roussel548ae942018-01-05 11:13:28 +0100624 dependsOn buildD8ApiUsageSample
625 dependsOn buildR8ApiUsageSample
626}
627
Mads Ager418d1ca2017-05-22 09:35:49 +0200628task buildDebugInfoExamplesDex {
629 def examplesDir = file("src/test/java")
630 def hostJar = "debuginfo_examples.jar"
631 def hostDexJar = "debuginfo_examples_dex.jar"
632 task "compile_debuginfo_examples"(type: JavaCompile) {
633 source = fileTree(dir: examplesDir, include: "com/android/tools/r8/debuginfo/*Test.java")
634 destinationDir = file("build/test/debuginfo_examples/classes")
635 classpath = sourceSets.main.compileClasspath
636 sourceCompatibility = JavaVersion.VERSION_1_7
637 targetCompatibility = JavaVersion.VERSION_1_7
638 options.compilerArgs += ["-Xlint:-options"]
639 }
640 task "jar_debuginfo_examples"(type: Jar, dependsOn: "compile_debuginfo_examples") {
641 archiveName = hostJar
642 destinationDir = file("build/test/")
643 from "build/test/debuginfo_examples/classes"
644 include "**/*.class"
645 }
646 task "dex_debuginfo_examples"(type: Exec,
647 dependsOn: ["jar_debuginfo_examples", "downloadDeps"]) {
Jean-Marie Henaff39587a82017-06-08 15:20:13 +0200648 if (OperatingSystem.current().isWindows()) {
649 executable file("tools/windows/dx/bin/dx.bat")
Jinseong Jeon35a1eff2017-09-24 23:28:08 -0700650 } else if (OperatingSystem.current().isMacOsX()) {
651 executable file("tools/mac/dx/bin/dx");
Jean-Marie Henaff39587a82017-06-08 15:20:13 +0200652 } else {
653 executable file("tools/linux/dx/bin/dx");
654 }
Mads Ager418d1ca2017-05-22 09:35:49 +0200655 args "--dex"
656 args "--output=build/test/${hostDexJar}"
657 args "build/test/${hostJar}"
658 inputs.file file("build/test/${hostJar}")
659 outputs.file file("build/test/${hostDexJar}")
660 }
661 dependsOn dex_debuginfo_examples
662}
663
664task buildDebugTestResourcesJars {
Mads Ager418d1ca2017-05-22 09:35:49 +0200665 def resourcesDir = file("src/test/debugTestResources")
666 def hostJar = "debug_test_resources.jar"
667 task "compile_debugTestResources"(type: JavaCompile) {
668 source = fileTree(dir: resourcesDir, include: '**/*.java')
669 destinationDir = file("build/test/debugTestResources/classes")
670 classpath = sourceSets.main.compileClasspath
671 sourceCompatibility = JavaVersion.VERSION_1_7
672 targetCompatibility = JavaVersion.VERSION_1_7
673 options.compilerArgs += ["-g", "-Xlint:-options"]
674 }
675 task "jar_debugTestResources"(type: Jar, dependsOn: "compile_debugTestResources") {
676 archiveName = hostJar
677 destinationDir = file("build/test/")
678 from "build/test/debugTestResources/classes"
679 include "**/*.class"
680 }
Sebastien Hertz964c5c22017-05-23 15:22:23 +0200681 def java8ResourcesDir = file("src/test/debugTestResourcesJava8")
682 def java8HostJar = "debug_test_resources_java8.jar"
683 task "compile_debugTestResourcesJava8"(type: JavaCompile) {
684 source = fileTree(dir: java8ResourcesDir, include: '**/*.java')
685 destinationDir = file("build/test/debugTestResourcesJava8/classes")
686 classpath = sourceSets.main.compileClasspath
687 sourceCompatibility = JavaVersion.VERSION_1_8
688 targetCompatibility = JavaVersion.VERSION_1_8
689 options.compilerArgs += ["-g", "-Xlint:-options"]
690 }
691 task "jar_debugTestResourcesJava8"(type: Jar, dependsOn: "compile_debugTestResourcesJava8") {
692 archiveName = java8HostJar
693 destinationDir = file("build/test/")
694 from "build/test/debugTestResourcesJava8/classes"
695 include "**/*.class"
696 }
Sebastien Hertz1d7702b2017-08-18 09:07:27 +0200697 def kotlinResourcesDir = file("src/test/debugTestResourcesKotlin")
Sebastien Hertz2ac9bac2018-01-15 16:33:44 +0000698 def kotlinHostJar = "debug_test_resources_kotlin.jar"
699 task "jar_debugTestResourcesKotlin"(type: kotlin.Kotlinc) {
700 source = fileTree(dir: kotlinResourcesDir, include: '**/*.kt')
701 destination = file("build/test/${kotlinHostJar}")
Sebastien Hertz1d7702b2017-08-18 09:07:27 +0200702 }
Sebastien Hertz964c5c22017-05-23 15:22:23 +0200703 dependsOn downloadDeps
Mads Ager418d1ca2017-05-22 09:35:49 +0200704 dependsOn jar_debugTestResources
Sebastien Hertz964c5c22017-05-23 15:22:23 +0200705 dependsOn jar_debugTestResourcesJava8
Sebastien Hertz2ac9bac2018-01-15 16:33:44 +0000706 dependsOn jar_debugTestResourcesKotlin
Mads Ager418d1ca2017-05-22 09:35:49 +0200707}
708
Søren Gjesse5b4ee0a2018-01-30 13:46:39 +0100709// Examples used by tests, where Android specific APIs are used.
710task buildExampleAndroidApi(type: JavaCompile) {
711 source = fileTree(dir: file("src/test/examplesAndroidApi"), include: "**/*.java")
712 destinationDir = file("build/test/examplesAndroidApi/classes")
713 classpath = files("third_party/android_jar/lib-v26/android.jar")
714 sourceCompatibility = JavaVersion.VERSION_1_8
715 targetCompatibility = JavaVersion.VERSION_1_8
716}
717
Mikaël Peltier3c8b6ea2017-12-12 13:00:21 +0100718task buildExampleKotlinJars {
719 def kotlinSrcDir = file("src/test/examplesKotlin")
720 kotlinSrcDir.eachDir { dir ->
Sebastien Hertz2ac9bac2018-01-15 16:33:44 +0000721 def name = dir.getName();
722 dependsOn "compile_example_kotlin_${name}"
723 task "compile_example_kotlin_${name}"(type: kotlin.Kotlinc) {
724 source = fileTree(dir: file("src/test/examplesKotlin/${name}"), include: '**/*.kt')
725 destination = file("build/test/examplesKotlin/${name}.jar")
Mikaël Peltier3c8b6ea2017-12-12 13:00:21 +0100726 }
727 }
728}
729
Lars Bakc91e87e2017-08-18 08:53:10 +0200730// Proto lite generated code yields warnings when compiling with javac.
731// We change the options passed to javac to ignore it.
732compileExamplesJava.options.compilerArgs = ["-Xlint:none"]
733
Søren Gjesse7320ce52018-05-07 15:45:22 +0200734
Mads Ager418d1ca2017-05-22 09:35:49 +0200735task buildExampleJars {
Rico Wind897bb712017-05-23 10:44:29 +0200736 dependsOn downloadProguard
Mads Ager418d1ca2017-05-22 09:35:49 +0200737 def examplesDir = file("src/test/examples")
Jean-Marie Henaff872e4422017-06-13 10:26:20 +0200738 def proguardScript
739 if (OperatingSystem.current().isWindows()) {
740 proguardScript = "third_party/proguard/proguard5.2.1/bin/proguard.bat"
741 } else {
742 proguardScript = "third_party/proguard/proguard5.2.1/bin/proguard.sh"
743 }
Stephan Herhut417a72a2017-07-18 10:38:30 +0200744 task extractExamplesRuntime(type: Sync) {
745 dependsOn configurations.examplesRuntime
Ivan Gavrilovic635c7e52017-12-01 15:10:45 +0000746 from { configurations.examplesRuntime.collect { zipTree(it) } }
Stephan Herhut417a72a2017-07-18 10:38:30 +0200747 include "**/*.class"
748 includeEmptyDirs false
749 into "$buildDir/runtime/examples/"
750 }
751
Søren Gjesse7320ce52018-05-07 15:45:22 +0200752 task "copy_examples_resources"(type: org.gradle.api.tasks.Copy) {
753 from examplesDir
754 exclude "**/*.java"
755 exclude "**/keep-rules*.txt"
756 into file("build/test/examples/classes")
757 }
758
759 task "compile_examples"(type: JavaCompile) {
Søren Gjesse7320ce52018-05-07 15:45:22 +0200760 dependsOn "copy_examples_resources"
Rico Wind40fd2c12018-09-12 12:14:44 +0200761 source examplesDir
Stephan Herhut417a72a2017-07-18 10:38:30 +0200762 include "**/*.java"
Mads Ager418d1ca2017-05-22 09:35:49 +0200763 destinationDir = file("build/test/examples/classes")
Stephan Herhut417a72a2017-07-18 10:38:30 +0200764 classpath = sourceSets.examples.compileClasspath
Mads Ager418d1ca2017-05-22 09:35:49 +0200765 sourceCompatibility = JavaVersion.VERSION_1_7
766 targetCompatibility = JavaVersion.VERSION_1_7
Tamas Kenezc5163ed2017-09-19 09:27:37 +0200767 options.compilerArgs = ["-g:source,lines", "-Xlint:none"]
768 }
Rico Wind40fd2c12018-09-12 12:14:44 +0200769 task "compile_examples_debuginfo_all"(type: JavaCompile) {
770 source examplesDir
Tamas Kenezc5163ed2017-09-19 09:27:37 +0200771 include "**/*.java"
772 destinationDir = file("build/test/examples/classes_debuginfo_all")
773 classpath = sourceSets.examples.compileClasspath
774 sourceCompatibility = JavaVersion.VERSION_1_7
775 targetCompatibility = JavaVersion.VERSION_1_7
776 options.compilerArgs = ["-g", "-Xlint:none"]
777 }
Rico Wind40fd2c12018-09-12 12:14:44 +0200778 task "compile_examples_debuginfo_none"(type: JavaCompile) {
779 source examplesDir
Tamas Kenezc5163ed2017-09-19 09:27:37 +0200780 include "**/*.java"
781 destinationDir = file("build/test/examples/classes_debuginfo_none")
782 classpath = sourceSets.examples.compileClasspath
783 sourceCompatibility = JavaVersion.VERSION_1_7
784 targetCompatibility = JavaVersion.VERSION_1_7
785 options.compilerArgs = ["-g:none", "-Xlint:none"]
Mads Ager418d1ca2017-05-22 09:35:49 +0200786 }
787 examplesDir.eachDir { dir ->
788 def name = dir.getName();
789 def exampleOutputDir = file("build/test/examples");
790 def jarName = "${name}.jar"
791 dependsOn "jar_example_${name}"
Tamas Kenezc5163ed2017-09-19 09:27:37 +0200792 dependsOn "jar_example_${name}_debuginfo_all"
793 dependsOn "jar_example_${name}_debuginfo_none"
Stephan Herhut417a72a2017-07-18 10:38:30 +0200794 dependsOn "extractExamplesRuntime"
795 def runtimeDependencies = copySpec { }
Mads Ager418d1ca2017-05-22 09:35:49 +0200796 // The "throwing" test verifies debugging/stack info on the post-proguarded output.
797 def proguardConfigPath = "${dir}/proguard.cfg"
798 if (new File(proguardConfigPath).exists()) {
799 task "pre_proguard_example_${name}"(type: Jar, dependsOn: "compile_examples") {
800 archiveName = "${name}_pre_proguard.jar"
801 destinationDir = exampleOutputDir
802 from "build/test/examples/classes"
Stephan Herhut417a72a2017-07-18 10:38:30 +0200803 include name + "/**/*.class"
804 with runtimeDependencies
805 includeEmptyDirs false
Mads Ager418d1ca2017-05-22 09:35:49 +0200806 }
807 def jarPath = files(tasks.getByPath("pre_proguard_example_${name}")).files.first();
808 def proguardJarPath = "${exampleOutputDir}/${jarName}"
809 def proguardMapPath = "${exampleOutputDir}/${name}/${name}.map"
810 task "jar_example_${name}"(type: Exec, dependsOn: "pre_proguard_example_${name}") {
811 inputs.files tasks.getByPath("pre_proguard_example_${name}")
812 inputs.file proguardConfigPath
813 // Enable these to get stdout and stderr redirected to files...
814 // standardOutput = new FileOutputStream('proguard.stdout')
815 // errorOutput = new FileOutputStream('proguard.stderr')
Jean-Marie Henaff872e4422017-06-13 10:26:20 +0200816 def proguardArguments = "-verbose -dontwarn java.** -injars ${jarPath}" +
Mads Ager418d1ca2017-05-22 09:35:49 +0200817 " -outjars ${proguardJarPath}" +
818 " -include ${proguardConfigPath}" +
Jean-Marie Henaff872e4422017-06-13 10:26:20 +0200819 " -printmapping ${proguardMapPath}"
820 if (OperatingSystem.current().isWindows()) {
821 executable "${proguardScript}"
822 args "${proguardArguments}"
823 } else {
824 executable "bash"
825 args "-c", "${proguardScript} '${proguardArguments}'"
826 }
Mads Ager418d1ca2017-05-22 09:35:49 +0200827 outputs.file proguardJarPath
828 }
Tamas Kenezc5163ed2017-09-19 09:27:37 +0200829 // TODO: Consider performing distinct proguard compilations.
830 task "jar_example_${name}_debuginfo_all"(type: Copy, dependsOn: "jar_example_${name}") {
831 from "${exampleOutputDir}/${name}.jar"
Tamas Kenez925cb642017-09-19 10:41:15 +0200832 into "${exampleOutputDir}"
833 rename(".*", "${name}_debuginfo_all.jar")
Tamas Kenezc5163ed2017-09-19 09:27:37 +0200834 }
835 task "jar_example_${name}_debuginfo_none"(type: Copy, dependsOn: "jar_example_${name}") {
836 from "${exampleOutputDir}/${name}.jar"
Tamas Kenez925cb642017-09-19 10:41:15 +0200837 into "${exampleOutputDir}"
838 rename(".*", "${name}_debuginfo_none.jar")
Tamas Kenezc5163ed2017-09-19 09:27:37 +0200839 }
Mads Ager418d1ca2017-05-22 09:35:49 +0200840 } else {
841 task "jar_example_${name}"(type: Jar, dependsOn: "compile_examples") {
Tamas Kenezc5163ed2017-09-19 09:27:37 +0200842 archiveName = "${name}.jar"
Mads Ager418d1ca2017-05-22 09:35:49 +0200843 destinationDir = exampleOutputDir
844 from "build/test/examples/classes"
Søren Gjesse7320ce52018-05-07 15:45:22 +0200845 include name + "/**/*"
Stephan Herhut417a72a2017-07-18 10:38:30 +0200846 with runtimeDependencies
Søren Gjesse7320ce52018-05-07 15:45:22 +0200847 includeEmptyDirs true
Mads Ager418d1ca2017-05-22 09:35:49 +0200848 }
Tamas Kenezc5163ed2017-09-19 09:27:37 +0200849 task "jar_example_${name}_debuginfo_all"(type: Jar, dependsOn: "compile_examples_debuginfo_all") {
850 archiveName = "${name}_debuginfo_all.jar"
851 destinationDir = exampleOutputDir
852 from "build/test/examples/classes_debuginfo_all"
853 include name + "/**/*.class"
854 with runtimeDependencies
855 includeEmptyDirs false
856 }
857 task "jar_example_${name}_debuginfo_none"(type: Jar, dependsOn: "compile_examples_debuginfo_none") {
858 archiveName = "${name}_debuginfo_none.jar"
859 destinationDir = exampleOutputDir
860 from "build/test/examples/classes_debuginfo_none"
861 include name + "/**/*.class"
862 with runtimeDependencies
863 includeEmptyDirs false
864 }
Mads Ager418d1ca2017-05-22 09:35:49 +0200865 }
866 }
867}
868
869task buildExampleAndroidNJars {
870 dependsOn downloadDeps
871 def examplesDir = file("src/test/examplesAndroidN")
872 task "compile_examplesAndroidN"(type: JavaCompile) {
873 source = fileTree(dir: examplesDir, include: '**/*.java')
874 destinationDir = file("build/test/examplesAndroidN/classes")
875 classpath = sourceSets.main.compileClasspath
876 sourceCompatibility = JavaVersion.VERSION_1_8
877 targetCompatibility = JavaVersion.VERSION_1_8
878 options.compilerArgs += ["-Xlint:-options"]
879 }
880 examplesDir.eachDir { dir ->
881 def name = dir.getName();
882 def exampleOutputDir = file("build/test/examplesAndroidN");
883 def jarName = "${name}.jar"
884 dependsOn "jar_examplesAndroidN_${name}"
885 task "jar_examplesAndroidN_${name}"(type: Jar, dependsOn: "compile_examplesAndroidN") {
886 archiveName = jarName
887 destinationDir = exampleOutputDir
888 from "build/test/examplesAndroidN/classes"
889 include "**/" + name + "/**/*.class"
890 }
891 }
892}
893
894
895task buildExampleAndroidOJars {
896 dependsOn downloadDeps
897 def examplesDir = file("src/test/examplesAndroidO")
898 // NOTE: we want to enable a scenario when test needs to reference some
899 // classes generated by legacy (1.6) Java compiler to test some specific
900 // behaviour. To do so we compile all the java files located in sub-directory
901 // called 'legacy' with Java 1.6, then compile the rest of the files with
902 // Java 1.8 and a reference to previously generated 1.6 classes.
903
904 // Compiling all classes in dirs 'legacy' with old Java version.
905 task "compile_examplesAndroidO_Legacy"(type: JavaCompile) {
906 source = fileTree(dir: examplesDir, include: '**/legacy/**/*.java')
907 destinationDir = file("build/test/examplesAndroidOLegacy/classes")
908 classpath = sourceSets.main.compileClasspath
909 sourceCompatibility = JavaVersion.VERSION_1_6
910 targetCompatibility = JavaVersion.VERSION_1_6
911 options.compilerArgs += ["-Xlint:-options", "-parameters"]
912 }
913 // Compiling the rest of the files as Java 1.8 code.
914 task "compile_examplesAndroidO"(type: JavaCompile) {
915 dependsOn "compile_examplesAndroidO_Legacy"
916 source = fileTree(dir: examplesDir, include: '**/*.java', exclude: '**/legacy/**/*.java')
917 destinationDir = file("build/test/examplesAndroidO/classes")
918 classpath = sourceSets.main.compileClasspath
919 classpath += files("build/test/examplesAndroidOLegacy/classes")
920 sourceCompatibility = JavaVersion.VERSION_1_8
921 targetCompatibility = JavaVersion.VERSION_1_8
922 options.compilerArgs += ["-Xlint:-options", "-parameters"]
923 }
924 examplesDir.eachDir { dir ->
925 def name = dir.getName();
926 def destinationDir = file("build/test/examplesAndroidO/classes");
927 if (file("src/test/examplesAndroidO/" + name + "/TestGenerator.java").isFile()) {
928 task "generate_examplesAndroidO_${name}"(type: JavaExec,
929 dependsOn: "compile_examplesAndroidO") {
930 main = name + ".TestGenerator"
931 classpath = files(destinationDir, sourceSets.main.compileClasspath)
932 args destinationDir
933 }
934 } else {
935 task "generate_examplesAndroidO_${name}" () {}
936 }
937 }
938 examplesDir.eachDir { dir ->
939 def name = dir.getName();
940 def exampleOutputDir = file("build/test/examplesAndroidO");
941 def jarName = "${name}.jar"
942 dependsOn "jar_examplesAndroidO_${name}"
943 task "jar_examplesAndroidO_${name}"(type: Jar, dependsOn: ["compile_examplesAndroidO",
944 "generate_examplesAndroidO_${name}"]) {
945 archiveName = jarName
946 destinationDir = exampleOutputDir
947 from "build/test/examplesAndroidO/classes" // Java 1.8 classes
948 from "build/test/examplesAndroidOLegacy/classes" // Java 1.6 classes
949 include "**/" + name + "/**/*.class"
950 // Do not include generator into the test runtime jar, it is not useful.
951 // Otherwise, shrinking will need ASM jars.
952 exclude "**/TestGenerator*"
953 }
954 }
955}
956
Mikaël Peltier7b7b53a2017-10-09 13:33:21 +0200957task buildExampleAndroidPJars {
958 dependsOn downloadDeps
959 def examplesDir = file("src/test/examplesAndroidP")
960
961 task "compile_examplesAndroidP"(type: JavaCompile) {
962 source = fileTree(dir: examplesDir, include: '**/*.java')
963 destinationDir = file("build/test/examplesAndroidP/classes")
964 classpath = sourceSets.main.compileClasspath
965 sourceCompatibility = JavaVersion.VERSION_1_8
966 targetCompatibility = JavaVersion.VERSION_1_8
967 options.compilerArgs += ["-Xlint:-options"]
968 }
969 examplesDir.eachDir { dir ->
970 def name = dir.getName();
971 def destinationDir = file("build/test/examplesAndroidP/classes");
972 if (file("src/test/examplesAndroidP/" + name + "/TestGenerator.java").isFile()) {
973 task "generate_examplesAndroidP_${name}"(type: JavaExec,
974 dependsOn: "compile_examplesAndroidP") {
975 main = name + ".TestGenerator"
976 classpath = files(destinationDir, sourceSets.main.compileClasspath)
977 args destinationDir
978 }
979 } else {
980 task "generate_examplesAndroidP_${name}" () {}
981 }
982 }
983 examplesDir.eachDir { dir ->
984 def name = dir.getName();
985 def exampleOutputDir = file("build/test/examplesAndroidP");
986 def jarName = "${name}.jar"
987 dependsOn "jar_examplesAndroidP_${name}"
988 task "jar_examplesAndroidP_${name}"(type: Jar,
989 dependsOn: ["compile_examplesAndroidP",
990 "generate_examplesAndroidP_${name}"]) {
991 archiveName = jarName
992 destinationDir = exampleOutputDir
993 from "build/test/examplesAndroidP/classes" // Java 1.8 classes
994 include "**/" + name + "/**/*.class"
995 // Do not include generator into the test runtime jar, it is not useful.
996 // Otherwise, shrinking will need ASM jars.
997 exclude "**/TestGenerator*"
998 }
999 }
1000}
1001
Mikaël Peltier61633d42017-10-13 16:51:06 +02001002task buildExampleJava9Jars {
1003 def examplesDir = file("src/test/examplesJava9")
1004 examplesDir.eachDir { dir ->
1005 def name = dir.getName();
1006 def exampleOutputDir = file("build/test/examplesJava9");
1007 def jarName = "${name}.jar"
1008 dependsOn "jar_examplesJava9_${name}"
1009 task "jar_examplesJava9_${name}"(type: Jar) {
1010 archiveName = jarName
1011 destinationDir = exampleOutputDir
1012 from "src/test/examplesJava9" // Java 1.9 classes
1013 include "**/" + name + "/**/*.class"
1014 }
1015 }
1016}
1017
Mikaël Peltier3c8b6ea2017-12-12 13:00:21 +01001018task buildExamplesKotlin {
1019 if (OperatingSystem.current().isMacOsX() || OperatingSystem.current().isWindows()) {
1020 logger.lifecycle("WARNING: Testing (including building kotlin examples) is only partially" +
1021 " supported on your platform (" + OperatingSystem.current().getName() + ").")
1022 } else if (!OperatingSystem.current().isLinux()) {
1023 logger.lifecycle("WARNING: Testing (including building kotlin examples) is not supported " +
1024 "on your platform. It is fully supported on Linux and partially supported on " +
1025 "Mac OS and Windows")
1026 return;
1027 }
1028 def examplesDir = file("src/test/examplesKotlin")
1029 examplesDir.eachDir { dir ->
Sebastien Hertz2ac9bac2018-01-15 16:33:44 +00001030 def name = dir.getName();
1031 dependsOn "dex_example_kotlin_${name}"
1032 def exampleOutputDir = file("build/test/examplesKotlin/" + name);
1033 def dexPath = file("${exampleOutputDir}")
1034 task "dex_example_kotlin_${name}"(type: dx.Dx,
1035 dependsOn: "compile_example_kotlin_${name}") {
1036 doFirst {
1037 if (!dexPath.exists()) {
1038 dexPath.mkdirs()
Mikaël Peltier3c8b6ea2017-12-12 13:00:21 +01001039 }
1040 }
Sebastien Hertz2ac9bac2018-01-15 16:33:44 +00001041 source = files(tasks.getByPath("compile_example_kotlin_${name}")).asFileTree
1042 destination = dexPath
1043 debug = false
Mikaël Peltier3c8b6ea2017-12-12 13:00:21 +01001044 }
1045 }
1046}
1047
Sebastien Hertzd3313772018-01-16 14:12:37 +01001048task buildKotlinR8TestResources {
1049 def examplesDir = file("src/test/kotlinR8TestResources")
1050 examplesDir.eachDir { dir ->
Sebastien Hertzfe97a712018-02-13 12:08:59 +01001051 kotlin.Kotlinc.KotlinTargetVersion.values().each { kotlinTargetVersion ->
1052 def name = dir.getName()
1053 def taskName = "jar_kotlinR8TestResources_${name}_${kotlinTargetVersion}"
1054 def outputFile = "build/test/kotlinR8TestResources/${kotlinTargetVersion}/${name}.jar"
Denis Vnukovc22da842018-03-14 12:57:20 -07001055 def javaOutput = "build/test/kotlinR8TestResources/${kotlinTargetVersion}/${name}/java"
1056 def javaOutputJarName = "${name}.java.jar"
1057 def javaOutputJarDir = "build/test/kotlinR8TestResources/${kotlinTargetVersion}"
1058 task "${taskName}Kotlin"(type: kotlin.Kotlinc) {
1059 source = fileTree(dir: file("${examplesDir}/${name}"),
1060 include: ['**/*.kt', '**/*.java'])
Sebastien Hertzfe97a712018-02-13 12:08:59 +01001061 destination = file(outputFile)
1062 targetVersion = kotlinTargetVersion
1063 }
Denis Vnukovc22da842018-03-14 12:57:20 -07001064 task "${taskName}Java"(type: JavaCompile) {
1065 source = fileTree(dir: file("${examplesDir}/${name}"), include: '**/*.java')
1066 destinationDir = file(javaOutput)
1067 classpath = sourceSets.main.compileClasspath
1068 sourceCompatibility = JavaVersion.VERSION_1_6
1069 targetCompatibility = JavaVersion.VERSION_1_6
1070 options.compilerArgs += ["-g", "-Xlint:-options"]
1071 }
1072 task "${taskName}JavaJar"(type: Jar, dependsOn: "${taskName}Java") {
1073 archiveName = javaOutputJarName
1074 destinationDir = file(javaOutputJarDir)
1075 from javaOutput
1076 include "**/*.class"
1077 }
1078 dependsOn "${taskName}Kotlin", "${taskName}JavaJar"
Sebastien Hertzd3313772018-01-16 14:12:37 +01001079 }
Sebastien Hertzd3313772018-01-16 14:12:37 +01001080 }
1081}
1082
Mads Ager418d1ca2017-05-22 09:35:49 +02001083task buildExamples {
Jean-Marie Henaff39587a82017-06-08 15:20:13 +02001084 if (OperatingSystem.current().isMacOsX() || OperatingSystem.current().isWindows()) {
1085 logger.lifecycle("WARNING: Testing (including building examples) is only partially supported on your " +
1086 "platform (" + OperatingSystem.current().getName() + ").")
Mads Ager418d1ca2017-05-22 09:35:49 +02001087 } else if (!OperatingSystem.current().isLinux()) {
1088 logger.lifecycle("WARNING: Testing (including building examples) is not supported on your platform. " +
Jean-Marie Henaff39587a82017-06-08 15:20:13 +02001089 "It is fully supported on Linux and partially supported on Mac OS and Windows")
Mads Ager418d1ca2017-05-22 09:35:49 +02001090 return;
1091 }
1092 dependsOn buildDebugTestResourcesJars
1093 dependsOn buildExampleJars
1094 dependsOn buildExampleAndroidNJars
1095 dependsOn buildExampleAndroidOJars
Mikaël Peltier7b7b53a2017-10-09 13:33:21 +02001096 dependsOn buildExampleAndroidPJars
Mikaël Peltier61633d42017-10-13 16:51:06 +02001097 dependsOn buildExampleJava9Jars
Søren Gjesse5b4ee0a2018-01-30 13:46:39 +01001098 dependsOn buildExampleAndroidApi
Mads Ager418d1ca2017-05-22 09:35:49 +02001099 def examplesDir = file("src/test/examples")
Yohann Rousself820a572017-05-31 20:25:51 +02001100 def noDexTests = [
1101 "multidex",
1102 "multidex002",
1103 "multidex004",
1104 ]
Mads Ager418d1ca2017-05-22 09:35:49 +02001105 examplesDir.eachDir { dir ->
1106 def name = dir.getName();
Yohann Rousself820a572017-05-31 20:25:51 +02001107 if (!(name in noDexTests)) {
1108 dependsOn "dex_example_${name}"
1109 def exampleOutputDir = file("build/test/examples/" + name);
1110 def dexPath = file("${exampleOutputDir}")
1111 def debug = (name == "throwing")
1112 if (!dexPath.exists()) {
1113 dexPath.mkdirs()
1114 }
1115 task "dex_example_${name}"(type: dx.Dx, dependsOn: "jar_example_${name}") {
1116 source = files(tasks.getByPath("jar_example_${name}")).asFileTree
1117 destination = dexPath
1118 debug = debug
1119 }
Mads Ager418d1ca2017-05-22 09:35:49 +02001120 }
1121 }
1122}
1123
1124task buildSmali {
1125 def smaliDir = file("src/test/smali")
1126 smaliDir.eachDirRecurse() { dir ->
1127 def name = dir.getName();
1128 def relativeDir = smaliDir.toPath().relativize(dir.toPath());
1129 def smaliOutputDir = file("build/test/smali/" + relativeDir);
1130 smaliOutputDir.mkdirs()
1131 outputs.dir smaliOutputDir
1132 def taskName = "smali_build_${relativeDir.toString().replace('/', '_')}"
1133 def smaliFiles = fileTree(dir: dir, include: '*.smali')
1134 def javaFiles = fileTree(dir: dir, include: '*.java')
1135 def destDir = smaliOutputDir;
1136 def destFile = destDir.toPath().resolve("${name}.dex").toFile()
1137 def intermediateFileName = "${name}-intermediate.dex";
1138 def intermediateFile = destDir.toPath().resolve(intermediateFileName).toFile()
1139 if (javaFiles.empty) {
1140 if (!smaliFiles.empty) {
1141 dependsOn "${taskName}_smali"
1142 task "${taskName}_smali"(type: smali.Smali) {
1143 source = smaliFiles
1144 destination = destFile
1145 }
1146 }
1147 } else {
1148 dependsOn "${taskName}_dexmerger"
1149 task "${taskName}_smali"(type: smali.Smali) {
1150 source = smaliFiles
1151 destination = intermediateFile
1152 }
1153 task "${taskName}_java"(type: JavaCompile) {
1154 source = javaFiles
1155 destinationDir destDir
1156 classpath = sourceSets.main.compileClasspath
1157 sourceCompatibility = JavaVersion.VERSION_1_7
1158 targetCompatibility = JavaVersion.VERSION_1_7
1159 options.compilerArgs += ["-Xlint:-options"]
1160 }
1161 task "${taskName}_jar"(type: Jar, dependsOn: "${taskName}_java") {
1162 archiveName = "Test.jar"
1163 destinationDir = destDir
1164 from fileTree(dir: destDir, include: 'Test.class')
1165 }
1166 task "${taskName}_dx"(type: dx.Dx, dependsOn: "${taskName}_jar") {
1167 source = fileTree(dir: destDir, include: 'Test.jar')
1168 destination = destDir
1169 }
1170 task "${taskName}_dexmerger"(
1171 type: dx.DexMerger, dependsOn: ["${taskName}_dx", "${taskName}_smali"]) {
1172 source = fileTree(dir: destDir, include: ["classes.dex", intermediateFileName])
1173 destination = destFile
1174 }
1175 }
1176 }
1177}
1178
1179tasks.withType(Test) {
1180 def userDefinedCoresPerFork = System.getenv('R8_GRADLE_CORES_PER_FORK')
1181 def coresPerFork = userDefinedCoresPerFork ? userDefinedCoresPerFork.toInteger() : 3
1182 // See https://docs.gradle.org/current/dsl/org.gradle.api.tasks.testing.Test.html.
1183 maxParallelForks = Runtime.runtime.availableProcessors().intdiv(coresPerFork) ?: 1
1184 forkEvery = 0
1185 // Use the Concurrent Mark Sweep GC (CMS) to keep memory usage at a resonable level.
1186 jvmArgs = ["-XX:+UseConcMarkSweepGC"]
Søren Gjesseaf1c5e22017-06-15 12:24:03 +02001187 if (project.hasProperty('disable_assertions')) {
1188 enableAssertions = false
1189 }
Mads Ager418d1ca2017-05-22 09:35:49 +02001190}
1191
1192task buildPreNJdwpTestsJar(type: Jar) {
1193 baseName = 'jdwp-tests-preN'
1194 from zipTree('third_party/jdwp-tests/apache-harmony-jdwp-tests-host.jar')
1195 // Exclude the classes containing java8
1196 exclude 'org/apache/harmony/jpda/tests/jdwp/InterfaceType/*.class'
1197 exclude 'org/apache/harmony/jpda/tests/jdwp/ObjectReference/InvokeMethodDefault*.class'
1198 includeEmptyDirs = false
1199}
1200
Ian Zerny74143162017-11-24 13:46:35 +01001201task buildPreNJdwpTestsDex(type: Exec, dependsOn: "buildPreNJdwpTestsJar") {
1202 def inFile = buildPreNJdwpTestsJar.archivePath
1203 def outFile = new File(buildPreNJdwpTestsJar.destinationDir, buildPreNJdwpTestsJar.baseName + '-dex.jar')
1204 inputs.file inFile
1205 outputs.file outFile
1206 if (OperatingSystem.current().isWindows()) {
1207 executable file("tools/windows/dx/bin/dx.bat")
1208 } else if (OperatingSystem.current().isMacOsX()) {
1209 executable file("tools/mac/dx/bin/dx");
1210 } else {
1211 executable file("tools/linux/dx/bin/dx");
1212 }
1213 args "--dex"
1214 args "--output=${outFile}"
1215 args inFile
1216}
1217
Ivan Gavrilovic635c7e52017-12-01 15:10:45 +00001218task getJarsFromSupportLibs(type: GetJarsFromConfiguration) {
1219 setConfiguration(configurations.supportLibs)
Yohann Roussel126f6872017-08-03 16:25:32 +02001220}
1221
Tamas Kenez0cad51c2017-08-21 14:42:01 +02001222task AospJarTest(type: Exec) {
1223 dependsOn CompatDx, downloadDeps
1224 def script = "tools/test_aosp_jar.py"
1225 inputs.file script
1226 commandLine "python", script, "--no-build"
1227 workingDir = projectDir
1228}
1229
Mads Ager418d1ca2017-05-22 09:35:49 +02001230test {
Jean-Marie Henaff7a64eec2018-05-31 15:30:35 +02001231 if (project.hasProperty('generate_golden_files_to')) {
1232 systemProperty 'generate_golden_files_to', project.property('generate_golden_files_to')
1233 assert project.hasProperty('HEAD_sha1')
1234 systemProperty 'test_git_HEAD_sha1', project.property('HEAD_sha1')
1235 }
1236
1237 if (project.hasProperty('use_golden_files_in')) {
1238 systemProperty 'use_golden_files_in', project.property('use_golden_files_in')
1239 assert project.hasProperty('HEAD_sha1')
1240 systemProperty 'test_git_HEAD_sha1', project.property('HEAD_sha1')
1241 }
1242
Ivan Gavrilovic635c7e52017-12-01 15:10:45 +00001243 dependsOn getJarsFromSupportLibs
Mads Ager418d1ca2017-05-22 09:35:49 +02001244 testLogging.exceptionFormat = 'full'
1245 if (project.hasProperty('print_test_stdout')) {
1246 testLogging.showStandardStreams = true
1247 }
Tamas Kenez0cad51c2017-08-21 14:42:01 +02001248 if (project.hasProperty('dex_vm') && project.property('dex_vm') != 'default') {
Mads Ager418d1ca2017-05-22 09:35:49 +02001249 println "Running with non default vm: " + project.property('dex_vm')
1250 systemProperty 'dex_vm', project.property('dex_vm')
Ian Zerny3f4ed602017-10-05 06:54:13 +02001251 if (project.property('dex_vm').startsWith('4.4.4') ||
1252 project.property('dex_vm').startsWith('5.1.1') ||
1253 project.property('dex_vm').startsWith('6.0.1')) {
Mads Ager418d1ca2017-05-22 09:35:49 +02001254 // R8 and D8 compute the dex file version number based on the input.
1255 // Jack generates dex files with version 37 which art 5.1.1 and 6.0.1 will not run.
1256 // Therefore we skip the jack generated art tests with those art versions.
1257 exclude "com/android/tools/r8/art/jack/**"
1258 }
1259 }
Tamas Kenez0cad51c2017-08-21 14:42:01 +02001260
Mads Ager418d1ca2017-05-22 09:35:49 +02001261 if (project.hasProperty('one_line_per_test')) {
1262 beforeTest { desc ->
1263 println "Start executing test ${desc.name} [${desc.className}]"
1264 }
1265 afterTest { desc, result ->
1266 println "Done executing test ${desc.name} [${desc.className}] with result: ${result.resultType}"
1267 }
1268 }
1269 if (project.hasProperty('no_internal')) {
1270 exclude "com/android/tools/r8/internal/**"
1271 }
1272 if (project.hasProperty('only_internal')) {
1273 include "com/android/tools/r8/internal/**"
1274 }
1275 if (project.hasProperty('tool')) {
1276 if (project.property('tool') == 'r8') {
1277 exclude "com/android/tools/r8/art/*/d8/**"
Tamas Kenez69c2e8b2017-05-31 13:41:07 +02001278 exclude "com/android/tools/r8/jctf/d8/**"
Mads Ager418d1ca2017-05-22 09:35:49 +02001279 } else {
1280 assert(project.property('tool') == 'd8')
1281 exclude "com/android/tools/r8/art/*/r8/**"
Tamas Kenez69c2e8b2017-05-31 13:41:07 +02001282 exclude "com/android/tools/r8/jctf/r8/**"
Mads Ager418d1ca2017-05-22 09:35:49 +02001283 }
1284 }
1285 if (!project.hasProperty('all_tests')) {
1286 exclude "com/android/tools/r8/art/dx/**"
1287 exclude "com/android/tools/r8/art/jack/**"
1288 }
1289 // TODO(tamaskenez) enable jctf on all_tests when consolidated
1290 if (!project.hasProperty('jctf') && !project.hasProperty('only_jctf')) {
Stephan Herhutea6ee582017-05-23 13:14:34 +02001291 exclude "com/android/tools/r8/jctf/**"
Mads Ager418d1ca2017-05-22 09:35:49 +02001292 }
1293 if (project.hasProperty('only_jctf')) {
Stephan Herhutea6ee582017-05-23 13:14:34 +02001294 include "com/android/tools/r8/jctf/**"
Mads Ager418d1ca2017-05-22 09:35:49 +02001295 }
1296 if (project.hasProperty('jctf_compile_only')) {
1297 println "JCTF: compiling only"
1298 systemProperty 'jctf_compile_only', '1'
1299 }
Tamas Kenezb77b7d82017-08-17 14:05:16 +02001300 if (project.hasProperty('test_dir')) {
1301 systemProperty 'test_dir', project.property('test_dir')
1302 }
Tamas Kenez0cad51c2017-08-21 14:42:01 +02001303 if (project.hasProperty('aosp_jar')) {
1304 dependsOn AospJarTest
1305 }
Mads Ager418d1ca2017-05-22 09:35:49 +02001306
Jean-Marie Henaff39587a82017-06-08 15:20:13 +02001307 if (OperatingSystem.current().isLinux()
1308 || OperatingSystem.current().isMacOsX()
1309 || OperatingSystem.current().isWindows()) {
Mads Ager418d1ca2017-05-22 09:35:49 +02001310 if (OperatingSystem.current().isMacOsX()) {
1311 logger.lifecycle("WARNING: Testing in only partially supported on Mac OS. " +
1312 "Art only runs on Linux and tests requiring Art runs in a Docker container, which must be present. " +
1313 "See tools/docker/README.md for details.")
1314 }
Jean-Marie Henaff39587a82017-06-08 15:20:13 +02001315 if (OperatingSystem.current().isWindows()) {
1316 logger.lifecycle("WARNING: Testing in only partially supported on Windows. " +
1317 "Art only runs on Linux and tests requiring Art will be skipped")
1318 }
Mads Ager418d1ca2017-05-22 09:35:49 +02001319 dependsOn downloadDeps
1320 dependsOn buildExamples
Mikaël Peltier3c8b6ea2017-12-12 13:00:21 +01001321 dependsOn buildExamplesKotlin
Sebastien Hertzd3313772018-01-16 14:12:37 +01001322 dependsOn buildKotlinR8TestResources
Mads Ager418d1ca2017-05-22 09:35:49 +02001323 dependsOn buildSmali
1324 dependsOn jctfCommonJar
1325 dependsOn jctfTestsClasses
1326 dependsOn buildDebugInfoExamplesDex
1327 dependsOn buildPreNJdwpTestsJar
Mathias Ravcd795072018-03-22 12:47:32 +01001328 dependsOn buildPreNJdwpTestsDex
Mads Ager418d1ca2017-05-22 09:35:49 +02001329 } else {
1330 logger.lifecycle("WARNING: Testing in not supported on your platform. Testing is only fully supported on " +
Jean-Marie Henaff39587a82017-06-08 15:20:13 +02001331 "Linux and partially supported on Mac OS and Windows. Art does not run on other platforms.")
Mads Ager418d1ca2017-05-22 09:35:49 +02001332 }
1333}
1334
1335// The Art tests we use for R8 are pre-build and downloaded from Google Cloud Storage.
1336//
1337// To build and upload a new set of the Art tests for use with R8 follow these steps:
1338//
1339// First of all an Android checkout is required. Currently it must be located
1340// in $HOME/android/master.
1341//
1342// TODO(ricow): simplify this
1343//
1344// Before: update the checked in art, see scripts/update-host-art.sh
1345//
1346// 1. Get an android checkout in $HOME/android/master and apply the patch from
1347// https://android-review.googlesource.com/#/c/294187/
1348//
1349// 2. run the following commands in the Android checkout directory:
1350//
1351// source build/envsetup.sh
Søren Gjesse34b77732017-07-07 13:56:21 +02001352// lunch aosp_angler-userdebug # or lunch aosp_angler-eng
1353// m desugar
1354// m -j30 test-art-host
1355// DESUGAR=false ANDROID_COMPILE_WITH_JACK=false art/test.py --host -t 001-HelloWorld
1356//
1357// Without running the test.py command the classes.jar file used by desugar in
1358// $HOME/android/master/out/host/common/obj/JAVA_LIBRARIES/core-oj-hostdex_intermediates/
1359// seems to be missing - there is probably also a make target to build it more directly
Mads Ager418d1ca2017-05-22 09:35:49 +02001360//
1361// 3. In the R8 project root directory, make sure we have a clean state before starting:
1362// tools/gradle.py downloadDeps
1363// tools/gradle.py clean
1364// rm -rf tests/art
1365//
1366// 4. Now build in the R8 checkout (-P hack to not generate dirs when not running this target)
Søren Gjesse34b77732017-07-07 13:56:21 +02001367// Make sure you have smali on your path, please use the build binary in the
1368// out/host/linux-x86/bin directory of the android checkout. Currently this is version pre 2.2.1,
1369// if that is updated the call to smali in "task "${smaliToDexTask}"(type: Exec)" below might
1370// need to change as smali got a completely new command line interface in version 2.2.1.
Mikaël Peltiere116cb62017-10-05 10:50:30 +02001371// After Android O, Jack is no longer alive, do not forget to uncomment call to buildArtTest for
1372// Jack if you build an android version using Jack.
Mads Ager418d1ca2017-05-22 09:35:49 +02001373//
Søren Gjesse34b77732017-07-07 13:56:21 +02001374// PATH=$HOME/android/master/out/host/linux-x86/bin:$PATH tools/gradle.py -Pandroid_source buildArtTests
Mads Ager418d1ca2017-05-22 09:35:49 +02001375//
1376// 4a. If any failures are produced in step 4, figure out what went wrong and add an entry in
1377// skippedTests with an explanation. Rerun from step 3.
1378//
1379// 5. Run the tests:
1380// tools/gradle.py clean
1381// tools/test.py
1382//
Søren Gjesse34b77732017-07-07 13:56:21 +02001383// 5a. If any more tests fail, either fix the issue or add them to the failuresToTriage list (note
1384// that you need to change "_" to "-" from stdout). Rerun from step 5 if anything was added to
1385// failuresToTriage.
Mads Ager418d1ca2017-05-22 09:35:49 +02001386//
Søren Gjesse34b77732017-07-07 13:56:21 +02001387// 6. To upload a new version to Google Cloud Storage:
Mads Ager418d1ca2017-05-22 09:35:49 +02001388// cd tests
1389// upload_to_google_storage.py -a --bucket r8-deps art
Søren Gjesse34b77732017-07-07 13:56:21 +02001390//
1391// 7. Update the manifest file describing the Android repo used:
1392// repo manifest -o <r8-checkout-root>/tools/linux/aosp_master_manifest.xml -r
Mads Ager418d1ca2017-05-22 09:35:49 +02001393
1394enum DexTool {
1395 JACK,
1396 DX
1397}
1398
1399def androidCheckoutDir = file("${System.env.HOME}/android/master")
1400def androidCheckoutJack = file("${androidCheckoutDir}/out/host/linux-x86/bin/jack");
1401def androidCheckoutJackServer = file("${androidCheckoutDir}/out/host/linux-x86/bin/jack-admin");
1402
1403def artTestDir = file("${androidCheckoutDir}/art/test")
1404
1405if (project.hasProperty('android_source')) {
1406 task buildArtTests {
1407 outputs.upToDateWhen { false }
1408 def toBeTriaged = [
1409 "903-hello-tagging",
1410 "904-object-allocation",
1411 "905-object-free",
1412 "906-iterate-heap",
1413 "907-get-loaded-classes",
1414 "908-gc-start-finish",
1415 "954-invoke-polymorphic-verifier",
1416 "955-methodhandles-smali",
1417 "596-monitor-inflation",
1418 ]
1419 def skippedTests = toBeTriaged + [
1420 // This test produces no jar.
1421 "000-nop",
1422 // This does not build, as it tests the error when the application exceeds more
1423 // than 65536 methods
1424 "089-many-methods",
1425 // Requires some jack beta jar
1426 "956-methodhandles",
1427 ]
1428
1429 def skippedTestsDx = [
1430 // Tests with custom build scripts, where javac is not passed the options
1431 // -source 1.7 -target 1.7.
1432 "462-checker-inlining-across-dex-files",
1433 "556-invoke-super",
1434 "569-checker-pattern-replacement",
1435 // These tests use jack even when --build-with-javac-dx is specified.
1436 "004-JniTest",
1437 "048-reflect-v8",
1438 "146-bad-interface",
1439 "563-checker-invoke-super",
1440 "580-checker-string-fact-intrinsics", // java.lang.StringFactory
1441 "604-hot-static-interface",
1442 "957-methodhandle-transforms",
1443 "958-methodhandle-emulated-stackframe",
1444 "959-invoke-polymorphic-accessors",
1445 "961-default-iface-resolution-gen",
1446 "962-iface-static",
1447 "963-default-range-smali",
1448 "964-default-iface-init-gen",
1449 "965-default-verify",
1450 "966-default-conflict",
1451 "967-default-ame",
1452 "968-default-partial-compile-gen",
1453 "969-iface-super",
1454 "970-iface-super-resolution-gen",
1455 "971-iface-super",
1456 // These tests does not build with --build-with-javac-dx
1457 "004-NativeAllocations", // Javac error
1458 "031-class-attributes",
1459 "138-duplicate-classes-check",
1460 "157-void-class", // Javac error
1461 "580-checker-string-factory-intrinsics",
1462 "612-jit-dex-cache",
1463 "613-inlining-dex-cache",
1464 "900-hello-plugin", // --experimental agents
1465 "901-hello-ti-agent", // --experimental agents
1466 "902-hello-transformation", // --experimental agents
1467 "909-attach-agent", // --experimental agents
1468 "946-obsolete-throw", // -source 1.7 -target 1.7, but use lambda
1469 "950-redefine-intrinsic", // -source 1.7 -target 1.7, but use method references
1470 "951-threaded-obsolete", // -source 1.7 -target 1.7, but use lambda
1471 "960-default-smali", // --experimental default-methods
1472 // These tests force the build to use jack
1473 "953-invoke-polymorphic-compiler",
1474 "958-methodhandle-stackframe",
1475 ]
1476
1477 def artTestBuildDir = file("${projectDir}/tests/art")
1478
1479 if (androidCheckoutDir.exists()) {
1480 dependsOn downloadDeps
1481 artTestBuildDir.mkdirs()
1482 // Ensure Jack server is running.
1483 "${androidCheckoutJackServer} start-server".execute()
1484 artTestDir.eachDir { dir ->
1485 def name = dir.getName();
1486 def markerFile = dir.toPath().resolve("info.txt").toFile();
1487 if (markerFile.exists() && !(name in skippedTests)) {
1488 if (!(name in skippedTestsDx)) {
1489 dependsOn buildArtTest(androidCheckoutDir, artTestBuildDir, dir, DexTool.DX);
1490 }
Mikaël Peltiere116cb62017-10-05 10:50:30 +02001491 // After Android O, Jack is no longer alive
1492 //dependsOn buildArtTest(androidCheckoutDir, artTestBuildDir, dir, DexTool.JACK);
Mads Ager418d1ca2017-05-22 09:35:49 +02001493 }
1494 }
1495 }
1496 doFirst {
1497 if (!androidCheckoutDir.exists()) {
1498 throw new InvalidUserDataException(
1499 "This task requires an Android checkout in ${androidCheckoutDir}");
1500 } else if (!androidCheckoutJack.exists() ||
1501 !androidCheckoutJackServer.exists()) {
1502 throw new InvalidUserDataException(
1503 "This task requires that tools for host testing have been build in the " +
1504 "Android checkout in ${androidCheckoutDir}");
1505 }
1506 }
1507 doLast {
1508 copy {
1509 from file("${androidCheckoutDir}/out/host/linux-x86/nativetest64")
1510 into file("${artTestBuildDir}/lib64")
1511 include 'lib*.so'
1512 }
1513 copy {
1514 from file("${androidCheckoutDir}/out/host/linux-x86/lib64")
1515 into file("${artTestBuildDir}/lib64")
1516 include 'libart.so'
1517 include 'libbacktrace.so'
1518 include 'libbase.so'
1519 include 'libc++.so'
1520 include 'libcutils.so'
1521 include 'liblz4.so'
1522 include 'liblzma.so'
1523 include 'libnativebridge.so'
1524 include 'libnativeloader.so'
1525 include 'libsigchain.so'
1526 include 'libunwind.so'
1527 include 'libziparchive.so'
1528 }
1529 copy {
1530 from file("${androidCheckoutDir}/out/host/linux-x86/nativetest")
1531 into file("${artTestBuildDir}/lib")
1532 include 'lib*.so'
1533 }
1534 copy {
1535 from file("${androidCheckoutDir}/out/host/linux-x86/lib")
1536 into file("${artTestBuildDir}/lib")
1537 include 'libart.so'
1538 include 'libbacktrace.so'
1539 include 'libbase.so'
1540 include 'libc++.so'
1541 include 'libcutils.so'
1542 include 'liblz4.so'
1543 include 'liblzma.so'
1544 include 'libnativebridge.so'
1545 include 'libnativeloader.so'
1546 include 'libsigchain.so'
1547 include 'libunwind.so'
1548 include 'libziparchive.so'
1549 }
1550 }
1551 }
1552}
1553
1554def buildArtTest(androidCheckoutDir, artTestBuildDir, dir, dexTool) {
1555 def artTestDir = file("${androidCheckoutDir}/art/test")
1556 def artRunTestScript = file("${artTestDir}/run-test")
1557 def dxExecutable = new File("tools/linux/dx/bin/dx");
Jean-Marie Henaff34d85f72017-06-14 10:32:04 +02001558 def dexMergerExecutable = Utils.dexMergerExecutable()
Mads Ager418d1ca2017-05-22 09:35:49 +02001559 def dexToolName = dexTool == DexTool.DX ? "dx" : "jack"
1560
Søren Gjesse34b77732017-07-07 13:56:21 +02001561 def name = dir.getName()
Mads Ager418d1ca2017-05-22 09:35:49 +02001562 def buildTask = "build_art_test_${dexToolName}_${name}"
1563 def sanitizeTask = "sanitize_art_test_${dexToolName}_${name}"
1564 def copyCheckTask = "copy_check_art_test_${dexToolName}_${name}"
1565 def smaliToDexTask = "smali_to_dex_${dexToolName}_${name}"
1566
1567 def buildInputs = fileTree(dir: dir, include: '**/*')
1568 def testDir = file("${artTestBuildDir}/${dexToolName}/${name}")
1569 def outputJar = testDir.toPath().resolve("${name}.jar").toFile()
1570 testDir.mkdirs()
1571 if (dexTool == DexTool.DX) {
1572 task "$buildTask"(type: Exec) {
1573 outputs.upToDateWhen { false }
1574 inputs.file buildInputs
1575 executable "${artRunTestScript}"
1576 args "--host"
1577 args "--build-only"
1578 args "--build-with-javac-dx"
1579 args "--output-path", "${testDir}"
1580 args "${name}"
1581 environment DX: "${dxExecutable.absolutePath}"
1582 environment DXMERGER: "${dexMergerExecutable.absolutePath}"
Søren Gjesse34b77732017-07-07 13:56:21 +02001583 environment ANDROID_BUILD_TOP: "${androidCheckoutDir}"
Mads Ager418d1ca2017-05-22 09:35:49 +02001584 outputs.file outputJar
1585 }
1586 } else {
1587 assert dexTool == DexTool.JACK
1588 def javaLibs = "${androidCheckoutDir}/out/host/common/obj/JAVA_LIBRARIES"
1589 def jackClasspath = "${javaLibs}/core-libart-hostdex_intermediates/classes.jack:" +
1590 "${javaLibs}/core-oj-hostdex_intermediates/classes.jack"
1591 task "$buildTask"(type: Exec) {
1592 outputs.upToDateWhen { false }
1593 inputs.file buildInputs
1594 executable "${artRunTestScript}"
1595 args "--host"
1596 args "--build-only"
1597 args "--output-path", "${testDir}"
1598 args "${name}"
1599 environment JACK: "${androidCheckoutDir}/out/host/linux-x86/bin/jack"
1600 environment JACK_CLASSPATH: jackClasspath
1601 environment DXMERGER: "${dexMergerExecutable.absolutePath}"
1602 environment ANDROID_BUILD_TOP: "${androidCheckoutDir}"
1603 outputs.file outputJar
1604 }
1605 }
1606 task "${sanitizeTask}"(type: Exec, dependsOn: buildTask) {
1607 outputs.upToDateWhen { false }
1608 executable "/bin/bash"
1609 args "-c"
1610 args "rm -rf ${testDir}/smali_*.dex ${testDir}/*-ex.dex ${testDir}/*-ex.jar" +
1611 " ${testDir}/classes-ex ${testDir}/check"
1612 }
1613
1614 task "${smaliToDexTask}"(type: Exec) {
Mikaël Peltiere116cb62017-10-05 10:50:30 +02001615 // Directory that contains smali files is either smali, or smali/art
1616 def smali_dir = file("${dir}/smali/art")
1617 if (smali_dir.exists()) {
1618 workingDir "${testDir}/smali/art"
1619 } else {
1620 workingDir "${testDir}/smali"
1621 }
Mads Ager418d1ca2017-05-22 09:35:49 +02001622 executable "/bin/bash"
Søren Gjesse34b77732017-07-07 13:56:21 +02001623 // This is the command line options for smali prior to 2.2.1, where smali got a new
1624 // command line interface.
1625 args "-c", "smali a *.smali"
1626 // This is the command line options for smali 2.2.1 and later.
1627 // args "-c", "smali -o out.dex *.smali"
Mads Ager418d1ca2017-05-22 09:35:49 +02001628 }
1629
1630 task "${copyCheckTask}"(type: Copy, dependsOn: sanitizeTask) {
1631 def smali_dir = file("${dir}/smali")
1632 outputs.upToDateWhen { false }
1633 if (smali_dir.exists() && dexTool == DexTool.DX) {
1634 dependsOn smaliToDexTask
1635 }
1636 from("${artTestDir}/${name}") {
1637 include 'check'
1638 }
1639 into testDir
1640 }
1641
1642 return copyCheckTask
1643}
1644
1645task javadocD8(type: Javadoc) {
Ian Zerny850f13d2018-01-04 11:25:38 +01001646 title "D8 API"
Mads Ager418d1ca2017-05-22 09:35:49 +02001647 classpath = sourceSets.main.compileClasspath
1648 source = sourceSets.main.allJava
Yohann Rousselb16d0f62017-10-09 16:08:09 +02001649 include '**/com/android/tools/r8/ArchiveClassFileProvider.java'
Ian Zerny850f13d2018-01-04 11:25:38 +01001650 include '**/com/android/tools/r8/ArchiveProgramResourceProvider.java'
Mads Ager418d1ca2017-05-22 09:35:49 +02001651 include '**/com/android/tools/r8/BaseCommand.java'
Ian Zerny850f13d2018-01-04 11:25:38 +01001652 include '**/com/android/tools/r8/BaseCompilerCommand.java'
Yohann Rousselb16d0f62017-10-09 16:08:09 +02001653 include '**/com/android/tools/r8/ClassFileResourceProvider.java'
Yohann Roussel078c9942017-11-28 15:55:46 +01001654 include '**/com/android/tools/r8/CompilationFailedException.java'
Mads Ager418d1ca2017-05-22 09:35:49 +02001655 include '**/com/android/tools/r8/CompilationMode.java'
1656 include '**/com/android/tools/r8/D8.java'
1657 include '**/com/android/tools/r8/D8Command.java'
Ian Zerny850f13d2018-01-04 11:25:38 +01001658 include '**/com/android/tools/r8/DexIndexedConsumer.java'
1659 include '**/com/android/tools/r8/DexFilePerClassFileConsumer.java'
Yohann Roussel078c9942017-11-28 15:55:46 +01001660 include '**/com/android/tools/r8/Diagnostic.java'
1661 include '**/com/android/tools/r8/DiagnosticsHandler.java'
Ian Zernyef028f52018-01-08 14:23:17 +01001662 include '**/com/android/tools/r8/DirectoryClassFileProvider.java'
1663 include '**/com/android/tools/r8/OutputMode.java'
Ian Zerny850f13d2018-01-04 11:25:38 +01001664 include '**/com/android/tools/r8/ProgramConsumer.java'
1665 include '**/com/android/tools/r8/ProgramResource.java'
1666 include '**/com/android/tools/r8/ProgramResourceProvider.java'
Mads Ager418d1ca2017-05-22 09:35:49 +02001667 include '**/com/android/tools/r8/Resource.java'
Ian Zerny850f13d2018-01-04 11:25:38 +01001668 include '**/com/android/tools/r8/ResourceException.java'
1669 include '**/com/android/tools/r8/StringConsumer.java'
1670 include '**/com/android/tools/r8/StringResource.java'
1671 include '**/com/android/tools/r8/Version.java'
1672 include '**/com/android/tools/r8/origin/*.java'
1673}
1674
1675task javadocR8(type: Javadoc) {
1676 title "R8 API"
1677 classpath = sourceSets.main.compileClasspath
1678 source = sourceSets.main.allJava
1679 include '**/com/android/tools/r8/ArchiveClassFileProvider.java'
1680 include '**/com/android/tools/r8/ArchiveProgramResourceProvider.java'
1681 include '**/com/android/tools/r8/BaseCommand.java'
1682 include '**/com/android/tools/r8/BaseCompilerCommand.java'
1683 include '**/com/android/tools/r8/ClassFileConsumer.java'
1684 include '**/com/android/tools/r8/ClassFileResourceProvider.java'
1685 include '**/com/android/tools/r8/CompilationFailedException.java'
1686 include '**/com/android/tools/r8/CompilationMode.java'
1687 include '**/com/android/tools/r8/R8.java'
1688 include '**/com/android/tools/r8/R8Command.java'
1689 include '**/com/android/tools/r8/DexIndexedConsumer.java'
1690 include '**/com/android/tools/r8/Diagnostic.java'
1691 include '**/com/android/tools/r8/DiagnosticsHandler.java'
Ian Zernyef028f52018-01-08 14:23:17 +01001692 include '**/com/android/tools/r8/DirectoryClassFileProvider.java'
1693 include '**/com/android/tools/r8/OutputMode.java'
Ian Zerny850f13d2018-01-04 11:25:38 +01001694 include '**/com/android/tools/r8/ProgramConsumer.java'
1695 include '**/com/android/tools/r8/ProgramResource.java'
1696 include '**/com/android/tools/r8/ProgramResourceProvider.java'
1697 include '**/com/android/tools/r8/Resource.java'
1698 include '**/com/android/tools/r8/ResourceException.java'
1699 include '**/com/android/tools/r8/StringConsumer.java'
1700 include '**/com/android/tools/r8/StringResource.java'
1701 include '**/com/android/tools/r8/Version.java'
Yohann Roussel078c9942017-11-28 15:55:46 +01001702 include '**/com/android/tools/r8/origin/*.java'
Mads Ager418d1ca2017-05-22 09:35:49 +02001703}
Søren Gjesse39a909a2017-10-12 09:49:20 +02001704
1705task copyMavenDeps(type: Copy) {
1706 from configurations.compile into "$buildDir/deps"
1707 from configurations.testCompile into "$buildDir/deps"
1708}
Mikaël Peltier61633d42017-10-13 16:51:06 +02001709
1710// This task allows to build class files from Java 9 source in order to use them as inputs of
1711// D8/R8 tests. Class files are generated in the same place than source files and must be commited
1712// to the D8 repository because there is no way to generate them on all computers due to the need of
1713// Java 9.
1714// Use the following command to rebuild class files of tests:
1715// ./tools/gradle.py -Pjava9Home=<java 9 home> buildJava9Tests
1716task buildJava9Tests {
1717 def javacOutputFolder = getTemporaryDir();
1718 def examplesDir = file("src/test/examplesJava9")
1719
1720 task "compile_Java9examples"(type: JavaCompile) {
1721 doFirst {
1722 if (!project.hasProperty('java9Home') || project.property('java9Home').isEmpty()) {
1723 throw new GradleException("Set java9Home property.")
1724 }
1725 }
1726
1727 source = fileTree(dir: examplesDir, include: '**/*.java')
1728 destinationDir = javacOutputFolder
1729 classpath = sourceSets.main.compileClasspath
1730 options.compilerArgs += ["-Xlint:-options"]
1731 sourceCompatibility = JavaVersion.VERSION_1_9
1732 targetCompatibility = JavaVersion.VERSION_1_9
1733 options.fork = true
1734
1735 if (project.hasProperty('java9Home')) {
1736 options.forkOptions.javaHome = file(getProperty('java9Home'))
1737 }
1738
1739 doLast {
1740 def classfileFrom = copySpec {
1741 from javacOutputFolder
1742 include "**/*.class"
1743 }
1744 copy {
1745 into examplesDir
1746 with classfileFrom
1747 }
1748 delete javacOutputFolder
1749 }
1750 }
1751
1752 dependsOn compile_Java9examples
Benoit Lamarchea032e472017-10-17 10:52:59 +02001753}