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