import com.android.build.gradle.internal.coverage.JacocoReportTask
import com.android.build.gradle.internal.tasks.DeviceProviderInstrumentTestTask
buildscript {
repositories {
maven { url '../../prebuilts/gradle-plugin' }
maven { url '../../prebuilts/tools/common/m2/repository' }
maven { url '../../prebuilts/tools/common/m2/internal' }
maven { url "../../prebuilts/maven_repo/android" }
}
dependencies {
classpath 'com.android.tools.build:gradle:2.1.2'
}
}
ext.supportVersion = '24.0.1'
ext.extraVersion = 34
ext.supportRepoOut = ''
ext.buildToolsVersion = '23.0.2'
ext.buildNumber = Integer.toString(ext.extraVersion)
/*
* With the build server you are given two env variables.
* The OUT_DIR is a temporary directory you can use to put things during the build.
* The DIST_DIR is where you want to save things from the build.
*
* The build server will copy the contents of DIST_DIR to somewhere and make it available.
*/
if (System.env.DIST_DIR != null && System.env.OUT_DIR != null) {
buildDir = new File(System.env.OUT_DIR + '/gradle/frameworks/support/build').getCanonicalFile()
project.ext.distDir = new File(System.env.DIST_DIR).getCanonicalFile()
// the build server does not pass the build number so we infer it from the last folder of the dist path.
ext.buildNumber = project.ext.distDir.getName()
} else {
buildDir = file('../../out/host/gradle/frameworks/support/build')
project.ext.distDir = file('../../out/dist')
}
ext.supportRepoOut = new File(buildDir, 'support_repo')
ext.testApkDistOut = ext.distDir
// Main task called by the build server.
task(createArchive) << {
}
// upload anchor for subprojects to upload their artifacts
// to the local repo.
task(mainUpload) << {
}
// repository creation task
task createRepository(type: Zip, dependsOn: mainUpload) {
from project.ext.supportRepoOut
destinationDir project.ext.distDir
into 'm2repository'
baseName = String.format("sdk-repo-linux-m2repository-%s", project.ext.buildNumber)
}
createArchive.dependsOn createRepository
// prepare repository with older versions
task unzipRepo(type: Copy) {
from "$rootDir/../../prebuilts/maven_repo/android"
into project.ext.supportRepoOut
}
unzipRepo.doFirst {
project.ext.supportRepoOut.deleteDir()
project.ext.supportRepoOut.mkdirs()
}
// anchor for prepare repo. This is post unzip + sourceProp.
task(prepareRepo) << {
}
import android.support.build.ApiModule
import com.google.common.io.Files
import com.google.common.base.Charsets
task(createXml) << {
def repoArchive = createRepository.archivePath
def repoArchiveName = createRepository.archiveName
def size = repoArchive.length()
def sha1 = getSha1(repoArchive)
def xml =
"<sdk:sdk-addon xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:sdk=\"http://schemas.android.com/sdk/android/addon/6\">\n\
<sdk:extra>\n\
<sdk:revision>\n\
<sdk:major>${project.ext.extraVersion}</sdk:major>\n\
</sdk:revision>\n\
<sdk:vendor-display>Android</sdk:vendor-display>\n\
<sdk:vendor-id>android</sdk:vendor-id>\n\
<sdk:name-display>Local Maven repository for Support Libraries</sdk:name-display>\n\
<sdk:path>m2repository</sdk:path>\n\
<sdk:archives>\n\
<sdk:archive>\n\
<sdk:size>${size}</sdk:size>\n\
<sdk:checksum type=\"sha1\">${sha1}</sdk:checksum>\n\
<sdk:url>${repoArchiveName}</sdk:url>\n\
</sdk:archive>\n\
</sdk:archives>\n\
</sdk:extra>\n\
</sdk:sdk-addon>"
Files.write(xml, new File(project.ext.distDir, 'repo-extras.xml'), Charsets.UTF_8)
}
createArchive.dependsOn createXml
task(createSourceProp) << {
def sourceProp =
"Extra.VendorDisplay=Android\n\
Extra.Path=m2repository\n\
Archive.Arch=ANY\n\
Extra.NameDisplay=Android Support Repository\n\
Archive.Os=ANY\n\
Pkg.Desc=Local Maven repository for Support Libraries\n\
Pkg.Revision=${project.ext.extraVersion}.0.0\n\
Extra.VendorId=android"
Files.write(sourceProp, new File(project.ext.supportRepoOut, 'source.properties'), Charsets.UTF_8)
}
createSourceProp.dependsOn unzipRepo
prepareRepo.dependsOn createSourceProp
import com.google.common.hash.HashCode
import com.google.common.hash.HashFunction
import com.google.common.hash.Hashing
import java.nio.charset.Charset
def getSha1(File inputFile) {
HashFunction hashFunction = Hashing.sha1()
HashCode hashCode = hashFunction.hashString(inputFile.getAbsolutePath(), Charset.forName("UTF-8"))
return hashCode.toString()
}
def createApiSourceSets(Project subProject, List<ApiModule> apiModules) {
subProject.ext._apiModules = apiModules
subProject.ext.allSS = []
if (gradle.ext.studioCompat.enableApiModules) {
// nothing to do, they are all modules
return
}
// create a jar task for the api specific internal implementations
def internalJar = subProject.tasks.create(name: "internalJar", type: Jar) {
baseName "internal_impl"
}
apiModules.each { ApiModule apiModule ->
apiModule.sourceSet = createApiSourceset(subProject, apiModule.folderName, apiModule.folderName,
apiModule.apiForSourceSet.toString(), apiModule.prev == null ? null : apiModule.prev.sourceSet)
subProject.ext.allSS.add(apiModule.sourceSet)
}
subProject.android.libraryVariants.all { variant ->
variant.javaCompile.dependsOn internalJar
}
}
def createApiSourceset(Project subProject, String name, String folder, String apiLevel,
SourceSet previousSource) {
def sourceSet = subProject.sourceSets.create(name)
sourceSet.java.srcDirs = [folder]
def configName = sourceSet.getCompileConfigurationName()
subProject.getDependencies().add(configName, getAndroidPrebuilt(apiLevel))
if (previousSource != null) {
setupDependencies(subProject, configName, previousSource)
}
subProject.ext.allSS.add(sourceSet)
subProject.tasks.internalJar.from sourceSet.output
return sourceSet
}
def setApiModuleDependencies(Project subProject, DependencyHandler handler, List extraDeps) {
if (gradle.ext.studioCompat.enableApiModules) {
subProject.android.enforceUniquePackageName=false
// add dependency on the latest module
handler.compile(project(subProject.ext._apiModules.last().moduleName))
} else {
handler.compile(files(subProject.tasks.internalJar.archivePath))
def firstModule = subProject.ext._apiModules[0]
extraDeps.each { dep ->
handler."${firstModule.folderName}Compile"(project(dep))
handler.compile(project(dep))
}
}
}
def setupDependencies(Project subProject, String configName, SourceSet previousSourceSet) {
subProject.getDependencies().add(configName, previousSourceSet.output)
subProject.getDependencies().add(configName, previousSourceSet.compileClasspath)
}
subprojects {
// Change buildDir first so that all plugins pick up the new value.
project.buildDir = project.file("$project.parent.buildDir/../$project.name/build")
// current SDK is set in studioCompat.gradle
project.ext.currentSdk = gradle.ext.currentSdk
apply plugin: 'maven'
project.ext.createApiSourceSets = this.&createApiSourceset
project.ext.setApiModuleDependencies = this.&setApiModuleDependencies
version = rootProject.ext.supportVersion
group = 'com.android.support'
repositories {
maven { url "${project.parent.projectDir}/../../prebuilts/tools/common/m2/repository" }
maven { url "${project.parent.projectDir}/../../prebuilts/tools/common/m2/internal" }
maven { url "${project.parent.projectDir}/../../prebuilts/maven_repo/android" }
}
task release(type: Upload) {
configuration = configurations.archives
repositories {
mavenDeployer {
repository(url: uri("$rootProject.ext.supportRepoOut"))
// Disable unique names for SNAPSHOTS so they can be updated in place.
setUniqueVersion(false)
doLast {
// Remove any invalid maven-metadata.xml files that may have been created
// for SNAPSHOT versions that are *not* uniquely versioned.
pom*.each { pom ->
if (pom.version.endsWith('-SNAPSHOT')) {
final File artifactDir = new File(rootProject.ext.supportRepoOut,
pom.groupId.replace('.', '/')
+ '/' + pom.artifactId
+ '/' + pom.version)
delete fileTree(dir: artifactDir, include: 'maven-metadata.xml*')
}
}
}
}
}
}
def deployer = release.repositories.mavenDeployer
deployer.pom*.whenConfigured { pom ->
pom.dependencies.findAll {dep -> dep.groupId == 'com.android.support' && dep.artifactId != 'support-annotations' }*.type = 'aar'
}
// before the upload, make sure the repo is ready.
release.dependsOn rootProject.tasks.prepareRepo
// make the mainupload depend on this one.
mainUpload.dependsOn release
project.plugins.whenPluginAdded { plugin ->
if ("com.android.build.gradle.LibraryPlugin".equals(plugin.class.name)) {
project.android.buildToolsVersion = rootProject.buildToolsVersion
// enable code coverage for debug builds only if we are not running inside the IDE
// enabling coverage reports breaks the method parameter resolution in the IDE debugger
project.android.buildTypes.debug.testCoverageEnabled = !hasProperty('android.injected.invoked.from.ide')
}
}
// Copy instrumentation test APK into the dist dir
project.afterEvaluate {
def assembleTestTask = project.tasks.findByPath('assembleAndroidTest')
if (assembleTestTask != null) {
assembleTestTask.doLast {
// If the project actually has some instrumentation tests, copy its APK
if (!project.android.sourceSets.androidTest.java.sourceFiles.isEmpty()) {
def pkgTask = project.tasks.findByPath('packageDebugAndroidTest')
copy {
from(pkgTask.outputFile)
into(rootProject.ext.testApkDistOut)
}
}
}
}
}
project.afterEvaluate { p ->
// remove dependency on the test so that we still get coverage even if some tests fail
p.tasks.findAll { it instanceof JacocoReportTask}.each { task ->
def toBeRemoved = new ArrayList()
def dependencyList = task.taskDependencies.values
dependencyList.each { dep ->
if (dep instanceof String) {
def t = tasks.findByName(dep)
if (t instanceof DeviceProviderInstrumentTestTask) {
toBeRemoved.add(dep)
task.mustRunAfter(t)
}
}
}
toBeRemoved.each { dep ->
dependencyList.remove(dep)
}
}
}
}
project.gradle.buildFinished { buildResult ->
if (buildResult.getFailure() != null) {
println()
println 'Build failed. Possible causes include:'
println ' 1) Bad codes'
println ' 2) Out of date prebuilts in prebuilts/sdk'
println ' 3) Need to update the compileSdkVersion in a library\'s build.gradle'
println()
}
}
FileCollection getAndroidPrebuilt(String apiLevel) {
files("$rootDir/../../prebuilts/sdk/$apiLevel/android.jar")
}