1 // Top-level build file where you can add configuration options common to all sub-projects/modules.
3 import io.gitlab.arturbosch.detekt.Detekt
4 import io.gitlab.arturbosch.detekt.DetektCreateBaselineTask
5 import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
6 import java.nio.file.Files
7 import java.nio.file.Paths
8 import java.nio.file.StandardCopyOption
11 // This logic is duplicated in the allprojects block: I don't know how to fix that.
13 gradle.mozconfig.substs.GRADLE_MAVEN_REPOSITORIES.each { repository ->
16 if (gradle.mozconfig.substs.ALLOW_INSECURE_GRADLE_REPOSITORIES) {
17 allowInsecureProtocol = true
24 classpath ComponentsDependencies.tools_androidgradle
25 classpath ComponentsDependencies.tools_kotlingradle
26 classpath FenixDependencies.tools_benchmarkgradle
27 classpath ComponentsDependencies.androidx_safeargs
28 classpath FenixDependencies.osslicenses_plugin
29 classpath "org.mozilla.telemetry:glean-gradle-plugin:${Versions.mozilla_glean}"
30 classpath "${ApplicationServicesConfig.groupId}:tooling-nimbus-gradle:${ApplicationServicesConfig.version}"
32 // NOTE: Do not place your application dependencies here; they belong
33 // in the individual module build.gradle files
36 // Variables in plugins {} aren't directly supported. Hack around it by setting an
37 // intermediate variable which can pull from FenixDependenciesPlugin.kt and be used later.
39 detekt_plugin = Versions.detekt
40 ksp_plugin = Versions.ksp_plugin
41 protobuf_plugin = FenixVersions.protobuf_plugin
42 python_envs_plugin = Versions.python_envs_plugin
47 id("io.gitlab.arturbosch.detekt").version("$detekt_plugin")
48 id("com.google.devtools.ksp").version("$ksp_plugin")
52 // This logic is duplicated in the buildscript block: I don't know how to fix that.
54 gradle.mozconfig.substs.GRADLE_MAVEN_REPOSITORIES.each { repository ->
57 if (gradle.mozconfig.substs.ALLOW_INSECURE_GRADLE_REPOSITORIES) {
58 allowInsecureProtocol = true
64 url "${gradle.mozconfig.topobjdir}/gradle/maven"
68 tasks.withType(KotlinCompile).configureEach {
69 kotlinOptions.allWarningsAsErrors = true
70 kotlinOptions.freeCompilerArgs += [
71 "-opt-in=kotlin.RequiresOptIn", "-Xjvm-default=all-compatibility"
79 jvmToolchain(config.jvmTargetCompatibility)
83 tasks.withType(KotlinCompile).configureEach { task ->
84 // Translate Kotlin messages like "w: ..." and "e: ..." into
85 // "...: warning: ..." and "...: error: ...", to make Treeherder understand.
88 if (it.startsWith("e: warnings found")) {
92 if (it.startsWith('w: ') || it.startsWith('e: ')) {
93 def matches = (it =~ /([ew]): (.+):(\d+):(\d+) (.*)/)
95 logger.quiet "kotlinc message format has changed!"
96 if (it.startsWith('w: ')) {
97 // For warnings, don't continue because we don't want to throw an
98 // exception. For errors, we want the exception so that the new error
99 // message format gets translated properly.
103 def (_, type, file, line, column, message) = matches[0]
104 type = (type == 'w') ? 'warning' : 'error'
105 // Use logger.lifecycle, which does not go through stderr again.
106 logger.lifecycle "$file:$line:$column: $type: $message"
108 } as StandardOutputListener
111 logging.addStandardErrorListener(listener)
114 logging.removeStandardErrorListener(listener)
119 tasks.register('clean', Delete) {
120 delete rootProject.layout.buildDirectory
124 input = files("$projectDir/app/src")
125 config = files("$projectDir/config/detekt.yml")
130 destination = file("$projectDir/build/reports/detekt.html")
141 tasks.withType(Detekt).configureEach() {
145 exclude "**/androidTest/**"
146 exclude "**/build/**"
147 exclude "**/resources/**"
151 // Apply same path exclusions as for the main task
152 tasks.withType(DetektCreateBaselineTask).configureEach() {
154 exclude "**/androidTest/**"
155 exclude "**/build/**"
156 exclude "**/resources/**"
165 ktlint("com.pinterest:ktlint:${Versions.ktlint}") {
167 attribute(Bundling.BUNDLING_ATTRIBUTE, getObjects().named(Bundling, Bundling.EXTERNAL))
171 detekt project(":mozilla-detekt-rules")
172 detekt "io.gitlab.arturbosch.detekt:detekt-cli:${Versions.detekt}"
175 tasks.register('ktlint', JavaExec) {
176 group = "verification"
177 description = "Check Kotlin code style."
178 classpath = configurations.ktlint
179 mainClass.set("com.pinterest.ktlint.Main")
180 args "app/src/**/*.kt", "!**/build/**/*.kt", "--baseline=ktlint-baseline.xml"
183 tasks.register('ktlintFormat', JavaExec) {
184 description = "Fix Kotlin code style deviations."
185 classpath = configurations.ktlint
186 mainClass.set("com.pinterest.ktlint.Main")
187 args "-F", "app/src/**/*.kt", "!**/build/**/*.kt", "--baseline=ktlint-baseline.xml"
188 jvmArgs("--add-opens", "java.base/java.lang=ALL-UNNAMED")
191 tasks.withType(Detekt.class).configureEach {
192 exclude("**/resources/**")
196 tasks.register("listRepositories") {
198 println "Repositories:"
199 project.repositories.each { println "Name: " + it.name + "; url: " + it.url }
203 // Task to copy generated baseline profile to the app module nightly variant.
204 tasks.register("copyBaselineProfile", DefaultTask) {
206 File profileFile = fileTree('benchmark/build/outputs') {
207 include '**/*baseline-prof.txt'
209 def destinationPath = Paths.get("app", "src", "nightly", "baselineProfiles", "baseline-prof.txt")
210 File destinationDir = destinationPath.toFile().parentFile
211 if (!destinationDir.exists()) {
212 destinationDir.mkdirs()
214 Files.copy(profileFile.toPath(), destinationPath, StandardCopyOption.REPLACE_EXISTING)