blob: 673f6f87e90b71a15a22b41a26a8a4656cec2d71 [file] [log] [blame]
Yigit Boyar88c16ce2017-02-08 16:06:14 -08001/*
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
22import org.gradle.internal.os.OperatingSystem
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.checkoutRoot = "${supportRoot}/../.."
Alan Viverette1b862372017-03-22 11:32:28 -040032ext.init.debugKeystore = file("${supportRoot}/development/keystore/debug.keystore")
Yigit Boyar88c16ce2017-02-08 16:06:14 -080033ext.init.prebuiltsRoot = "${init.checkoutRoot}/prebuilts"
34ext.init.prebuiltsRootUri = "file://${init.prebuiltsRoot}"
35ext.init.enablePublicRepos = System.getenv("ALLOW_PUBLIC_REPOS") != null
Yigit Boyar7bfacb72017-03-02 14:27:41 -080036ext.runningInBuildServer = System.env.DIST_DIR != null && System.env.OUT_DIR != null
Yigit Boyar88c16ce2017-02-08 16:06:14 -080037
38ext.repoNames = ["${init.prebuiltsRoot}/gradle-plugin",
39 "${init.prebuiltsRoot}/tools/common/m2/repository",
40 "${init.prebuiltsRoot}/tools/common/m2/internal",
41 "${init.prebuiltsRoot}/maven_repo/android"]
42
43apply from: "${supportRoot}/buildSrc/dependencies.gradle"
Yigit Boyar63e6c672017-03-31 13:32:17 -070044ext.buildOfflineDocs = rootProject.getProperties().containsKey("offlineDocs")
Yigit Boyar88c16ce2017-02-08 16:06:14 -080045
46def loadDefaultVersions() {
47 apply from: "${supportRootFolder}/buildSrc/versions.gradle"
48}
49
50def addMavenRepositories(RepositoryHandler handler) {
51 repoNames.each { repo ->
52 handler.maven {
53 url repo
54 }
55 if (ext.init.enablePublicRepos) {
56 handler.mavenCentral()
57 handler.jcenter()
58 }
59 }
60}
61
62def enableDoclavaAndJDiff(p) {
63 p.configurations {
64 doclava
65 jdiff
66 }
67
68 p.dependencies {
69 doclava project(':doclava')
70 jdiff project(':jdiff')
71 jdiff libs.xml_parser_apis
72 jdiff libs.xerces_impl
73 }
74 apply from: "${ext.supportRootFolder}/buildSrc/diff_and_docs.gradle"
75}
76
77def setSdkInLocalPropertiesFile() {
78 final String platform = OperatingSystem.current().isMacOsX() ? 'darwin' : 'linux'
79 System.setProperty('android.dir', "${supportRootFolder}/../../")
Aurimas Liutikasd2d9bda2017-03-03 16:06:39 -080080 ext.buildToolsVersion = '26.0.0'
Yigit Boyar88c16ce2017-02-08 16:06:14 -080081 final String fullSdkPath = "${init.prebuiltsRoot}/fullsdk-${platform}"
82 if (file(fullSdkPath).exists()) {
83 gradle.ext.currentSdk = 26
Alan Viveretteeb9f3322017-03-09 16:29:57 -050084 project.ext.androidJar =
85 files("${fullSdkPath}/platforms/android-${gradle.currentSdk}/android.jar")
86 project.ext.androidSrcJar =
87 file("${fullSdkPath}/platforms/android-${gradle.currentSdk}/android-stubs-src.jar")
Alan Viverette810a1482017-03-20 12:43:43 -040088 project.ext.androidApiTxt = null
Yigit Boyar88c16ce2017-02-08 16:06:14 -080089 System.setProperty('android.home', "${init.prebuiltsRoot}/fullsdk-${platform}")
90 File props = file("local.properties")
91 props.write "sdk.dir=${fullSdkPath}"
Aurimas Liutikas3c666002017-03-08 19:30:28 -080092 ext.usingFullSdk = true
Yigit Boyar88c16ce2017-02-08 16:06:14 -080093 } else {
94 gradle.ext.currentSdk = 'current'
Yigit Boyar88c16ce2017-02-08 16:06:14 -080095 project.ext.androidJar = files("${init.prebuiltsRoot}/sdk/current/android.jar")
Alan Viverette810a1482017-03-20 12:43:43 -040096 project.ext.androidSrcJar = null
97 project.ext.androidApiTxt = file("${init.prebuiltsRoot}/sdk/api/26.txt")
Yigit Boyar88c16ce2017-02-08 16:06:14 -080098 File props = file("local.properties")
99 props.write "android.dir=../../"
Aurimas Liutikas3c666002017-03-08 19:30:28 -0800100 ext.usingFullSdk = false
Yigit Boyar88c16ce2017-02-08 16:06:14 -0800101 }
102}
103
104def setupRepoOutAndBuildNumber() {
105 ext.supportRepoOut = ''
106 ext.buildNumber = Integer.toString(ext.extraVersion)
107
108 /*
109 * With the build server you are given two env variables.
110 * The OUT_DIR is a temporary directory you can use to put things during the build.
111 * The DIST_DIR is where you want to save things from the build.
112 *
113 * The build server will copy the contents of DIST_DIR to somewhere and make it available.
114 */
Yigit Boyar7bfacb72017-03-02 14:27:41 -0800115 if (ext.runningInBuildServer) {
Yigit Boyar88c16ce2017-02-08 16:06:14 -0800116 buildDir = new File(System.env.OUT_DIR + '/gradle/frameworks/support/build')
117 .getCanonicalFile()
118 project.ext.distDir = new File(System.env.DIST_DIR).getCanonicalFile()
119
120 // the build server does not pass the build number so we infer it from the last folder of
121 // the dist path.
122 ext.buildNumber = project.ext.distDir.getName()
123 } else {
124 buildDir = file("${ext.supportRootFolder}/../../out/host/gradle/frameworks/support/build")
125 project.ext.distDir = new File("${ext.supportRootFolder}/../../out/dist")
126 }
127 subprojects {
128 // Change buildDir first so that all plugins pick up the new value.
129 project.buildDir = new File("$project.parent.buildDir/../$project.name/build")
130 }
131 ext.supportRepoOut = new File(buildDir, 'support_repo')
132 ext.testApkDistOut = ext.distDir
Yigit Boyar7bfacb72017-03-02 14:27:41 -0800133 ext.testResultsDistDir = new File(distDir, "host-test-reports")
Yigit Boyar88c16ce2017-02-08 16:06:14 -0800134 ext.docsDir = new File(buildDir, 'javadoc')
135}
136
137def configureSubProjects() {
138 // lint every library
139 def lintTask = project.tasks.create("lint")
140 subprojects {
141 // Only modify Android projects.
Yigit Boyar7bfacb72017-03-02 14:27:41 -0800142 if (project.name.equals('doclava') || project.name.equals('jdiff')) {
143 // disable tests and return
144 project.tasks.whenTaskAdded { task ->
145 if (task instanceof org.gradle.api.tasks.testing.Test) {
146 task.enabled = false
147 }
148 }
149 return
150 }
Yigit Boyar88c16ce2017-02-08 16:06:14 -0800151
152 // Current SDK is set in studioCompat.gradle.
153 project.ext.currentSdk = gradle.ext.currentSdk
154 apply plugin: 'maven'
155
156 version = rootProject.ext.supportVersion
157 group = 'com.android.support'
158
159 init.addMavenRepositories(repositories)
160 project.plugins.whenPluginAdded { plugin ->
161 def isAndroidLibrary = "com.android.build.gradle.LibraryPlugin"
162 .equals(plugin.class.name)
163 def isAndroidApp = "com.android.build.gradle.AppPlugin".equals(plugin.class.name)
164 def isJavaLibrary = "org.gradle.api.plugins.JavaPlugin".equals(plugin.class.name)
165
166 if (isAndroidLibrary || isAndroidApp) {
167 project.android.buildToolsVersion = rootProject.buildToolsVersion
168
169 // Enable code coverage for debug builds only if we are not running inside the IDE,
170 // since enabling coverage reports breaks the method parameter resolution in the IDE
171 // debugger.
172 project.android.buildTypes.debug.testCoverageEnabled =
173 !hasProperty('android.injected.invoked.from.ide')
174
175 // Copy the class files in a jar to be later used to generate code coverage report
176 project.android.testVariants.all { v ->
177 // check if the variant has any source files
178 // and test coverage is enabled
179 if (v.buildType.testCoverageEnabled
180 && v.sourceSets.any { !it.java.sourceFiles.isEmpty() }) {
181 def jarifyTask = project.tasks.create(
182 name: "package${v.name.capitalize()}ClassFilesForCoverageReport",
183 type: Jar) {
184 from v.testedVariant.javaCompile.destinationDir
185 exclude "**/R.class"
186 exclude "**/R\$*.class"
187 exclude "**/BuildConfig.class"
188 destinationDir file(project.distDir)
189 archiveName "${project.archivesBaseName}-${v.baseName}-allclasses.jar"
190 }
191 def jacocoAntConfig =
192 project.configurations[JacocoPlugin.ANT_CONFIGURATION_NAME]
193 def jacocoAntArtifacts = jacocoAntConfig.resolvedConfiguration
194 .resolvedArtifacts
195 def version = jacocoAntArtifacts.find { "org.jacoco.ant".equals(it.name) }
196 .moduleVersion.id.version
197 def collectJacocoAntPackages = project.tasks.create(
198 name: "collectJacocoAntPackages",
199 type: Jar) {
200 from(jacocoAntArtifacts.collect { zipTree(it.getFile()) }) {
201 // exclude all the signatures the jar might have
202 exclude "META-INF/*.SF"
203 exclude "META-INF/*.DSA"
204 exclude "META-INF/*.RSA"
205 }
206 destinationDir file(project.distDir)
207 archiveName "jacocoant-" + version + ".jar"
208 }
209 jarifyTask.dependsOn v.getJavaCompiler()
210 v.assemble.dependsOn jarifyTask, collectJacocoAntPackages
211 }
212 }
213
214 // Enforce NewApi lint check as fatal.
215 project.android.lintOptions.check 'NewApi'
216 project.android.lintOptions.fatal 'NewApi'
217 lintTask.dependsOn project.lint
218 }
219
220 if (isAndroidLibrary || isJavaLibrary) {
221 // Add library to the aggregate dependency report.
222 task allDeps(type: DependencyReportTask) {}
223
224 // Create release and separate zip task for library.
225 task release(type: Upload) {
226 configuration = configurations.archives
227 repositories {
228 mavenDeployer {
229 repository(url: uri("$rootProject.ext.supportRepoOut"))
230
231 // Disable unique names for SNAPSHOTS so they can be updated in place.
232 setUniqueVersion(false)
233 doLast {
234 // Remove any invalid maven-metadata.xml files that may have been
235 // created for SNAPSHOT versions that are *not* uniquely versioned.
236 pom*.each { pom ->
237 if (pom.version.endsWith('-SNAPSHOT')) {
238 final File artifactDir = new File(
239 rootProject.ext.supportRepoOut,
240 pom.groupId.replace('.', '/')
241 + '/' + pom.artifactId
242 + '/' + pom.version)
243 delete fileTree(dir: artifactDir,
244 include: 'maven-metadata.xml*')
245 }
246 }
247 }
248 }
249 }
250 }
251
252 def deployer = release.repositories.mavenDeployer
253 deployer.pom*.whenConfigured { pom ->
254 pom.dependencies.findAll { dep ->
255 dep.groupId == 'com.android.support' &&
256 dep.artifactId != 'support-annotations'
257 }*.type = 'aar'
258 }
259
260 ext.versionDir = {
261 def groupDir = new File(rootProject.ext.supportRepoOut,
262 project.group.replace('.', '/'))
263 def artifactDir = new File(groupDir, archivesBaseName)
264 return new File(artifactDir, version)
265 }
266
267 task generateSourceProps(dependsOn: createRepository)
268 generateSourceProps.doLast({
269 def content = "Maven.GroupId=$deployer.pom.groupId\n" +
270 "Maven.ArtifactId=$deployer.pom.artifactId\n" +
271 "Maven.Version=$deployer.pom.version\n" +
272 "Extra.VendorDisplay=Android\n" +
273 "Extra.VendorId=android\n" +
274 "Pkg.Desc=$project.name\n" +
275 "Pkg.Revision=1\n" +
276 "Maven.Dependencies=" +
277 String.join(",", project.configurations.compile.allDependencies
278 .collect {
279 def p = parent.findProject(it.name)
280 return p ? "$p.group:$p.archivesBaseName:$p.version" : null
281 }.grep()) +
282 "\n"
283 Files.write(content, new File(versionDir(), 'source.properties'),
284 Charsets.UTF_8)
285 })
286
287 task createSeparateZip(type: Zip, dependsOn: generateSourceProps) {
288 into archivesBaseName
Yigit Boyar7bfacb72017-03-02 14:27:41 -0800289 destinationDir rootProject.ext.distDir
Yigit Boyar88c16ce2017-02-08 16:06:14 -0800290 baseName = project.group
Yigit Boyar7bfacb72017-03-02 14:27:41 -0800291 version = rootProject.ext.buildNumber
Yigit Boyar88c16ce2017-02-08 16:06:14 -0800292 }
Yigit Boyar7bfacb72017-03-02 14:27:41 -0800293 rootProject.createArchive.dependsOn createSeparateZip
Yigit Boyar88c16ce2017-02-08 16:06:14 -0800294
295 // Before the upload, make sure the repo is ready.
296 release.dependsOn rootProject.tasks.prepareRepo
297
298 // Make the mainupload depend on this one.
299 mainUpload.dependsOn release
300 }
301 }
302
Yigit Boyar7bfacb72017-03-02 14:27:41 -0800303 // Copy instrumentation test APKs and app APKs into the dist dir
304 // For test apks, they are uploaded only if we have java test sources.
305 // For regular app apks, they are uploaded only if they have java sources.
306 project.tasks.whenTaskAdded { task ->
307 if (task.name.startsWith("packageDebug")) {
308 def testApk = task.name.contains("AndroidTest")
309 task.doLast {
310 def source = testApk ? project.android.sourceSets.androidTest
311 : project.android.sourceSets.main
312 if (task.hasProperty("outputFile") && !source.java.sourceFiles.isEmpty()) {
313 copy {
314 from(task.outputFile)
315 into(rootProject.ext.testApkDistOut)
316 rename { String fileName ->
317 // multiple modules may have the same name so prefix the name with
318 // the module's path to ensure it is unique.
319 // e.g. palette-v7-debug-androidTest.apk becomes
320 // support-palette-v7_palette-v7-debug-androidTest.apk
321 "${project.getPath().replace(':', '-').substring(1)}_${fileName}"
322 }
323 }
324 }
325 }
326 }
327 }
328
329 // copy host side test results to DIST
330 project.tasks.whenTaskAdded { task ->
331 if (task instanceof org.gradle.api.tasks.testing.Test) {
332 def junitReport = task.reports.junitXml
333 if (junitReport.enabled) {
334 def zipTask = project.tasks.create(name : "zipResultsOf${task.name.capitalize()}", type : Zip) {
335 destinationDir(testResultsDistDir)
Yigit Boyar278676d2017-03-10 15:29:11 -0800336 // first one is always :, drop it.
337 archiveName("${project.getPath().split(":").join("_").substring(1)}.zip")
Yigit Boyar7bfacb72017-03-02 14:27:41 -0800338 }
339 if (project.rootProject.ext.runningInBuildServer) {
340 task.ignoreFailures = true
341 }
342 task.finalizedBy zipTask
343 task.doFirst {
344 zipTask.from(junitReport.destination)
345 }
346 }
347 }
348 }
349
Yigit Boyar88c16ce2017-02-08 16:06:14 -0800350 project.afterEvaluate {
351 // The archivesBaseName isn't available initially, so set it now
352 def createZipTask = project.tasks.findByName("createSeparateZip")
353 if (createZipTask != null) {
354 createZipTask.appendix = archivesBaseName
355 createZipTask.from versionDir()
356 }
Yigit Boyar88c16ce2017-02-08 16:06:14 -0800357 }
358
359 project.afterEvaluate { p ->
360 // remove dependency on the test so that we still get coverage even if some tests fail
361 p.tasks.findAll { it instanceof JacocoReportTask }.each { task ->
362 def toBeRemoved = new ArrayList()
363 def dependencyList = task.taskDependencies.values
364 dependencyList.each { dep ->
365 if (dep instanceof String) {
366 def t = tasks.findByName(dep)
367 if (t instanceof DeviceProviderInstrumentTestTask) {
368 toBeRemoved.add(dep)
369 task.mustRunAfter(t)
370 }
371 }
372 }
373 toBeRemoved.each { dep ->
374 dependencyList.remove(dep)
375 }
376 }
377 }
378 }
379}
380
381def setupRelease() {
382 apply from: "${ext.supportRootFolder}/buildSrc/release.gradle"
383}
384
385ext.init.addMavenRepositories = this.&addMavenRepositories
386ext.init.enableDoclavaAndJDiff = this.&enableDoclavaAndJDiff
387ext.init.setSdkInLocalPropertiesFile = this.&setSdkInLocalPropertiesFile
388ext.init.setupRepoOutAndBuildNumber = this.&setupRepoOutAndBuildNumber
389ext.init.setupRelease = this.&setupRelease
390ext.init.loadDefaultVersions = this.&loadDefaultVersions
391ext.init.configureSubProjects = this.&configureSubProjects