1import com.android.build.gradle.internal.coverage.JacocoReportTask 2import com.android.build.gradle.internal.tasks.DeviceProviderInstrumentTestTask 3 4buildscript { 5 repositories { 6 maven { url '../../prebuilts/gradle-plugin' } 7 maven { url '../../prebuilts/tools/common/m2/repository' } 8 maven { url '../../prebuilts/tools/common/m2/internal' } 9 maven { url "../../prebuilts/maven_repo/android" } 10 } 11 dependencies { 12 classpath 'com.android.tools.build:gradle:2.1.2' 13 } 14} 15 16ext.supportVersion = '24.0.1' 17ext.extraVersion = 34 18ext.supportRepoOut = '' 19ext.buildToolsVersion = '23.0.2' 20ext.buildNumber = Integer.toString(ext.extraVersion) 21 22/* 23 * With the build server you are given two env variables. 24 * The OUT_DIR is a temporary directory you can use to put things during the build. 25 * The DIST_DIR is where you want to save things from the build. 26 * 27 * The build server will copy the contents of DIST_DIR to somewhere and make it available. 28 */ 29if (System.env.DIST_DIR != null && System.env.OUT_DIR != null) { 30 buildDir = new File(System.env.OUT_DIR + '/gradle/frameworks/support/build').getCanonicalFile() 31 project.ext.distDir = new File(System.env.DIST_DIR).getCanonicalFile() 32 33 // the build server does not pass the build number so we infer it from the last folder of the dist path. 34 ext.buildNumber = project.ext.distDir.getName() 35} else { 36 buildDir = file('../../out/host/gradle/frameworks/support/build') 37 project.ext.distDir = file('../../out/dist') 38} 39 40ext.supportRepoOut = new File(buildDir, 'support_repo') 41ext.testApkDistOut = ext.distDir 42 43// Main task called by the build server. 44task(createArchive) << { 45} 46 47 48// upload anchor for subprojects to upload their artifacts 49// to the local repo. 50task(mainUpload) << { 51} 52 53// repository creation task 54task createRepository(type: Zip, dependsOn: mainUpload) { 55 from project.ext.supportRepoOut 56 destinationDir project.ext.distDir 57 into 'm2repository' 58 baseName = String.format("sdk-repo-linux-m2repository-%s", project.ext.buildNumber) 59} 60createArchive.dependsOn createRepository 61 62// prepare repository with older versions 63task unzipRepo(type: Copy) { 64 from "$rootDir/../../prebuilts/maven_repo/android" 65 into project.ext.supportRepoOut 66} 67 68unzipRepo.doFirst { 69 project.ext.supportRepoOut.deleteDir() 70 project.ext.supportRepoOut.mkdirs() 71} 72 73// anchor for prepare repo. This is post unzip + sourceProp. 74task(prepareRepo) << { 75} 76 77 78import android.support.build.ApiModule 79import com.google.common.io.Files 80import com.google.common.base.Charsets 81 82task(createXml) << { 83 def repoArchive = createRepository.archivePath 84 def repoArchiveName = createRepository.archiveName 85 def size = repoArchive.length() 86 def sha1 = getSha1(repoArchive) 87 88 def xml = 89"<sdk:sdk-addon xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:sdk=\"http://schemas.android.com/sdk/android/addon/6\">\n\ 90 <sdk:extra>\n\ 91 <sdk:revision>\n\ 92 <sdk:major>${project.ext.extraVersion}</sdk:major>\n\ 93 </sdk:revision>\n\ 94 <sdk:vendor-display>Android</sdk:vendor-display>\n\ 95 <sdk:vendor-id>android</sdk:vendor-id>\n\ 96 <sdk:name-display>Local Maven repository for Support Libraries</sdk:name-display>\n\ 97 <sdk:path>m2repository</sdk:path>\n\ 98 <sdk:archives>\n\ 99 <sdk:archive>\n\ 100 <sdk:size>${size}</sdk:size>\n\ 101 <sdk:checksum type=\"sha1\">${sha1}</sdk:checksum>\n\ 102 <sdk:url>${repoArchiveName}</sdk:url>\n\ 103 </sdk:archive>\n\ 104 </sdk:archives>\n\ 105 </sdk:extra>\n\ 106</sdk:sdk-addon>" 107 108 Files.write(xml, new File(project.ext.distDir, 'repo-extras.xml'), Charsets.UTF_8) 109} 110createArchive.dependsOn createXml 111 112task(createSourceProp) << { 113 def sourceProp = 114"Extra.VendorDisplay=Android\n\ 115Extra.Path=m2repository\n\ 116Archive.Arch=ANY\n\ 117Extra.NameDisplay=Android Support Repository\n\ 118Archive.Os=ANY\n\ 119Pkg.Desc=Local Maven repository for Support Libraries\n\ 120Pkg.Revision=${project.ext.extraVersion}.0.0\n\ 121Extra.VendorId=android" 122 123 Files.write(sourceProp, new File(project.ext.supportRepoOut, 'source.properties'), Charsets.UTF_8) 124} 125createSourceProp.dependsOn unzipRepo 126prepareRepo.dependsOn createSourceProp 127 128import com.google.common.hash.HashCode 129import com.google.common.hash.HashFunction 130import com.google.common.hash.Hashing 131import java.nio.charset.Charset 132 133def getSha1(File inputFile) { 134 HashFunction hashFunction = Hashing.sha1() 135 HashCode hashCode = hashFunction.hashString(inputFile.getAbsolutePath(), Charset.forName("UTF-8")) 136 return hashCode.toString() 137} 138 139def createApiSourceSets(Project subProject, List<ApiModule> apiModules) { 140 subProject.ext._apiModules = apiModules 141 subProject.ext.allSS = [] 142 if (gradle.ext.studioCompat.enableApiModules) { 143 // nothing to do, they are all modules 144 return 145 } 146 // create a jar task for the api specific internal implementations 147 def internalJar = subProject.tasks.create(name: "internalJar", type: Jar) { 148 baseName "internal_impl" 149 } 150 apiModules.each { ApiModule apiModule -> 151 apiModule.sourceSet = createApiSourceset(subProject, apiModule.folderName, apiModule.folderName, 152 apiModule.apiForSourceSet.toString(), apiModule.prev == null ? null : apiModule.prev.sourceSet) 153 subProject.ext.allSS.add(apiModule.sourceSet) 154 } 155 subProject.android.libraryVariants.all { variant -> 156 variant.javaCompile.dependsOn internalJar 157 } 158} 159 160def createApiSourceset(Project subProject, String name, String folder, String apiLevel, 161 SourceSet previousSource) { 162 def sourceSet = subProject.sourceSets.create(name) 163 sourceSet.java.srcDirs = [folder] 164 165 def configName = sourceSet.getCompileConfigurationName() 166 167 subProject.getDependencies().add(configName, getAndroidPrebuilt(apiLevel)) 168 if (previousSource != null) { 169 setupDependencies(subProject, configName, previousSource) 170 } 171 subProject.ext.allSS.add(sourceSet) 172 subProject.tasks.internalJar.from sourceSet.output 173 return sourceSet 174} 175 176def setApiModuleDependencies(Project subProject, DependencyHandler handler, List extraDeps) { 177 if (gradle.ext.studioCompat.enableApiModules) { 178 subProject.android.enforceUniquePackageName=false 179 // add dependency on the latest module 180 handler.compile(project(subProject.ext._apiModules.last().moduleName)) 181 } else { 182 handler.compile(files(subProject.tasks.internalJar.archivePath)) 183 def firstModule = subProject.ext._apiModules[0] 184 extraDeps.each { dep -> 185 handler."${firstModule.folderName}Compile"(project(dep)) 186 handler.compile(project(dep)) 187 } 188 189 } 190} 191 192def setupDependencies(Project subProject, String configName, SourceSet previousSourceSet) { 193 subProject.getDependencies().add(configName, previousSourceSet.output) 194 subProject.getDependencies().add(configName, previousSourceSet.compileClasspath) 195} 196 197subprojects { 198 // Change buildDir first so that all plugins pick up the new value. 199 project.buildDir = project.file("$project.parent.buildDir/../$project.name/build") 200 // current SDK is set in studioCompat.gradle 201 project.ext.currentSdk = gradle.ext.currentSdk 202 apply plugin: 'maven' 203 project.ext.createApiSourceSets = this.&createApiSourceset 204 project.ext.setApiModuleDependencies = this.&setApiModuleDependencies 205 206 207 version = rootProject.ext.supportVersion 208 group = 'com.android.support' 209 210 repositories { 211 maven { url "${project.parent.projectDir}/../../prebuilts/tools/common/m2/repository" } 212 maven { url "${project.parent.projectDir}/../../prebuilts/tools/common/m2/internal" } 213 maven { url "${project.parent.projectDir}/../../prebuilts/maven_repo/android" } 214 } 215 216 task release(type: Upload) { 217 configuration = configurations.archives 218 repositories { 219 mavenDeployer { 220 repository(url: uri("$rootProject.ext.supportRepoOut")) 221 222 // Disable unique names for SNAPSHOTS so they can be updated in place. 223 setUniqueVersion(false) 224 doLast { 225 // Remove any invalid maven-metadata.xml files that may have been created 226 // for SNAPSHOT versions that are *not* uniquely versioned. 227 pom*.each { pom -> 228 if (pom.version.endsWith('-SNAPSHOT')) { 229 final File artifactDir = new File(rootProject.ext.supportRepoOut, 230 pom.groupId.replace('.', '/') 231 + '/' + pom.artifactId 232 + '/' + pom.version) 233 delete fileTree(dir: artifactDir, include: 'maven-metadata.xml*') 234 } 235 } 236 } 237 } 238 } 239 } 240 241 def deployer = release.repositories.mavenDeployer 242 deployer.pom*.whenConfigured { pom -> 243 pom.dependencies.findAll {dep -> dep.groupId == 'com.android.support' && dep.artifactId != 'support-annotations' }*.type = 'aar' 244 } 245 246 // before the upload, make sure the repo is ready. 247 release.dependsOn rootProject.tasks.prepareRepo 248 // make the mainupload depend on this one. 249 mainUpload.dependsOn release 250 251 project.plugins.whenPluginAdded { plugin -> 252 if ("com.android.build.gradle.LibraryPlugin".equals(plugin.class.name)) { 253 project.android.buildToolsVersion = rootProject.buildToolsVersion 254 // enable code coverage for debug builds only if we are not running inside the IDE 255 // enabling coverage reports breaks the method parameter resolution in the IDE debugger 256 project.android.buildTypes.debug.testCoverageEnabled = !hasProperty('android.injected.invoked.from.ide') 257 } 258 } 259 260 // Copy instrumentation test APK into the dist dir 261 project.afterEvaluate { 262 def assembleTestTask = project.tasks.findByPath('assembleAndroidTest') 263 if (assembleTestTask != null) { 264 assembleTestTask.doLast { 265 // If the project actually has some instrumentation tests, copy its APK 266 if (!project.android.sourceSets.androidTest.java.sourceFiles.isEmpty()) { 267 def pkgTask = project.tasks.findByPath('packageDebugAndroidTest') 268 copy { 269 from(pkgTask.outputFile) 270 into(rootProject.ext.testApkDistOut) 271 } 272 } 273 } 274 } 275 } 276 277 project.afterEvaluate { p -> 278 // remove dependency on the test so that we still get coverage even if some tests fail 279 p.tasks.findAll { it instanceof JacocoReportTask}.each { task -> 280 def toBeRemoved = new ArrayList() 281 def dependencyList = task.taskDependencies.values 282 dependencyList.each { dep -> 283 if (dep instanceof String) { 284 def t = tasks.findByName(dep) 285 if (t instanceof DeviceProviderInstrumentTestTask) { 286 toBeRemoved.add(dep) 287 task.mustRunAfter(t) 288 } 289 } 290 } 291 toBeRemoved.each { dep -> 292 dependencyList.remove(dep) 293 } 294 } 295 } 296} 297 298project.gradle.buildFinished { buildResult -> 299 if (buildResult.getFailure() != null) { 300 println() 301 println 'Build failed. Possible causes include:' 302 println ' 1) Bad codes' 303 println ' 2) Out of date prebuilts in prebuilts/sdk' 304 println ' 3) Need to update the compileSdkVersion in a library\'s build.gradle' 305 println() 306 } 307} 308 309FileCollection getAndroidPrebuilt(String apiLevel) { 310 files("$rootDir/../../prebuilts/sdk/$apiLevel/android.jar") 311} 312