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 17import com.android.build.gradle.internal.coverage.JacocoPlugin 18import com.android.build.gradle.internal.coverage.JacocoReportTask 19import com.android.build.gradle.internal.tasks.DeviceProviderInstrumentTestTask 20import com.google.common.base.Charsets 21import com.google.common.io.Files 22 23import org.gradle.api.logging.configuration.ShowStacktrace 24 25def supportRoot = ext.supportRootFolder 26if (supportRoot == null) { 27 throw new RuntimeException("variable supportRootFolder is not set. you must set it before" + 28 " including this script") 29} 30def init = new Properties() 31ext.init = init 32ext.init.debugKeystore = file("${supportRoot}/development/keystore/debug.keystore") 33 34ext.runningInBuildServer = System.env.DIST_DIR != null && System.env.OUT_DIR != null 35 36apply from: "${supportRoot}/buildSrc/dependencies.gradle" 37ext.docs = [:] 38ext.docs.offline = rootProject.getProperties().containsKey("offlineDocs") 39ext.docs.dac = [ 40 libraryroot: "android/support", 41 dataname: "SUPPORT_DATA" 42] 43 44def loadDefaultVersions() { 45 apply from: "${supportRootFolder}/buildSrc/versions.gradle" 46} 47 48def enableDoclavaAndJDiff(p) { 49 p.configurations { 50 doclava 51 jdiff 52 } 53 54 p.dependencies { 55 doclava project(':doclava') 56 jdiff project(':jdiff') 57 jdiff libs.xml_parser_apis 58 jdiff libs.xerces_impl 59 } 60 apply from: "${ext.supportRootFolder}/buildSrc/diff_and_docs.gradle" 61} 62 63def setSdkInLocalPropertiesFile() { 64 final String osName = System.getProperty("os.name").toLowerCase(); 65 final boolean isMacOsX = 66 osName.contains("mac os x") || osName.contains("darwin") || osName.contains("osx"); 67 final String platform = isMacOsX ? 'darwin' : 'linux' 68 System.setProperty('android.dir', "${supportRootFolder}/../../") 69 ext.buildToolsVersion = '26.0.0' 70 final String fullSdkPath = "${repos.prebuiltsRoot}/fullsdk-${platform}" 71 if (file(fullSdkPath).exists()) { 72 gradle.ext.currentSdk = 26 73 project.ext.androidJar = 74 files("${fullSdkPath}/platforms/android-${gradle.currentSdk}/android.jar") 75 project.ext.androidSrcJar = 76 file("${fullSdkPath}/platforms/android-${gradle.currentSdk}/android-stubs-src.jar") 77 project.ext.androidApiTxt = null 78 System.setProperty('android.home', "${repos.prebuiltsRoot}/fullsdk-${platform}") 79 File props = file("local.properties") 80 props.write "sdk.dir=${fullSdkPath}" 81 ext.usingFullSdk = true 82 } else { 83 gradle.ext.currentSdk = 'current' 84 project.ext.androidJar = files("${repos.prebuiltsRoot}/sdk/current/android.jar") 85 project.ext.androidSrcJar = null 86 project.ext.androidApiTxt = file("${repos.prebuiltsRoot}/sdk/api/26.txt") 87 File props = file("local.properties") 88 props.write "android.dir=../../" 89 ext.usingFullSdk = false 90 } 91} 92 93def setupRepoOutAndBuildNumber() { 94 ext.supportRepoOut = '' 95 ext.buildNumber = Integer.toString(ext.extraVersion) 96 97 /* 98 * With the build server you are given two env variables. 99 * The OUT_DIR is a temporary directory you can use to put things during the build. 100 * The DIST_DIR is where you want to save things from the build. 101 * 102 * The build server will copy the contents of DIST_DIR to somewhere and make it available. 103 */ 104 if (ext.runningInBuildServer) { 105 buildDir = new File(System.env.OUT_DIR + '/gradle/frameworks/support/build') 106 .getCanonicalFile() 107 project.ext.distDir = new File(System.env.DIST_DIR).getCanonicalFile() 108 109 // the build server does not pass the build number so we infer it from the last folder of 110 // the dist path. 111 ext.buildNumber = project.ext.distDir.getName() 112 113 // the build server should always print out full stack traces for any failures. 114 gradle.startParameter.showStacktrace = ShowStacktrace.ALWAYS 115 } else { 116 buildDir = file("${ext.supportRootFolder}/../../out/host/gradle/frameworks/support/build") 117 project.ext.distDir = new File("${ext.supportRootFolder}/../../out/dist") 118 } 119 subprojects { 120 // Change buildDir first so that all plugins pick up the new value. 121 project.buildDir = new File("$project.parent.buildDir/../$project.name/build") 122 } 123 ext.supportRepoOut = new File(buildDir, 'support_repo') 124 ext.testApkDistOut = ext.distDir 125 ext.testResultsDistDir = new File(distDir, "host-test-reports") 126 ext.docsDir = new File(buildDir, 'javadoc') 127} 128 129def configureSubProjects() { 130 // lint every library 131 def lintTask = project.tasks.create("lint") 132 subprojects { 133 repos.addMavenRepositories(repositories) 134 135 // Only modify Android projects. 136 if (project.name.equals('doclava') 137 || project.name.equals('jdiff') 138 || project.name.equals('support-testutils') 139 || project.name.equals('noto-emoji-compat')) { 140 // disable tests and return 141 project.tasks.whenTaskAdded { task -> 142 if (task instanceof org.gradle.api.tasks.testing.Test) { 143 task.enabled = false 144 } 145 } 146 return 147 } 148 149 // Current SDK is set in studioCompat.gradle. 150 project.ext.currentSdk = gradle.ext.currentSdk 151 apply plugin: 'maven' 152 153 version = rootProject.ext.supportVersion 154 group = 'com.android.support' 155 156 project.plugins.whenPluginAdded { plugin -> 157 def isAndroidLibrary = "com.android.build.gradle.LibraryPlugin" 158 .equals(plugin.class.name) 159 def isAndroidApp = "com.android.build.gradle.AppPlugin".equals(plugin.class.name) 160 def isJavaLibrary = "org.gradle.api.plugins.JavaPlugin".equals(plugin.class.name) 161 162 if (isAndroidLibrary || isAndroidApp) { 163 project.android.buildToolsVersion = rootProject.buildToolsVersion 164 165 // Enable code coverage for debug builds only if we are not running inside the IDE, 166 // since enabling coverage reports breaks the method parameter resolution in the IDE 167 // debugger. 168 project.android.buildTypes.debug.testCoverageEnabled = 169 !project.hasProperty('android.injected.invoked.from.ide') 170 171 // Copy the class files in a jar to be later used to generate code coverage report 172 project.android.testVariants.all { v -> 173 // check if the variant has any source files 174 // and test coverage is enabled 175 if (v.buildType.testCoverageEnabled 176 && v.sourceSets.any { !it.java.sourceFiles.isEmpty() }) { 177 def jarifyTask = project.tasks.create( 178 name: "package${v.name.capitalize()}ClassFilesForCoverageReport", 179 type: Jar) { 180 from v.testedVariant.javaCompile.destinationDir 181 exclude "**/R.class" 182 exclude "**/R\$*.class" 183 exclude "**/BuildConfig.class" 184 destinationDir file(project.distDir) 185 archiveName "${project.archivesBaseName}-${v.baseName}-allclasses.jar" 186 } 187 def jacocoAntConfig = 188 project.configurations[JacocoPlugin.ANT_CONFIGURATION_NAME] 189 def jacocoAntArtifacts = jacocoAntConfig.resolvedConfiguration 190 .resolvedArtifacts 191 def version = jacocoAntArtifacts.find { "org.jacoco.ant".equals(it.name) } 192 .moduleVersion.id.version 193 def collectJacocoAntPackages = project.tasks.create( 194 name: "collectJacocoAntPackages", 195 type: Jar) { 196 from(jacocoAntArtifacts.collect { zipTree(it.getFile()) }) { 197 // exclude all the signatures the jar might have 198 exclude "META-INF/*.SF" 199 exclude "META-INF/*.DSA" 200 exclude "META-INF/*.RSA" 201 } 202 destinationDir file(project.distDir) 203 archiveName "jacocoant-" + version + ".jar" 204 } 205 jarifyTask.dependsOn v.getJavaCompiler() 206 v.assemble.dependsOn jarifyTask, collectJacocoAntPackages 207 } 208 } 209 210 // Enforce NewApi lint check as fatal. 211 project.android.lintOptions.check 'NewApi' 212 project.android.lintOptions.fatal 'NewApi' 213 lintTask.dependsOn project.lint 214 } 215 216 if (isAndroidLibrary || isJavaLibrary) { 217 // Add library to the aggregate dependency report. 218 task allDeps(type: DependencyReportTask) {} 219 220 project.afterEvaluate { 221 Upload uploadTask = (Upload) project.tasks.uploadArchives; 222 uploadTask.repositories.mavenDeployer { 223 // Disable unique names for SNAPSHOTS so they can be updated in place. 224 setUniqueVersion(false) 225 } 226 uploadTask.doLast { 227 // Remove any invalid maven-metadata.xml files that may have been 228 // created for SNAPSHOT versions that are *not* uniquely versioned. 229 repositories.mavenDeployer.pom*.each { pom -> 230 if (pom.version.endsWith('-SNAPSHOT')) { 231 final File artifactDir = new File( 232 rootProject.ext.supportRepoOut, 233 pom.groupId.replace('.', '/') 234 + '/' + pom.artifactId 235 + '/' + pom.version) 236 delete fileTree(dir: artifactDir, 237 include: 'maven-metadata.xml*') 238 } 239 } 240 } 241 242 uploadTask.repositories.mavenDeployer.pom*.whenConfigured { pom -> 243 pom.dependencies.findAll { dep -> 244 dep.groupId == 'com.android.support' && 245 dep.artifactId != 'support-annotations' 246 }*.type = 'aar' 247 } 248 249 // Before the upload, make sure the repo is ready. 250 uploadTask.dependsOn rootProject.tasks.prepareRepo 251 252 // Make the mainupload depend on this one. 253 mainUpload.dependsOn uploadTask 254 } 255 256 } 257 } 258 259 // Copy instrumentation test APKs and app APKs into the dist dir 260 // For test apks, they are uploaded only if we have java test sources. 261 // For regular app apks, they are uploaded only if they have java sources. 262 project.tasks.whenTaskAdded { task -> 263 if (task.name.startsWith("packageDebug")) { 264 def testApk = task.name.contains("AndroidTest") 265 task.doLast { 266 def source = testApk ? project.android.sourceSets.androidTest 267 : project.android.sourceSets.main 268 if (task.hasProperty("outputFile") && !source.java.sourceFiles.isEmpty()) { 269 copy { 270 from(task.outputFile) 271 into(rootProject.ext.testApkDistOut) 272 rename { String fileName -> 273 // multiple modules may have the same name so prefix the name with 274 // the module's path to ensure it is unique. 275 // e.g. palette-v7-debug-androidTest.apk becomes 276 // support-palette-v7_palette-v7-debug-androidTest.apk 277 "${project.getPath().replace(':', '-').substring(1)}_${fileName}" 278 } 279 } 280 } 281 } 282 } 283 } 284 285 // copy host side test results to DIST 286 project.tasks.whenTaskAdded { task -> 287 if (task instanceof org.gradle.api.tasks.testing.Test) { 288 def junitReport = task.reports.junitXml 289 if (junitReport.enabled) { 290 def zipTask = project.tasks.create(name : "zipResultsOf${task.name.capitalize()}", type : Zip) { 291 destinationDir(testResultsDistDir) 292 // first one is always :, drop it. 293 archiveName("${project.getPath().split(":").join("_").substring(1)}.zip") 294 } 295 if (project.rootProject.ext.runningInBuildServer) { 296 task.ignoreFailures = true 297 } 298 task.finalizedBy zipTask 299 task.doFirst { 300 zipTask.from(junitReport.destination) 301 } 302 } 303 } 304 } 305 306 project.afterEvaluate { 307 // The archivesBaseName isn't available initially, so set it now 308 def createZipTask = project.tasks.findByName("createSeparateZip") 309 if (createZipTask != null) { 310 createZipTask.appendix = archivesBaseName 311 createZipTask.from versionDir() 312 } 313 } 314 315 project.afterEvaluate { p -> 316 // remove dependency on the test so that we still get coverage even if some tests fail 317 p.tasks.findAll { it instanceof JacocoReportTask }.each { task -> 318 def toBeRemoved = new ArrayList() 319 def dependencyList = task.taskDependencies.values 320 dependencyList.each { dep -> 321 if (dep instanceof String) { 322 def t = tasks.findByName(dep) 323 if (t instanceof DeviceProviderInstrumentTestTask) { 324 toBeRemoved.add(dep) 325 task.mustRunAfter(t) 326 } 327 } 328 } 329 toBeRemoved.each { dep -> 330 dependencyList.remove(dep) 331 } 332 } 333 } 334 } 335} 336 337def setupRelease() { 338 apply from: "${ext.supportRootFolder}/buildSrc/release.gradle" 339} 340 341ext.init.enableDoclavaAndJDiff = this.&enableDoclavaAndJDiff 342ext.init.setSdkInLocalPropertiesFile = this.&setSdkInLocalPropertiesFile 343ext.init.setupRepoOutAndBuildNumber = this.&setupRepoOutAndBuildNumber 344ext.init.setupRelease = this.&setupRelease 345ext.init.loadDefaultVersions = this.&loadDefaultVersions 346ext.init.configureSubProjects = this.&configureSubProjects