536 lines
21 KiB
Groovy
536 lines
21 KiB
Groovy
import android.support.doclava.DoclavaMultilineJavadocOptionFileOption
|
|
import com.android.build.gradle.internal.coverage.JacocoReportTask
|
|
import com.android.build.gradle.internal.tasks.DeviceProviderInstrumentTestTask
|
|
|
|
import android.support.checkapi.CheckApiTask
|
|
import android.support.checkapi.UpdateApiTask
|
|
import android.support.doclava.DoclavaTask
|
|
|
|
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.2.0'
|
|
}
|
|
}
|
|
|
|
repositories {
|
|
maven { url '../../prebuilts/tools/common/m2/repository' }
|
|
}
|
|
|
|
configurations {
|
|
doclava
|
|
}
|
|
|
|
dependencies {
|
|
doclava project(':doclava')
|
|
}
|
|
|
|
ext.supportVersion = '25.0.1'
|
|
ext.extraVersion = 40
|
|
ext.supportRepoOut = ''
|
|
ext.buildToolsVersion = '23.0.2'
|
|
ext.buildNumber = Integer.toString(ext.extraVersion)
|
|
|
|
ext.testRunnerVersion = '0.6-alpha'
|
|
ext.espressoVersion = '2.3-alpha'
|
|
|
|
// Enforce the use of prebuilt dependencies in all sub-projects. This is
|
|
// required for the doclava dependency.
|
|
ext.usePrebuilts = "true"
|
|
|
|
/*
|
|
* 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("${project.rootDir}/../../out/host/gradle/frameworks/support/build")
|
|
project.ext.distDir = file("${project.rootDir}/../../out/dist")
|
|
}
|
|
|
|
subprojects {
|
|
// Change buildDir first so that all plugins pick up the new value.
|
|
project.buildDir = project.file("$project.parent.buildDir/../$project.name/build")
|
|
}
|
|
|
|
ext.docsDir = new File(buildDir, 'javadoc')
|
|
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 "${project.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
|
|
|
|
/**
|
|
* Generates SHA1 hash for the specified file's absolute path.
|
|
*
|
|
* @param inputFile file to hash
|
|
* @return SHA1 hash
|
|
*/
|
|
String getSha1(File inputFile) {
|
|
HashFunction hashFunction = Hashing.sha1()
|
|
HashCode hashCode = hashFunction.hashString(inputFile.getAbsolutePath(), Charset.forName("UTF-8"))
|
|
return hashCode.toString()
|
|
}
|
|
|
|
/**
|
|
* Returns the Android prebuilt JAR for the specified API level.
|
|
*
|
|
* @param apiLevel the API level or "current"
|
|
* @return a file collection containing the Android prebuilt JAR
|
|
*/
|
|
FileCollection getAndroidPrebuilt(apiLevel) {
|
|
files("${project.rootDir}/../../prebuilts/sdk/$apiLevel/android.jar")
|
|
}
|
|
|
|
/**
|
|
* Populates the sub-project's set of source sets with the specified modules.
|
|
*
|
|
* @param subProject the sub-project to which the modules belong
|
|
* @param apiModules the modules from which to populate
|
|
*/
|
|
void 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
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Adds the specified module to the sub-project's set of source sets and
|
|
* internal JAR. Also sets up dependencies, if supplied.
|
|
*
|
|
* @param subProject the sub-project to which the module belongs
|
|
* @param name the name of the module
|
|
* @param folder the module's source folder
|
|
* @param apiLevel the module's compile API level
|
|
* @param previousSource source set dependency (optional)
|
|
* @return a source set for the module
|
|
*/
|
|
SourceSet createApiSourceset(Project subProject, String name, String folder, String apiLevel,
|
|
SourceSet previousSource) {
|
|
def sourceSet = subProject.sourceSets.create(name)
|
|
sourceSet.java.srcDirs = [folder]
|
|
|
|
// The Android gradle plugin doesn't touch Java sub-tasks, so we need to
|
|
// manually set the Java task's boot classpath to the correct Android SDK.
|
|
def compileJavaTaskName = sourceSet.getCompileJavaTaskName();
|
|
def compileJavaOptions = subProject.tasks."${compileJavaTaskName}".options
|
|
compileJavaOptions.bootClasspath = getAndroidPrebuilt(apiLevel)
|
|
|
|
// Useful for cleaning up compiler warnings...
|
|
//compileJavaOptions.compilerArgs << "-Xlint:unchecked" << "-Xlint:deprecation"
|
|
|
|
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
|
|
}
|
|
|
|
/**
|
|
* Adds the specified source set as a dependency for the sub-project.
|
|
*
|
|
* @param subProject the sub-project to modify
|
|
* @param configName
|
|
* @param previousSourceSet the source set to add as a dependency
|
|
*/
|
|
void setupDependencies(Project subProject, String configName, SourceSet previousSourceSet) {
|
|
subProject.getDependencies().add(configName, previousSourceSet.output)
|
|
subProject.getDependencies().add(configName, previousSourceSet.compileClasspath)
|
|
}
|
|
|
|
void 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))
|
|
}
|
|
}
|
|
}
|
|
|
|
void registerForDocsTask(Task task, Project subProject, releaseVariant) {
|
|
task.dependsOn releaseVariant.javaCompile
|
|
task.source {
|
|
def buildConfig = fileTree(releaseVariant.getGenerateBuildConfig().sourceOutputDir)
|
|
return releaseVariant.javaCompile.source.minus(buildConfig) +
|
|
fileTree(releaseVariant.aidlCompile.sourceOutputDir) +
|
|
fileTree(releaseVariant.outputs[0].processResources.sourceOutputDir)
|
|
}
|
|
task.classpath += files(releaseVariant.javaCompile.classpath) +
|
|
files(releaseVariant.javaCompile.destinationDir)
|
|
|
|
if (subProject.hasProperty('allSS')) {
|
|
subProject.allSS.each { ss ->
|
|
task.source ss.java
|
|
}
|
|
}
|
|
}
|
|
|
|
// Generates online docs.
|
|
task generateDocs(type: DoclavaTask, dependsOn: configurations.doclava) {
|
|
docletpath = configurations.doclava.resolve()
|
|
destinationDir = new File(project.docsDir, "online")
|
|
|
|
// Base classpath is Android SDK, sub-projects add their own.
|
|
classpath = getAndroidPrebuilt(gradle.ext.currentSdk)
|
|
|
|
def hdfOption = new DoclavaMultilineJavadocOptionFileOption('hdf')
|
|
hdfOption.add(
|
|
['android.whichdoc', 'online'],
|
|
['android.hasSamples', 'true']);
|
|
|
|
options {
|
|
addStringOption "templatedir",
|
|
"${project.rootDir}/../../build/tools/droiddoc/templates-sdk"
|
|
addStringOption "federate Android", "http://developer.android.com"
|
|
addStringOption "federationapi Android",
|
|
"${project.rootDir}/../../prebuilts/sdk/api/24.txt"
|
|
addStringOption "stubpackages", "android.support.*"
|
|
addStringOption "samplesdir", "${project.rootDir}/samples"
|
|
addOption hdfOption
|
|
}
|
|
|
|
exclude '**/BuildConfig.java'
|
|
}
|
|
|
|
// Generates API files.
|
|
task generateApi(type: DoclavaTask, dependsOn: configurations.doclava) {
|
|
docletpath = configurations.doclava.resolve()
|
|
destinationDir = project.docsDir
|
|
|
|
// Base classpath is Android SDK, sub-projects add their own.
|
|
classpath = getAndroidPrebuilt(gradle.ext.currentSdk)
|
|
|
|
apiFile = new File(project.docsDir, 'release/current.txt')
|
|
removedApiFile = new File(project.docsDir, 'release/removed.txt')
|
|
generateDocs = false
|
|
|
|
options {
|
|
addStringOption "templatedir",
|
|
"${project.rootDir}/../../build/tools/droiddoc/templates-sdk"
|
|
addStringOption "federate Android", "http://developer.android.com"
|
|
addStringOption "federationapi Android",
|
|
"${project.rootDir}/../../prebuilts/sdk/api/24.txt"
|
|
addStringOption "stubpackages", "android.support.*"
|
|
}
|
|
exclude '**/BuildConfig.java'
|
|
exclude '**/R.java'
|
|
}
|
|
|
|
// Copies generated API files to current version.
|
|
task updateApi(type: UpdateApiTask, dependsOn: generateApi) {
|
|
newApiFile = new File(project.docsDir, 'release/current.txt')
|
|
oldApiFile = new File(project.rootDir, 'api/current.txt')
|
|
newRemovedApiFile = new File(project.docsDir, 'release/removed.txt')
|
|
oldRemovedApiFile = new File(project.rootDir, 'api/removed.txt')
|
|
}
|
|
|
|
// Checks generated API files against current version.
|
|
task checkApi(type: CheckApiTask, dependsOn: generateApi) {
|
|
doclavaClasspath = generateApi.docletpath
|
|
|
|
checkApiTaskPath = name
|
|
updateApiTaskPath = updateApi.name
|
|
|
|
newApiFile = new File(project.docsDir, 'release/current.txt')
|
|
oldApiFile = new File(project.rootDir, 'api/current.txt')
|
|
newRemovedApiFile = new File(project.docsDir, 'release/removed.txt')
|
|
oldRemovedApiFile = new File(project.rootDir, 'api/removed.txt')
|
|
}
|
|
createArchive.dependsOn checkApi
|
|
|
|
subprojects {
|
|
// Only modify android projects.
|
|
if (project.name.equals('doclava')) return;
|
|
|
|
// 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" }
|
|
}
|
|
|
|
project.plugins.whenPluginAdded { plugin ->
|
|
if ("com.android.build.gradle.LibraryPlugin".equals(plugin.class.name)
|
|
|| "com.android.build.gradle.AppPlugin".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')
|
|
}
|
|
|
|
// Create release and separate zip task for Android libraries (and android-annotations,
|
|
// which is just a Java library).
|
|
if ("com.android.build.gradle.LibraryPlugin".equals(plugin.class.name)
|
|
|| "org.gradle.api.plugins.JavaPlugin".equals(plugin.class.name)) {
|
|
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'
|
|
}
|
|
|
|
ext.versionDir = {
|
|
def groupDir = new File(rootProject.ext.supportRepoOut,
|
|
project.group.replace('.','/'))
|
|
def artifactDir = new File(groupDir, archivesBaseName)
|
|
return new File(artifactDir, version)
|
|
}
|
|
|
|
task generateSourceProps(dependsOn: createRepository) << {
|
|
def content = "Maven.GroupId=$deployer.pom.groupId\n" +
|
|
"Maven.ArtifactId=$deployer.pom.artifactId\n" +
|
|
"Maven.Version=$deployer.pom.version\n" +
|
|
"Extra.VendorDisplay=Android\n" +
|
|
"Extra.VendorId=android\n" +
|
|
"Pkg.Desc=$project.name\n" +
|
|
"Pkg.Revision=1\n" +
|
|
"Maven.Dependencies=" +
|
|
String.join(",", project.configurations.compile.allDependencies.collect {
|
|
def p = parent.findProject(it.name)
|
|
return p ? "$p.group:$p.archivesBaseName:$p.version" : null
|
|
}.grep()) +
|
|
"\n"
|
|
Files.write(content, new File(versionDir(), 'source.properties'), Charsets.UTF_8)
|
|
}
|
|
|
|
task createSeparateZip(type: Zip, dependsOn: generateSourceProps) {
|
|
into archivesBaseName
|
|
destinationDir project.parent.ext.distDir
|
|
baseName = project.group
|
|
version = project.parent.ext.buildNumber
|
|
}
|
|
project.parent.createArchive.dependsOn createSeparateZip
|
|
|
|
// 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.afterEvaluate {
|
|
// The archivesBaseName isn't available intially, so set it now
|
|
def createZipTask = project.tasks.findByName("createSeparateZip")
|
|
if (createZipTask != null) {
|
|
createZipTask.appendix = archivesBaseName
|
|
createZipTask.from versionDir()
|
|
}
|
|
|
|
// Copy instrumentation test APK into the dist dir
|
|
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.afterEvaluate { p ->
|
|
if (p.hasProperty('android')
|
|
&& p.android.hasProperty('libraryVariants')
|
|
&& !(p.android.hasProperty('noDocs') && p.android.noDocs)) {
|
|
p.android.libraryVariants.all { v ->
|
|
if (v.name == 'release') {
|
|
registerForDocsTask(rootProject.generateDocs, p, v)
|
|
registerForDocsTask(rootProject.generateApi, p, v)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
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()
|
|
}
|
|
}
|