Yigit Boyar | 88c16ce | 2017-02-08 16:06:14 -0800 | [diff] [blame] | 1 | /* |
| 2 | * Copyright (C) 2017 The Android Open Source Project |
| 3 | * |
| 4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | * you may not use this file except in compliance with the License. |
| 6 | * You may obtain a copy of the License at |
| 7 | * |
| 8 | * http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | * |
| 10 | * Unless required by applicable law or agreed to in writing, software |
| 11 | * distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | * See the License for the specific language governing permissions and |
| 14 | * limitations under the License. |
| 15 | */ |
| 16 | |
| 17 | import com.android.build.gradle.internal.coverage.JacocoPlugin |
| 18 | import com.android.build.gradle.internal.coverage.JacocoReportTask |
| 19 | import com.android.build.gradle.internal.tasks.DeviceProviderInstrumentTestTask |
| 20 | import com.google.common.base.Charsets |
| 21 | import com.google.common.io.Files |
| 22 | import org.gradle.internal.os.OperatingSystem |
| 23 | |
| 24 | def supportRoot = ext.supportRootFolder |
| 25 | if (supportRoot == null) { |
| 26 | throw new RuntimeException("variable supportRootFolder is not set. you must set it before" + |
| 27 | " including this script") |
| 28 | } |
| 29 | def init = new Properties() |
| 30 | ext.init = init |
| 31 | ext.init.checkoutRoot = "${supportRoot}/../.." |
Alan Viverette | 1b86237 | 2017-03-22 11:32:28 -0400 | [diff] [blame] | 32 | ext.init.debugKeystore = file("${supportRoot}/development/keystore/debug.keystore") |
Yigit Boyar | 88c16ce | 2017-02-08 16:06:14 -0800 | [diff] [blame] | 33 | ext.init.prebuiltsRoot = "${init.checkoutRoot}/prebuilts" |
| 34 | ext.init.prebuiltsRootUri = "file://${init.prebuiltsRoot}" |
| 35 | ext.init.enablePublicRepos = System.getenv("ALLOW_PUBLIC_REPOS") != null |
Yigit Boyar | 7bfacb7 | 2017-03-02 14:27:41 -0800 | [diff] [blame] | 36 | ext.runningInBuildServer = System.env.DIST_DIR != null && System.env.OUT_DIR != null |
Yigit Boyar | 88c16ce | 2017-02-08 16:06:14 -0800 | [diff] [blame] | 37 | |
| 38 | ext.repoNames = ["${init.prebuiltsRoot}/gradle-plugin", |
| 39 | "${init.prebuiltsRoot}/tools/common/m2/repository", |
| 40 | "${init.prebuiltsRoot}/tools/common/m2/internal", |
| 41 | "${init.prebuiltsRoot}/maven_repo/android"] |
| 42 | |
| 43 | apply from: "${supportRoot}/buildSrc/dependencies.gradle" |
Yigit Boyar | 63e6c67 | 2017-03-31 13:32:17 -0700 | [diff] [blame] | 44 | ext.buildOfflineDocs = rootProject.getProperties().containsKey("offlineDocs") |
Yigit Boyar | 88c16ce | 2017-02-08 16:06:14 -0800 | [diff] [blame] | 45 | |
| 46 | def loadDefaultVersions() { |
| 47 | apply from: "${supportRootFolder}/buildSrc/versions.gradle" |
| 48 | } |
| 49 | |
| 50 | def addMavenRepositories(RepositoryHandler handler) { |
| 51 | repoNames.each { repo -> |
| 52 | handler.maven { |
| 53 | url repo |
| 54 | } |
| 55 | if (ext.init.enablePublicRepos) { |
| 56 | handler.mavenCentral() |
| 57 | handler.jcenter() |
| 58 | } |
| 59 | } |
| 60 | } |
| 61 | |
| 62 | def enableDoclavaAndJDiff(p) { |
| 63 | p.configurations { |
| 64 | doclava |
| 65 | jdiff |
| 66 | } |
| 67 | |
| 68 | p.dependencies { |
| 69 | doclava project(':doclava') |
| 70 | jdiff project(':jdiff') |
| 71 | jdiff libs.xml_parser_apis |
| 72 | jdiff libs.xerces_impl |
| 73 | } |
| 74 | apply from: "${ext.supportRootFolder}/buildSrc/diff_and_docs.gradle" |
| 75 | } |
| 76 | |
| 77 | def setSdkInLocalPropertiesFile() { |
| 78 | final String platform = OperatingSystem.current().isMacOsX() ? 'darwin' : 'linux' |
| 79 | System.setProperty('android.dir', "${supportRootFolder}/../../") |
Aurimas Liutikas | d2d9bda | 2017-03-03 16:06:39 -0800 | [diff] [blame] | 80 | ext.buildToolsVersion = '26.0.0' |
Yigit Boyar | 88c16ce | 2017-02-08 16:06:14 -0800 | [diff] [blame] | 81 | final String fullSdkPath = "${init.prebuiltsRoot}/fullsdk-${platform}" |
| 82 | if (file(fullSdkPath).exists()) { |
| 83 | gradle.ext.currentSdk = 26 |
Alan Viverette | eb9f332 | 2017-03-09 16:29:57 -0500 | [diff] [blame] | 84 | project.ext.androidJar = |
| 85 | files("${fullSdkPath}/platforms/android-${gradle.currentSdk}/android.jar") |
| 86 | project.ext.androidSrcJar = |
| 87 | file("${fullSdkPath}/platforms/android-${gradle.currentSdk}/android-stubs-src.jar") |
Alan Viverette | 810a148 | 2017-03-20 12:43:43 -0400 | [diff] [blame] | 88 | project.ext.androidApiTxt = null |
Yigit Boyar | 88c16ce | 2017-02-08 16:06:14 -0800 | [diff] [blame] | 89 | System.setProperty('android.home', "${init.prebuiltsRoot}/fullsdk-${platform}") |
| 90 | File props = file("local.properties") |
| 91 | props.write "sdk.dir=${fullSdkPath}" |
Aurimas Liutikas | 3c66600 | 2017-03-08 19:30:28 -0800 | [diff] [blame] | 92 | ext.usingFullSdk = true |
Yigit Boyar | 88c16ce | 2017-02-08 16:06:14 -0800 | [diff] [blame] | 93 | } else { |
| 94 | gradle.ext.currentSdk = 'current' |
Yigit Boyar | 88c16ce | 2017-02-08 16:06:14 -0800 | [diff] [blame] | 95 | project.ext.androidJar = files("${init.prebuiltsRoot}/sdk/current/android.jar") |
Alan Viverette | 810a148 | 2017-03-20 12:43:43 -0400 | [diff] [blame] | 96 | project.ext.androidSrcJar = null |
| 97 | project.ext.androidApiTxt = file("${init.prebuiltsRoot}/sdk/api/26.txt") |
Yigit Boyar | 88c16ce | 2017-02-08 16:06:14 -0800 | [diff] [blame] | 98 | File props = file("local.properties") |
| 99 | props.write "android.dir=../../" |
Aurimas Liutikas | 3c66600 | 2017-03-08 19:30:28 -0800 | [diff] [blame] | 100 | ext.usingFullSdk = false |
Yigit Boyar | 88c16ce | 2017-02-08 16:06:14 -0800 | [diff] [blame] | 101 | } |
| 102 | } |
| 103 | |
| 104 | def setupRepoOutAndBuildNumber() { |
| 105 | ext.supportRepoOut = '' |
| 106 | ext.buildNumber = Integer.toString(ext.extraVersion) |
| 107 | |
| 108 | /* |
| 109 | * With the build server you are given two env variables. |
| 110 | * The OUT_DIR is a temporary directory you can use to put things during the build. |
| 111 | * The DIST_DIR is where you want to save things from the build. |
| 112 | * |
| 113 | * The build server will copy the contents of DIST_DIR to somewhere and make it available. |
| 114 | */ |
Yigit Boyar | 7bfacb7 | 2017-03-02 14:27:41 -0800 | [diff] [blame] | 115 | if (ext.runningInBuildServer) { |
Yigit Boyar | 88c16ce | 2017-02-08 16:06:14 -0800 | [diff] [blame] | 116 | buildDir = new File(System.env.OUT_DIR + '/gradle/frameworks/support/build') |
| 117 | .getCanonicalFile() |
| 118 | project.ext.distDir = new File(System.env.DIST_DIR).getCanonicalFile() |
| 119 | |
| 120 | // the build server does not pass the build number so we infer it from the last folder of |
| 121 | // the dist path. |
| 122 | ext.buildNumber = project.ext.distDir.getName() |
| 123 | } else { |
| 124 | buildDir = file("${ext.supportRootFolder}/../../out/host/gradle/frameworks/support/build") |
| 125 | project.ext.distDir = new File("${ext.supportRootFolder}/../../out/dist") |
| 126 | } |
| 127 | subprojects { |
| 128 | // Change buildDir first so that all plugins pick up the new value. |
| 129 | project.buildDir = new File("$project.parent.buildDir/../$project.name/build") |
| 130 | } |
| 131 | ext.supportRepoOut = new File(buildDir, 'support_repo') |
| 132 | ext.testApkDistOut = ext.distDir |
Yigit Boyar | 7bfacb7 | 2017-03-02 14:27:41 -0800 | [diff] [blame] | 133 | ext.testResultsDistDir = new File(distDir, "host-test-reports") |
Yigit Boyar | 88c16ce | 2017-02-08 16:06:14 -0800 | [diff] [blame] | 134 | ext.docsDir = new File(buildDir, 'javadoc') |
| 135 | } |
| 136 | |
| 137 | def configureSubProjects() { |
| 138 | // lint every library |
| 139 | def lintTask = project.tasks.create("lint") |
| 140 | subprojects { |
| 141 | // Only modify Android projects. |
Yigit Boyar | 7bfacb7 | 2017-03-02 14:27:41 -0800 | [diff] [blame] | 142 | if (project.name.equals('doclava') || project.name.equals('jdiff')) { |
| 143 | // disable tests and return |
| 144 | project.tasks.whenTaskAdded { task -> |
| 145 | if (task instanceof org.gradle.api.tasks.testing.Test) { |
| 146 | task.enabled = false |
| 147 | } |
| 148 | } |
| 149 | return |
| 150 | } |
Yigit Boyar | 88c16ce | 2017-02-08 16:06:14 -0800 | [diff] [blame] | 151 | |
| 152 | // Current SDK is set in studioCompat.gradle. |
| 153 | project.ext.currentSdk = gradle.ext.currentSdk |
| 154 | apply plugin: 'maven' |
| 155 | |
| 156 | version = rootProject.ext.supportVersion |
| 157 | group = 'com.android.support' |
| 158 | |
| 159 | init.addMavenRepositories(repositories) |
| 160 | project.plugins.whenPluginAdded { plugin -> |
| 161 | def isAndroidLibrary = "com.android.build.gradle.LibraryPlugin" |
| 162 | .equals(plugin.class.name) |
| 163 | def isAndroidApp = "com.android.build.gradle.AppPlugin".equals(plugin.class.name) |
| 164 | def isJavaLibrary = "org.gradle.api.plugins.JavaPlugin".equals(plugin.class.name) |
| 165 | |
| 166 | if (isAndroidLibrary || isAndroidApp) { |
| 167 | project.android.buildToolsVersion = rootProject.buildToolsVersion |
| 168 | |
| 169 | // Enable code coverage for debug builds only if we are not running inside the IDE, |
| 170 | // since enabling coverage reports breaks the method parameter resolution in the IDE |
| 171 | // debugger. |
| 172 | project.android.buildTypes.debug.testCoverageEnabled = |
| 173 | !hasProperty('android.injected.invoked.from.ide') |
| 174 | |
| 175 | // Copy the class files in a jar to be later used to generate code coverage report |
| 176 | project.android.testVariants.all { v -> |
| 177 | // check if the variant has any source files |
| 178 | // and test coverage is enabled |
| 179 | if (v.buildType.testCoverageEnabled |
| 180 | && v.sourceSets.any { !it.java.sourceFiles.isEmpty() }) { |
| 181 | def jarifyTask = project.tasks.create( |
| 182 | name: "package${v.name.capitalize()}ClassFilesForCoverageReport", |
| 183 | type: Jar) { |
| 184 | from v.testedVariant.javaCompile.destinationDir |
| 185 | exclude "**/R.class" |
| 186 | exclude "**/R\$*.class" |
| 187 | exclude "**/BuildConfig.class" |
| 188 | destinationDir file(project.distDir) |
| 189 | archiveName "${project.archivesBaseName}-${v.baseName}-allclasses.jar" |
| 190 | } |
| 191 | def jacocoAntConfig = |
| 192 | project.configurations[JacocoPlugin.ANT_CONFIGURATION_NAME] |
| 193 | def jacocoAntArtifacts = jacocoAntConfig.resolvedConfiguration |
| 194 | .resolvedArtifacts |
| 195 | def version = jacocoAntArtifacts.find { "org.jacoco.ant".equals(it.name) } |
| 196 | .moduleVersion.id.version |
| 197 | def collectJacocoAntPackages = project.tasks.create( |
| 198 | name: "collectJacocoAntPackages", |
| 199 | type: Jar) { |
| 200 | from(jacocoAntArtifacts.collect { zipTree(it.getFile()) }) { |
| 201 | // exclude all the signatures the jar might have |
| 202 | exclude "META-INF/*.SF" |
| 203 | exclude "META-INF/*.DSA" |
| 204 | exclude "META-INF/*.RSA" |
| 205 | } |
| 206 | destinationDir file(project.distDir) |
| 207 | archiveName "jacocoant-" + version + ".jar" |
| 208 | } |
| 209 | jarifyTask.dependsOn v.getJavaCompiler() |
| 210 | v.assemble.dependsOn jarifyTask, collectJacocoAntPackages |
| 211 | } |
| 212 | } |
| 213 | |
| 214 | // Enforce NewApi lint check as fatal. |
| 215 | project.android.lintOptions.check 'NewApi' |
| 216 | project.android.lintOptions.fatal 'NewApi' |
| 217 | lintTask.dependsOn project.lint |
| 218 | } |
| 219 | |
| 220 | if (isAndroidLibrary || isJavaLibrary) { |
| 221 | // Add library to the aggregate dependency report. |
| 222 | task allDeps(type: DependencyReportTask) {} |
| 223 | |
| 224 | // Create release and separate zip task for library. |
| 225 | task release(type: Upload) { |
| 226 | configuration = configurations.archives |
| 227 | repositories { |
| 228 | mavenDeployer { |
| 229 | repository(url: uri("$rootProject.ext.supportRepoOut")) |
| 230 | |
| 231 | // Disable unique names for SNAPSHOTS so they can be updated in place. |
| 232 | setUniqueVersion(false) |
| 233 | doLast { |
| 234 | // Remove any invalid maven-metadata.xml files that may have been |
| 235 | // created for SNAPSHOT versions that are *not* uniquely versioned. |
| 236 | pom*.each { pom -> |
| 237 | if (pom.version.endsWith('-SNAPSHOT')) { |
| 238 | final File artifactDir = new File( |
| 239 | rootProject.ext.supportRepoOut, |
| 240 | pom.groupId.replace('.', '/') |
| 241 | + '/' + pom.artifactId |
| 242 | + '/' + pom.version) |
| 243 | delete fileTree(dir: artifactDir, |
| 244 | include: 'maven-metadata.xml*') |
| 245 | } |
| 246 | } |
| 247 | } |
| 248 | } |
| 249 | } |
| 250 | } |
| 251 | |
| 252 | def deployer = release.repositories.mavenDeployer |
| 253 | deployer.pom*.whenConfigured { pom -> |
| 254 | pom.dependencies.findAll { dep -> |
| 255 | dep.groupId == 'com.android.support' && |
| 256 | dep.artifactId != 'support-annotations' |
| 257 | }*.type = 'aar' |
| 258 | } |
| 259 | |
| 260 | ext.versionDir = { |
| 261 | def groupDir = new File(rootProject.ext.supportRepoOut, |
| 262 | project.group.replace('.', '/')) |
| 263 | def artifactDir = new File(groupDir, archivesBaseName) |
| 264 | return new File(artifactDir, version) |
| 265 | } |
| 266 | |
| 267 | task generateSourceProps(dependsOn: createRepository) |
| 268 | generateSourceProps.doLast({ |
| 269 | def content = "Maven.GroupId=$deployer.pom.groupId\n" + |
| 270 | "Maven.ArtifactId=$deployer.pom.artifactId\n" + |
| 271 | "Maven.Version=$deployer.pom.version\n" + |
| 272 | "Extra.VendorDisplay=Android\n" + |
| 273 | "Extra.VendorId=android\n" + |
| 274 | "Pkg.Desc=$project.name\n" + |
| 275 | "Pkg.Revision=1\n" + |
| 276 | "Maven.Dependencies=" + |
| 277 | String.join(",", project.configurations.compile.allDependencies |
| 278 | .collect { |
| 279 | def p = parent.findProject(it.name) |
| 280 | return p ? "$p.group:$p.archivesBaseName:$p.version" : null |
| 281 | }.grep()) + |
| 282 | "\n" |
| 283 | Files.write(content, new File(versionDir(), 'source.properties'), |
| 284 | Charsets.UTF_8) |
| 285 | }) |
| 286 | |
Yigit Boyar | 88c16ce | 2017-02-08 16:06:14 -0800 | [diff] [blame] | 287 | // Before the upload, make sure the repo is ready. |
| 288 | release.dependsOn rootProject.tasks.prepareRepo |
| 289 | |
| 290 | // Make the mainupload depend on this one. |
| 291 | mainUpload.dependsOn release |
| 292 | } |
| 293 | } |
| 294 | |
Yigit Boyar | 7bfacb7 | 2017-03-02 14:27:41 -0800 | [diff] [blame] | 295 | // Copy instrumentation test APKs and app APKs into the dist dir |
| 296 | // For test apks, they are uploaded only if we have java test sources. |
| 297 | // For regular app apks, they are uploaded only if they have java sources. |
| 298 | project.tasks.whenTaskAdded { task -> |
| 299 | if (task.name.startsWith("packageDebug")) { |
| 300 | def testApk = task.name.contains("AndroidTest") |
| 301 | task.doLast { |
| 302 | def source = testApk ? project.android.sourceSets.androidTest |
| 303 | : project.android.sourceSets.main |
| 304 | if (task.hasProperty("outputFile") && !source.java.sourceFiles.isEmpty()) { |
| 305 | copy { |
| 306 | from(task.outputFile) |
| 307 | into(rootProject.ext.testApkDistOut) |
| 308 | rename { String fileName -> |
| 309 | // multiple modules may have the same name so prefix the name with |
| 310 | // the module's path to ensure it is unique. |
| 311 | // e.g. palette-v7-debug-androidTest.apk becomes |
| 312 | // support-palette-v7_palette-v7-debug-androidTest.apk |
| 313 | "${project.getPath().replace(':', '-').substring(1)}_${fileName}" |
| 314 | } |
| 315 | } |
| 316 | } |
| 317 | } |
| 318 | } |
| 319 | } |
| 320 | |
| 321 | // copy host side test results to DIST |
| 322 | project.tasks.whenTaskAdded { task -> |
| 323 | if (task instanceof org.gradle.api.tasks.testing.Test) { |
| 324 | def junitReport = task.reports.junitXml |
| 325 | if (junitReport.enabled) { |
| 326 | def zipTask = project.tasks.create(name : "zipResultsOf${task.name.capitalize()}", type : Zip) { |
| 327 | destinationDir(testResultsDistDir) |
Yigit Boyar | 278676d | 2017-03-10 15:29:11 -0800 | [diff] [blame] | 328 | // first one is always :, drop it. |
| 329 | archiveName("${project.getPath().split(":").join("_").substring(1)}.zip") |
Yigit Boyar | 7bfacb7 | 2017-03-02 14:27:41 -0800 | [diff] [blame] | 330 | } |
| 331 | if (project.rootProject.ext.runningInBuildServer) { |
| 332 | task.ignoreFailures = true |
| 333 | } |
| 334 | task.finalizedBy zipTask |
| 335 | task.doFirst { |
| 336 | zipTask.from(junitReport.destination) |
| 337 | } |
| 338 | } |
| 339 | } |
| 340 | } |
| 341 | |
Yigit Boyar | 88c16ce | 2017-02-08 16:06:14 -0800 | [diff] [blame] | 342 | project.afterEvaluate { |
| 343 | // The archivesBaseName isn't available initially, so set it now |
| 344 | def createZipTask = project.tasks.findByName("createSeparateZip") |
| 345 | if (createZipTask != null) { |
| 346 | createZipTask.appendix = archivesBaseName |
| 347 | createZipTask.from versionDir() |
| 348 | } |
Yigit Boyar | 88c16ce | 2017-02-08 16:06:14 -0800 | [diff] [blame] | 349 | } |
| 350 | |
| 351 | project.afterEvaluate { p -> |
| 352 | // remove dependency on the test so that we still get coverage even if some tests fail |
| 353 | p.tasks.findAll { it instanceof JacocoReportTask }.each { task -> |
| 354 | def toBeRemoved = new ArrayList() |
| 355 | def dependencyList = task.taskDependencies.values |
| 356 | dependencyList.each { dep -> |
| 357 | if (dep instanceof String) { |
| 358 | def t = tasks.findByName(dep) |
| 359 | if (t instanceof DeviceProviderInstrumentTestTask) { |
| 360 | toBeRemoved.add(dep) |
| 361 | task.mustRunAfter(t) |
| 362 | } |
| 363 | } |
| 364 | } |
| 365 | toBeRemoved.each { dep -> |
| 366 | dependencyList.remove(dep) |
| 367 | } |
| 368 | } |
| 369 | } |
| 370 | } |
| 371 | } |
| 372 | |
| 373 | def setupRelease() { |
| 374 | apply from: "${ext.supportRootFolder}/buildSrc/release.gradle" |
| 375 | } |
| 376 | |
| 377 | ext.init.addMavenRepositories = this.&addMavenRepositories |
| 378 | ext.init.enableDoclavaAndJDiff = this.&enableDoclavaAndJDiff |
| 379 | ext.init.setSdkInLocalPropertiesFile = this.&setSdkInLocalPropertiesFile |
| 380 | ext.init.setupRepoOutAndBuildNumber = this.&setupRepoOutAndBuildNumber |
| 381 | ext.init.setupRelease = this.&setupRelease |
| 382 | ext.init.loadDefaultVersions = this.&loadDefaultVersions |
| 383 | ext.init.configureSubProjects = this.&configureSubProjects |