1/* 2 * Copyright 2020 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 * https://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 17buildscript { 18 repositories { 19 google() 20 mavenCentral() 21 gradlePluginPortal() 22 } 23 24 dependencies { 25 classpath libs.android.tools.build.gradle 26 classpath libs.android.gradlePlugin 27 classpath libs.kotlin.gradlePlugin 28 29 classpath libs.gradleMavenPublishPlugin 30 31 classpath libs.metalavaGradle 32 33 classpath libs.affectedmoduledetector 34 } 35} 36 37plugins { 38 id "com.diffplug.spotless" version "6.5.2" 39 alias(libs.plugins.jetbrains.dokka) 40} 41 42apply plugin: 'com.dropbox.affectedmoduledetector' 43apply plugin: 'com.diffplug.spotless' 44 45tasks.withType(org.jetbrains.dokka.gradle.DokkaMultiModuleTask).configureEach { 46 outputDirectory = rootProject.file('docs/api') 47 failOnWarning = true 48} 49 50affectedModuleDetector { 51 baseDir = "${project.rootDir}" 52 pathsAffectingAllModules = [ 53 "gradle/libs.versions.toml", 54 ] 55 excludedModules = [ 56 "sample" 57 ] 58 59 logFilename = "output.log" 60 logFolder = "${rootProject.buildDir}/affectedModuleDetector" 61 62 String baseRef = findProperty("affected_base_ref") 63 // If we have a base ref to diff against, extract the branch name and use it 64 if (baseRef != null && !baseRef.isEmpty()) { 65 // Remove the prefix from the head. 66 // TODO: need to support other types of git refs 67 specifiedBranch = baseRef.replace('refs/heads/', '') 68 compareFrom = "SpecifiedBranchCommit" 69 } else { 70 // Otherwise we use the previous commit. This is mostly used for commits to main. 71 compareFrom = "PreviousCommit" 72 } 73} 74 75allprojects { 76 repositories { 77 google() 78 mavenCentral() 79 80 def composeSnapshot = libs.versions.composesnapshot.get() 81 if (composeSnapshot.length() > 1) { 82 maven { url "https://androidx.dev/snapshots/builds/$composeSnapshot/artifacts/repository/" } 83 } 84 } 85} 86 87subprojects { 88 apply plugin: 'com.diffplug.spotless' 89 90 spotless { 91 kotlin { 92 target "**/*.kt" 93 ktlint(libs.versions.ktlint.get()) 94 licenseHeaderFile rootProject.file('spotless/copyright.txt') 95 } 96 97 groovyGradle { 98 target '**/*.gradle' 99 greclipse().configFile(rootProject.file('spotless/greclipse.properties')) 100 licenseHeaderFile rootProject.file('spotless/copyright.txt'), 101 '(buildscript|apply|import|plugins)' 102 } 103 } 104 105 // Remove all test apps after running UI tests. 106 // This is specially important in CI so that test emulators don't run out of space. 107 tasks.whenTaskAdded { task -> 108 if (task.name == 'connectedDebugAndroidTest') { 109 task.finalizedBy 'uninstallDebugAndroidTest' 110 } 111 } 112 113 configurations.configureEach { 114 resolutionStrategy.eachDependency { DependencyResolveDetails details -> 115 // Make sure that we're using the Android version of Guava 116 if (details.requested.group == 'com.google.guava' 117 && details.requested.module.name == 'guava' 118 && details.requested.version.contains('jre')) { 119 details.useVersion details.requested.version.replace('jre', 'android') 120 } 121 } 122 } 123 124 tasks.withType(org.jetbrains.kotlin.gradle.tasks.KotlinCompile).configureEach { compile -> 125 kotlinOptions { 126 // Treat all Kotlin warnings as errors 127 allWarningsAsErrors = true 128 // Set JVM target to 1.8 129 jvmTarget = "1.8" 130 // Allow use of @OptIn 131 freeCompilerArgs += "-opt-in=kotlin.RequiresOptIn" 132 // Enable default methods in interfaces 133 freeCompilerArgs += "-Xjvm-default=all" 134 } 135 } 136 137 // Read in the signing.properties file if it is exists 138 def signingPropsFile = rootProject.file('release/signing.properties') 139 if (signingPropsFile.exists()) { 140 def localProperties = new Properties() 141 signingPropsFile.withInputStream { is -> localProperties.load(is) } 142 localProperties.each { prop -> 143 if (prop.key == "signing.secretKeyRingFile") { 144 // If this is the key ring, treat it as a relative path 145 project.ext.set(prop.key, rootProject.file(prop.value).absolutePath) 146 } else { 147 project.ext.set(prop.key, prop.value) 148 } 149 } 150 } 151 152 // Must be afterEvaluate or else com.vanniktech.maven.publish will overwrite our 153 // dokka and version configuration. 154 afterEvaluate { 155 if (tasks.findByName('dokkaHtmlPartial') == null) { 156 // If dokka isn't enabled on this module, skip 157 return 158 } 159 160 tasks.named('dokkaHtmlPartial') { 161 dokkaSourceSets.configureEach { 162 reportUndocumented.set(true) 163 skipEmptyPackages.set(true) 164 skipDeprecated.set(true) 165 jdkVersion.set(8) 166 167 // Add Android SDK packages 168 noAndroidSdkLink.set(false) 169 170 // Add samples from :sample module 171 samples.from(rootProject.file("sample/src/main/java/")) 172 173 // AndroidX + Compose docs 174 externalDocumentationLink { 175 url.set(new URL("https://developer.android.com/reference/")) 176 packageListUrl.set(new URL("https://developer.android.com/reference/androidx/package-list")) 177 } 178 externalDocumentationLink { 179 url.set(new URL("https://developer.android.com/reference/kotlin/")) 180 packageListUrl.set(new URL("https://developer.android.com/reference/kotlin/androidx/package-list")) 181 } 182 183 sourceLink { 184 localDirectory.set(project.file("src/main/java")) 185 // URL showing where the source code can be accessed through the web browser 186 remoteUrl.set(new URL("https://github.com/google/accompanist/blob/main/${project.name}/src/main/java")) 187 // Suffix which is used to append the line number to the URL. Use #L for GitHub 188 remoteLineSuffix.set("#L") 189 } 190 } 191 } 192 } 193 194 afterEvaluate { 195 def composeSnapshot = libs.versions.composesnapshot.get() 196 if (composeSnapshot.length() > 1) { 197 // We're depending on a Jetpack Compose snapshot, update the library version name 198 // to indicate it's from a Compose snapshot 199 def versionName = project.properties.get('VERSION_NAME') 200 if (versionName.contains("SNAPSHOT")) { 201 version = versionName.replace('-SNAPSHOT', ".compose-${composeSnapshot}-SNAPSHOT") 202 } 203 } 204 205 if (!version.endsWith('SNAPSHOT')) { 206 // If we're not a SNAPSHOT library version, we fail the build if we're relying on 207 // any snapshot dependencies 208 configurations.configureEach { configuration -> 209 configuration.dependencies.configureEach { dependency -> 210 if (dependency instanceof ProjectDependency) { 211 // We don't care about internal project dependencies 212 return 213 } 214 215 def depVersion = dependency.version 216 if (depVersion != null && depVersion.endsWith('SNAPSHOT')) { 217 throw new IllegalArgumentException( 218 "Using SNAPSHOT dependency with non-SNAPSHOT library version: $dependency" 219 ) 220 } 221 } 222 } 223 } 224 } 225} 226