build.gradle (7947B)
1 // Top-level build file where you can add configuration options common to all sub-projects/modules. 2 3 4 import io.gitlab.arturbosch.detekt.Detekt 5 import io.gitlab.arturbosch.detekt.DetektCreateBaselineTask 6 import org.jetbrains.kotlin.gradle.tasks.KotlinCompile 7 8 buildscript { 9 // This logic is duplicated in the allprojects block: I don't know how to fix that. 10 repositories { 11 mavenLocal() 12 gradle.mozconfig.substs.GRADLE_MAVEN_REPOSITORIES.each { repository -> 13 maven { 14 url = repository 15 if (gradle.mozconfig.substs.ALLOW_INSECURE_GRADLE_REPOSITORIES) { 16 allowInsecureProtocol = true 17 } 18 } 19 } 20 } 21 22 dependencies { 23 classpath libs.android.gradle.plugin 24 classpath libs.androidx.benchmark.gradle 25 classpath libs.androidx.navigation.safeargs 26 classpath libs.mozilla.glean.gradle.plugin 27 classpath libs.osslicenses.plugin 28 29 // NOTE: Do not place your application dependencies here; they belong 30 // in the individual module build.gradle files 31 } 32 } 33 34 plugins { 35 id 'ApkSizePlugin' 36 id "mozac.ConfigPlugin" 37 alias(libs.plugins.detekt) 38 alias(libs.plugins.kotlin.android) apply false 39 alias(libs.plugins.kotlin.compose) apply false 40 alias(libs.plugins.ksp) 41 } 42 43 allprojects { 44 // This logic is duplicated in the buildscript block: I don't know how to fix that. 45 repositories { 46 mavenLocal() 47 gradle.mozconfig.substs.GRADLE_MAVEN_REPOSITORIES.each { repository -> 48 maven { 49 url = repository 50 if (gradle.mozconfig.substs.ALLOW_INSECURE_GRADLE_REPOSITORIES) { 51 allowInsecureProtocol = true 52 } 53 } 54 } 55 56 maven { 57 url = "${gradle.mozconfig.topobjdir}/gradle/maven" 58 } 59 } 60 61 ext { 62 gleanVersion = libs.versions.glean.get() 63 } 64 65 tasks.withType(KotlinCompile).configureEach { 66 compilerOptions.allWarningsAsErrors = true 67 } 68 } 69 70 subprojects { 71 afterEvaluate { 72 if (it.hasProperty('kotlin')) { 73 kotlin { 74 jvmToolchain(config.jvmTargetCompatibility) 75 } 76 } 77 78 if (it.hasProperty('android')) { 79 android { 80 buildToolsVersion gradle.mozconfig.substs.ANDROID_BUILD_TOOLS_VERSION 81 } 82 } 83 } 84 85 project.configurations.configureEach { 86 // Dependencies can't depend on a different major version of Glean than A-C itself. 87 resolutionStrategy.eachDependency { details -> 88 if (details.requested.group == 'org.mozilla.telemetry' 89 && details.requested.name.contains('glean') ) { 90 def requested = details.requested.version.tokenize(".") 91 def defined = project.ext.gleanVersion.tokenize(".") 92 // Check the major version 93 if (requested[0] != defined[0]) { 94 throw new AssertionError("Cannot resolve to a single Glean version. Requested: ${details.requested.version}, A-C uses: ${project.ext.gleanVersion}") 95 } else { 96 // Enforce that all (transitive) dependencies are using the defined Glean version 97 details.useVersion project.ext.gleanVersion 98 } 99 } 100 } 101 102 resolutionStrategy.capabilitiesResolution.withCapability("org.mozilla.telemetry:glean-native") { 103 def toBeSelected = candidates.find { it.id instanceof ModuleComponentIdentifier && it.id.module.contains('geckoview') } 104 if (toBeSelected != null) { 105 select(toBeSelected) 106 } 107 because 'use GeckoView Glean instead of standalone Glean' 108 } 109 } 110 111 tasks.withType(KotlinCompile).configureEach { task -> 112 // Translate Kotlin messages like "w: ..." and "e: ..." into 113 // "...: warning: ..." and "...: error: ...", to make Treeherder understand. 114 def listener = { 115 116 if (it.startsWith("e: warnings found")) { 117 return 118 } 119 120 if (it.startsWith('w: ') || it.startsWith('e: ')) { 121 def matches = (it =~ /([ew]): (.+):(\d+):(\d+) (.*)/) 122 if (!matches) { 123 task.logger.quiet "kotlinc message format has changed!" 124 if (it.startsWith('w: ')) { 125 // For warnings, don't continue because we don't want to throw an 126 // exception. For errors, we want the exception so that the new error 127 // message format gets translated properly. 128 return 129 } 130 } 131 def (_, type, file, line, column, message) = matches[0] 132 type = (type == 'w') ? 'warning' : 'error' 133 // Use logger.lifecycle, which does not go through stderr again. 134 task.logger.lifecycle "$file:$line:$column: $type: $message" 135 } 136 } as StandardOutputListener 137 138 doFirst { 139 logging.addStandardErrorListener(listener) 140 } 141 doLast { 142 logging.removeStandardErrorListener(listener) 143 } 144 } 145 } 146 147 tasks.register('clean', Delete) { 148 delete rootProject.layout.buildDirectory 149 } 150 151 detekt { 152 input = files("$projectDir/app/src") 153 config = files("$projectDir/config/detekt.yml") 154 baseline = file("$projectDir/config/detekt-baseline.xml") 155 156 reports { 157 html { 158 enabled = true 159 destination = file("$projectDir/build/reports/detekt.html") 160 } 161 xml { 162 enabled = false 163 } 164 txt { 165 enabled = false 166 } 167 } 168 } 169 170 tasks.withType(Detekt).configureEach() { 171 autoCorrect = true 172 173 exclude "**/test/**" 174 exclude "**/androidTest/**" 175 exclude "**/build/**" 176 exclude "**/resources/**" 177 exclude "**/tmp/**" 178 179 reports { 180 custom { 181 reportId = "suppression-count" 182 outputLocation.set(file("$projectDir/build/reports/suppressions.txt")) 183 } 184 } 185 } 186 187 // Apply same path exclusions as for the main task 188 tasks.withType(DetektCreateBaselineTask).configureEach() { 189 exclude "**/test/**" 190 exclude "**/androidTest/**" 191 exclude "**/build/**" 192 exclude "**/resources/**" 193 exclude "**/tmp/**" 194 } 195 196 configurations { 197 ktlint 198 } 199 200 dependencies { 201 ktlint(libs.ktlint) { 202 attributes { 203 attribute(Bundling.BUNDLING_ATTRIBUTE, getObjects().named(Bundling, Bundling.EXTERNAL)) 204 } 205 } 206 detekt project(":components:tooling-detekt") 207 detekt project(":mozilla-detekt-rules") 208 detekt libs.detekt.cli 209 } 210 211 tasks.register('ktlint', JavaExec) { 212 group = "verification" 213 description = "Check Kotlin code style." 214 classpath = configurations.ktlint 215 mainClass.set("com.pinterest.ktlint.Main") 216 args "app/src/**/*.kt" 217 args "!**/build/**/*.kt" 218 args "--reporter=json,output=build/reports/ktlint/ktlint.json" 219 args "--reporter=plain" 220 } 221 222 tasks.register('ktlintFormat', JavaExec) { 223 description = "Fix Kotlin code style deviations." 224 classpath = configurations.ktlint 225 mainClass.set("com.pinterest.ktlint.Main") 226 args "-F" 227 args "app/src/**/*.kt" 228 args "!**/build/**/*.kt" 229 args "--reporter=json,output=build/reports/ktlint/ktlintFormat.json" 230 args "--reporter=plain" 231 jvmArgs("--add-opens", "java.base/java.lang=ALL-UNNAMED") 232 } 233 234 tasks.withType(Detekt.class).configureEach { 235 exclude("**/resources/**") 236 exclude("**/tmp/**") 237 } 238 239 tasks.register("listRepositories") { 240 def reposData = project.provider { 241 project.repositories.collect { repo -> 242 [name: repo.name, url: repo.url.toString()] 243 } 244 } 245 doLast { 246 println "Repositories:" 247 reposData.get().each { println "Name: " + it.name + "; url: " + it.url } 248 } 249 }