From 553c84904e0dccafb6006f88e83f0835b8b63c34 Mon Sep 17 00:00:00 2001 From: Tom Tresansky Date: Thu, 6 Jun 2024 15:07:53 -0400 Subject: [PATCH 1/7] Add proguard support for NiA --- .../AbstractAndroidSoftwarePlugin.java | 17 +++++++++-- .../android/AndroidSoftwareBuildType.java | 29 +++++++++++++++++++ .../experimental/android/ProguardFile.java | 26 +++++++++++++++++ .../android/extensions/testing/Roborazzi.java | 2 ++ .../StandaloneAndroidLibraryPlugin.java | 15 ---------- .../experimental/android/nia/NiaSupport.java | 8 ++--- 6 files changed, 75 insertions(+), 22 deletions(-) create mode 100644 unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/ProguardFile.java create mode 100644 unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/extensions/testing/Roborazzi.java diff --git a/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/AbstractAndroidSoftwarePlugin.java b/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/AbstractAndroidSoftwarePlugin.java index 8dd150e0..6e221259 100644 --- a/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/AbstractAndroidSoftwarePlugin.java +++ b/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/AbstractAndroidSoftwarePlugin.java @@ -4,6 +4,8 @@ import com.android.build.api.dsl.BuildType; import com.android.build.api.dsl.CommonExtension; import com.android.build.api.dsl.UnitTestOptions; +import com.android.build.gradle.BaseExtension; +import com.android.build.gradle.ProguardFiles; import com.google.devtools.ksp.gradle.KspExtension; import org.gradle.api.Action; import org.gradle.api.JavaVersion; @@ -17,6 +19,7 @@ import org.gradle.api.provider.Property; import org.jetbrains.kotlin.gradle.dsl.KotlinAndroidProjectExtension; +import java.io.File; import java.util.Objects; import static org.gradle.api.experimental.android.extensions.ComposeSupport.configureCompose; @@ -100,8 +103,8 @@ protected void linkDslModelToPlugin(Project project, AndroidSoftware dslModel, C // Link build types AndroidSoftwareBuildTypes modelBuildType = dslModel.getBuildTypes(); NamedDomainObjectContainer androidBuildTypes = android.getBuildTypes(); - linkBuildType(androidBuildTypes.getByName("debug"), modelBuildType.getDebug(), configurations); - linkBuildType(androidBuildTypes.getByName("release"), modelBuildType.getRelease(), configurations); + linkBuildType(androidBuildTypes.getByName("debug"), modelBuildType.getDebug(), configurations, android); + linkBuildType(androidBuildTypes.getByName("release"), modelBuildType.getRelease(), configurations, android); configureTesting(project, dslModel, android); @@ -197,9 +200,17 @@ protected void configureKotlinSerialization(Project project, AndroidSoftware dsl /** * Links build types from the model to the android extension. */ - protected void linkBuildType(BuildType buildType, AndroidSoftwareBuildType model, ConfigurationContainer configurations) { + protected void linkBuildType(BuildType buildType, AndroidSoftwareBuildType model, ConfigurationContainer configurations, CommonExtension android) { buildType.setMinifyEnabled(model.getMinify().getEnabled().get()); linkBuildTypeDependencies(buildType, model.getDependencies(), configurations); + + model.getDefaultProguardFiles().get().forEach(proguardFile -> { + File defaultProguardFile = android.getDefaultProguardFile(proguardFile.getName().get()); + buildType.proguardFile(defaultProguardFile); + }); + model.getProguardFiles().get().forEach(proguardFile -> { + buildType.proguardFile(proguardFile.getName().get()); + }); } @SuppressWarnings("UnstableApiUsage") diff --git a/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/AndroidSoftwareBuildType.java b/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/AndroidSoftwareBuildType.java index 9912c533..55cb11cd 100644 --- a/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/AndroidSoftwareBuildType.java +++ b/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/AndroidSoftwareBuildType.java @@ -2,10 +2,15 @@ import org.gradle.api.Action; import org.gradle.api.experimental.android.extensions.Minify; +import org.gradle.api.model.ObjectFactory; +import org.gradle.api.provider.ListProperty; import org.gradle.api.tasks.Nested; +import org.gradle.declarative.dsl.model.annotations.Adding; import org.gradle.declarative.dsl.model.annotations.Configuring; import org.gradle.declarative.dsl.model.annotations.Restricted; +import javax.inject.Inject; + @Restricted public interface AndroidSoftwareBuildType { /** @@ -20,4 +25,28 @@ public interface AndroidSoftwareBuildType { default void minify(Action action) { action.execute(getMinify()); } + + ListProperty getProguardFiles(); + ListProperty getDefaultProguardFiles(); + + @Adding + default ProguardFile proguardFile(Action configure) { + ProguardFile proguardFile = getObjectFactory().newInstance(ProguardFile.class); + proguardFile.getName().convention(""); + configure.execute(proguardFile); + getProguardFiles().add(proguardFile); + return proguardFile; + } + + @Adding + default ProguardFile defaultProguardFile(Action configure) { + ProguardFile proguardFile = getObjectFactory().newInstance(ProguardFile.class); + proguardFile.getName().convention(""); + configure.execute(proguardFile); + getDefaultProguardFiles().add(proguardFile); + return proguardFile; + } + + @Inject + ObjectFactory getObjectFactory(); } diff --git a/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/ProguardFile.java b/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/ProguardFile.java new file mode 100644 index 00000000..cf3c7cfc --- /dev/null +++ b/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/ProguardFile.java @@ -0,0 +1,26 @@ +/* + * Copyright 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.api.experimental.android; + +import org.gradle.api.provider.Property; +import org.gradle.declarative.dsl.model.annotations.Restricted; + +@Restricted +public interface ProguardFile { + @Restricted + Property getName(); +} diff --git a/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/extensions/testing/Roborazzi.java b/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/extensions/testing/Roborazzi.java new file mode 100644 index 00000000..c3ad56f9 --- /dev/null +++ b/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/extensions/testing/Roborazzi.java @@ -0,0 +1,2 @@ +package org.gradle.api.experimental.android.extensions.testing;public interface Roborazzi { +} diff --git a/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/library/StandaloneAndroidLibraryPlugin.java b/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/library/StandaloneAndroidLibraryPlugin.java index b6f1b351..381b0839 100644 --- a/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/library/StandaloneAndroidLibraryPlugin.java +++ b/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/library/StandaloneAndroidLibraryPlugin.java @@ -5,10 +5,8 @@ import com.android.build.api.variant.LibraryAndroidComponentsExtension; import com.google.protobuf.gradle.ProtobufExtension; import org.gradle.api.Project; -import org.gradle.api.artifacts.Configuration; import org.gradle.api.artifacts.ConfigurationContainer; import org.gradle.api.artifacts.Dependency; -import org.gradle.api.artifacts.dsl.DependencyCollector; import org.gradle.api.experimental.android.AbstractAndroidSoftwarePlugin; import org.gradle.api.experimental.android.AndroidSoftware; import org.gradle.api.experimental.android.nia.NiaSupport; @@ -118,19 +116,6 @@ private static String getProtocDepGAV(AndroidLibrary dslModel) { return protocDep.getGroup() + ":" + protocDep.getName() + ":" + protocDep.getVersion(); } - private File resolveSingleDependency(Project project, DependencyCollector dependencyCollector) { - Configuration resolver = project.getConfigurations().detachedConfiguration(); - resolver.setCanBeResolved(true); - resolver.fromDependencyCollector(dependencyCollector); - - Set deps = dependencyCollector.getDependencies().get(); - Preconditions.checkState(deps.size() == 1, "Should have a single dependency, but had: " + deps.size()); - - Set files = resolver.resolve(); - Preconditions.checkState(files.size() == 1, "Should have resolved a single file, but resolved: " + files.size()); - return files.iterator().next(); - } - @SuppressWarnings("UnstableApiUsage") private void linkCommonDependencies(AndroidLibraryDependencies dependencies, ConfigurationContainer configurations) { super.linkCommonDependencies(dependencies, configurations); diff --git a/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/nia/NiaSupport.java b/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/nia/NiaSupport.java index 4c0a664e..cd85a7f5 100644 --- a/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/nia/NiaSupport.java +++ b/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/nia/NiaSupport.java @@ -81,7 +81,7 @@ public static void configureNiaApplication(Project project, AndroidApplication d testOptions.setAnimationsDisabled(true); configureBadgingTasks(project, androidAppComponents); - configureDependencyGuard(project, dslModel, androidApp); + configureDependencyGuard(project, dslModel); } @SuppressWarnings("UnstableApiUsage") @@ -341,8 +341,8 @@ private static void configureJacoco(Project project, AndroidSoftware dslModel, C JacocoPluginExtension jacocoPluginExtension = project.getExtensions().getByType(JacocoPluginExtension.class); jacocoPluginExtension.setToolVersion(dslModel.getTesting().getJacoco().getVersion().get()); - LibraryAndroidComponentsExtension androidLibComponents = project.getExtensions().getByType(LibraryAndroidComponentsExtension.class); - androidLibComponents.onVariants(androidLibComponents.selector().all(), variant -> { + AndroidComponentsExtension androidComponentsExtension = project.getExtensions().getByType(AndroidComponentsExtension.class); + androidComponentsExtension.onVariants(androidComponentsExtension.selector().all(), variant -> { final String testTaskName = "test" + StringUtils.capitalize(variant.getName()) + "UnitTest"; final File buildDir = project.getLayout().getBuildDirectory().get().getAsFile(); project.getTasks().register("jacoco" + StringUtils.capitalize(testTaskName) + "Report", JacocoReport.class, task -> { @@ -382,7 +382,7 @@ private static void configureJacoco(Project project, AndroidSoftware dslModel, C } } - private static void configureDependencyGuard(Project project, AndroidApplication dslModel, CommonExtension android) { + private static void configureDependencyGuard(Project project, AndroidApplication dslModel) { if (dslModel.getDependencyGuard().getEnabled().get()) { // Slight change of behavior here - NiA just applies this plugin to all applications, which seems unnecessary project.getPlugins().apply("com.dropbox.dependency-guard"); From 27328d74ad55e34bb9ba90d453bf19f186e36f37 Mon Sep 17 00:00:00 2001 From: Tom Tresansky Date: Thu, 6 Jun 2024 15:08:04 -0400 Subject: [PATCH 2/7] Add roborazzi support for NiA --- .../unified-plugin/gradle/libs.versions.toml | 2 ++ .../plugin-android/build.gradle.kts | 1 + .../AbstractAndroidSoftwarePlugin.java | 14 +++++++--- .../android/extensions/testing/Jacoco.java | 3 --- .../android/extensions/testing/Roborazzi.java | 26 ++++++++++++++++++- .../android/extensions/testing/Testing.java | 10 +++++++ 6 files changed, 49 insertions(+), 7 deletions(-) diff --git a/unified-prototype/unified-plugin/gradle/libs.versions.toml b/unified-prototype/unified-plugin/gradle/libs.versions.toml index 2f22dbed..5309935f 100644 --- a/unified-prototype/unified-plugin/gradle/libs.versions.toml +++ b/unified-prototype/unified-plugin/gradle/libs.versions.toml @@ -10,6 +10,7 @@ android = "8.3.0" androidTools = "31.3.0" hilt = "2.50" room = "2.6.1" +roborazzi = "1.7.0" #Other Libs apache-commons = "3.3.1" @@ -38,3 +39,4 @@ apache-commons-lang = { module = "org.apache.commons:commons-lang3", version.ref dependency-guard-plugin = { module = "com.dropbox.dependency-guard:com.dropbox.dependency-guard.gradle.plugin", version.ref = "dependency-guard"} truth = { module = "com.google.truth:truth", version.ref = "truth" } protobuf-plugin = { module = "com.google.protobuf:protobuf-gradle-plugin", version.ref = "protobuf" } +roborazzi-plugin = { module = "io.github.takahirom.roborazzi:roborazzi-gradle-plugin", version.ref = "roborazzi" } diff --git a/unified-prototype/unified-plugin/plugin-android/build.gradle.kts b/unified-prototype/unified-plugin/plugin-android/build.gradle.kts index a4d37888..4e7de481 100644 --- a/unified-prototype/unified-plugin/plugin-android/build.gradle.kts +++ b/unified-prototype/unified-plugin/plugin-android/build.gradle.kts @@ -20,6 +20,7 @@ dependencies { implementation(libs.kotlin.serialization.plugin) implementation(libs.room.plugin) implementation(libs.protobuf.plugin) + implementation(libs.roborazzi.plugin) implementation(libs.apache.commons.lang) implementation(libs.android.tools.common) diff --git a/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/AbstractAndroidSoftwarePlugin.java b/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/AbstractAndroidSoftwarePlugin.java index 6e221259..13cd0ebb 100644 --- a/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/AbstractAndroidSoftwarePlugin.java +++ b/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/AbstractAndroidSoftwarePlugin.java @@ -4,8 +4,6 @@ import com.android.build.api.dsl.BuildType; import com.android.build.api.dsl.CommonExtension; import com.android.build.api.dsl.UnitTestOptions; -import com.android.build.gradle.BaseExtension; -import com.android.build.gradle.ProguardFiles; import com.google.devtools.ksp.gradle.KspExtension; import org.gradle.api.Action; import org.gradle.api.JavaVersion; @@ -20,7 +18,6 @@ import org.jetbrains.kotlin.gradle.dsl.KotlinAndroidProjectExtension; import java.io.File; -import java.util.Objects; import static org.gradle.api.experimental.android.extensions.ComposeSupport.configureCompose; @@ -61,6 +58,7 @@ public void apply(Project project) { dslModel.getTesting().getTestOptions().getReturnDefaultValues().convention(false); dslModel.getTesting().getJacoco().getEnabled().convention(false); dslModel.getTesting().getJacoco().getVersion().convention("0.8.7"); + dslModel.getTesting().getRoborazzi().getEnabled().convention(false); } /** @@ -126,6 +124,8 @@ protected void configureHilt(Project project, AndroidSoftware dslModel, CommonEx // Add support for Hilt project.getPlugins().apply("dagger.hilt.android.plugin"); project.getDependencies().add("implementation", "com.google.dagger:hilt-android:2.50"); + + project.getDependencies().add("kspTest", "com.google.dagger:hilt-android-compiler:2.50"); } } @@ -181,6 +181,14 @@ protected void configureTesting(Project project, AndroidSoftware dslModel, Commo ConfigurationContainer configurations = project.getConfigurations(); configurations.getByName("testImplementation").fromDependencyCollector(testDependencies.getImplementation()); configurations.getByName("androidTestImplementation").fromDependencyCollector(testDependencies.getAndroidImplementation()); + + configureRoborazzi(project, dslModel); + } + + protected void configureRoborazzi(Project project, AndroidSoftware dslModel) { + if (dslModel.getTesting().getRoborazzi().getEnabled().get()) { + project.getPlugins().apply("io.github.takahirom.roborazzi"); + } } @SuppressWarnings("UnstableApiUsage") diff --git a/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/extensions/testing/Jacoco.java b/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/extensions/testing/Jacoco.java index 3711d0cc..0f45e478 100644 --- a/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/extensions/testing/Jacoco.java +++ b/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/extensions/testing/Jacoco.java @@ -8,9 +8,6 @@ */ @Restricted public interface Jacoco { - /** - * Internal property purposely not exposed to the DSL. - */ @Restricted Property getEnabled(); diff --git a/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/extensions/testing/Roborazzi.java b/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/extensions/testing/Roborazzi.java index c3ad56f9..8731c0e9 100644 --- a/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/extensions/testing/Roborazzi.java +++ b/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/extensions/testing/Roborazzi.java @@ -1,2 +1,26 @@ -package org.gradle.api.experimental.android.extensions.testing;public interface Roborazzi { +/* + * Copyright 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.api.experimental.android.extensions.testing; + +import org.gradle.api.provider.Property; +import org.gradle.declarative.dsl.model.annotations.Restricted; + +@Restricted +public interface Roborazzi { + @Restricted + Property getEnabled(); } diff --git a/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/extensions/testing/Testing.java b/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/extensions/testing/Testing.java index 4e04ea3f..7d72a83f 100644 --- a/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/extensions/testing/Testing.java +++ b/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/extensions/testing/Testing.java @@ -20,6 +20,16 @@ default void jacoco(Action action) { jacoco.getEnabled().set(true); } + @Nested + Roborazzi getRoborazzi(); + + @Configuring + default void roborazzi(Action action) { + Roborazzi roborazzi = getRoborazzi(); + roborazzi.getEnabled().set(true); + action.execute(roborazzi); + } + @Nested TestOptions getTestOptions(); From 07869f443c80a2e1b60d491be55b4d74e37cce10 Mon Sep 17 00:00:00 2001 From: Tom Tresansky Date: Mon, 10 Jun 2024 07:58:55 -0400 Subject: [PATCH 3/7] Add Firebase support for NiA --- .../unified-plugin/gradle/libs.versions.toml | 6 ++++ .../plugin-android/build.gradle.kts | 3 ++ .../application/AndroidApplication.java | 11 +++++++ .../StandaloneAndroidApplicationPlugin.java | 3 ++ .../android/extensions/Firebase.java | 32 +++++++++++++++++++ .../experimental/android/nia/NiaSupport.java | 21 ++++++++++++ 6 files changed, 76 insertions(+) create mode 100644 unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/extensions/Firebase.java diff --git a/unified-prototype/unified-plugin/gradle/libs.versions.toml b/unified-prototype/unified-plugin/gradle/libs.versions.toml index 5309935f..4b29cf70 100644 --- a/unified-prototype/unified-plugin/gradle/libs.versions.toml +++ b/unified-prototype/unified-plugin/gradle/libs.versions.toml @@ -8,6 +8,9 @@ ksp = "1.9.23-1.0.20" # Find latest version at: https://developer.android.com/reference/tools/gradle-api android = "8.3.0" androidTools = "31.3.0" +firebaseCrashlytics = "2.9.9" +firebasePerf = "1.4.2" +gms = "4.4.1" hilt = "2.50" room = "2.6.1" roborazzi = "1.7.0" @@ -29,6 +32,9 @@ kotlin-serialization-plugin = { module = "org.jetbrains.kotlin:kotlin-serializat android-agp-application = { module = "com.android.application:com.android.application.gradle.plugin", version.ref = "android" } android-kotlin-android = { module = "org.jetbrains.kotlin.android:org.jetbrains.kotlin.android.gradle.plugin", version.ref = "kotlin" } android-tools-common = { module = "com.android.tools:common", version.ref = "androidTools" } +firebase-perf-plugin = { module = "com.google.firebase:perf-plugin", version.ref = "firebasePerf" } +firebase-crashlytics-plugin = { module = "com.google.firebase:firebase-crashlytics-gradle", version.ref = "firebaseCrashlytics" } +google-services-plugin = { module = "com.google.gms.google-services:com.google.gms.google-services.gradle.plugin", version.ref = "gms" } hilt-android-plugin = { module = "com.google.dagger:hilt-android-gradle-plugin", version.ref = "hilt" } hilt-android = { module = "com.google.dagger:hilt-android", version.ref = "hilt"} hilt-compiler = { module = "com.google.dagger:hilt-android-compiler", version.ref = "hilt" } diff --git a/unified-prototype/unified-plugin/plugin-android/build.gradle.kts b/unified-prototype/unified-plugin/plugin-android/build.gradle.kts index 4e7de481..a4c9f717 100644 --- a/unified-prototype/unified-plugin/plugin-android/build.gradle.kts +++ b/unified-prototype/unified-plugin/plugin-android/build.gradle.kts @@ -21,6 +21,9 @@ dependencies { implementation(libs.room.plugin) implementation(libs.protobuf.plugin) implementation(libs.roborazzi.plugin) + implementation(libs.google.services.plugin) + implementation(libs.firebase.perf.plugin) + implementation(libs.firebase.crashlytics.plugin) implementation(libs.apache.commons.lang) implementation(libs.android.tools.common) diff --git a/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/application/AndroidApplication.java b/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/application/AndroidApplication.java index 07168808..99ea09b1 100644 --- a/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/application/AndroidApplication.java +++ b/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/application/AndroidApplication.java @@ -20,6 +20,7 @@ import org.gradle.api.Action; import org.gradle.api.experimental.android.AndroidSoftware; import org.gradle.api.experimental.android.extensions.DependencyGuard; +import org.gradle.api.experimental.android.extensions.Firebase; import org.gradle.api.provider.Property; import org.gradle.api.tasks.Nested; import org.gradle.declarative.dsl.model.annotations.Configuring; @@ -72,4 +73,14 @@ default void dependencyGuard(Action action) { dependencyGuard.getEnabled().set(true); action.execute(dependencyGuard); } + + @Nested + Firebase getFirebase(); + + @Configuring + default void firebase(Action action) { + Firebase firebase = getFirebase(); + firebase.getEnabled().set(true); + action.execute(firebase); + } } diff --git a/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/application/StandaloneAndroidApplicationPlugin.java b/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/application/StandaloneAndroidApplicationPlugin.java index b13ae6a0..cecad341 100644 --- a/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/application/StandaloneAndroidApplicationPlugin.java +++ b/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/application/StandaloneAndroidApplicationPlugin.java @@ -33,6 +33,9 @@ public void apply(Project project) { // Setup application-specific conventions dslModel.getDependencyGuard().getEnabled().convention(false); + dslModel.getFirebase().getEnabled().convention(false); + dslModel.getFirebase().getVersion().convention("32.4.0"); + // Register an afterEvaluate listener before we apply the Android plugin to ensure we can // run actions before Android does. project.afterEvaluate(p -> linkDslModelToPlugin(p, dslModel)); diff --git a/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/extensions/Firebase.java b/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/extensions/Firebase.java new file mode 100644 index 00000000..3e5d6e28 --- /dev/null +++ b/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/extensions/Firebase.java @@ -0,0 +1,32 @@ +/* + * Copyright 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.api.experimental.android.extensions; + +import org.gradle.api.provider.Property; +import org.gradle.declarative.dsl.model.annotations.Restricted; + +@Restricted +public interface Firebase { + @Restricted + Property getEnabled(); + + @Restricted + Property getVersion(); + + @Restricted + Property getMappingFileUploadEnabled(); +} diff --git a/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/nia/NiaSupport.java b/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/nia/NiaSupport.java index cd85a7f5..d7af23b8 100644 --- a/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/nia/NiaSupport.java +++ b/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/nia/NiaSupport.java @@ -18,6 +18,7 @@ import com.android.build.api.variant.LibraryAndroidComponentsExtension; import com.android.build.gradle.BaseExtension; import com.dropbox.gradle.plugins.dependencyguard.DependencyGuardPluginExtension; +import com.google.firebase.crashlytics.buildtools.gradle.CrashlyticsExtension; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.text.WordUtils; import org.gradle.api.*; @@ -82,6 +83,7 @@ public static void configureNiaApplication(Project project, AndroidApplication d configureBadgingTasks(project, androidAppComponents); configureDependencyGuard(project, dslModel); + configureFirebase(project, dslModel, androidApp); } @SuppressWarnings("UnstableApiUsage") @@ -102,6 +104,25 @@ private static void configureNia(Project project, AndroidSoftware dslModel, Comm configureFeature(project, dslModel, android); } + @SuppressWarnings("UnstableApiUsage") + private static void configureFirebase(Project project, AndroidApplication dslModel, ApplicationExtension androidApp) { + if (dslModel.getFirebase().getEnabled().get()) { + project.getPlugins().apply("com.google.gms.google-services"); + project.getPlugins().apply("com.google.firebase.firebase-perf"); + project.getPlugins().apply("com.google.firebase.crashlytics"); + + dslModel.getDependencies().getImplementation().add(project.getDependencies().platform("com.google.firebase:firebase-bom:" + dslModel.getFirebase().getVersion().get())); + dslModel.getDependencies().getImplementation().add("com.google.firebase:firebase-analytics-ktx"); + dslModel.getDependencies().getImplementation().add("com.google.firebase:firebase-perf-ktx"); + dslModel.getDependencies().getImplementation().add("com.google.firebase:firebase-crashlytics-ktx"); + + androidApp.getBuildTypes().configureEach(buildType -> { + CrashlyticsExtension crashlyticsExtension = buildType.getExtensions().getByType(CrashlyticsExtension.class); + crashlyticsExtension.setMappingFileUploadEnabled(dslModel.getFirebase().getMappingFileUploadEnabled().get()); + }); + } + } + private static void configureBadgingTasks(Project project, ApplicationAndroidComponentsExtension androidAppComponents) { BaseExtension baseExtension = project.getExtensions().getByType(BaseExtension.class); From eeea165eca79341b84bbb8a3fbb4421e4d220843 Mon Sep 17 00:00:00 2001 From: Tom Tresansky Date: Mon, 10 Jun 2024 11:04:39 -0400 Subject: [PATCH 4/7] Add licenses feature, some minor adjustments and cleanup --- .../unified-plugin/gradle/libs.versions.toml | 6 ++-- .../plugin-android/build.gradle.kts | 1 + .../AbstractAndroidSoftwarePlugin.java | 18 ++++------ .../experimental/android/AndroidSoftware.java | 15 +++++++++ .../experimental/android/AndroidSupport.java | 33 +++++++++++++++++++ .../StandaloneAndroidApplicationPlugin.java | 5 +++ .../StandaloneAndroidLibraryPlugin.java | 2 ++ .../experimental/android/nia/Licenses.java | 28 ++++++++++++++++ .../experimental/android/nia/NiaSupport.java | 16 ++++++++- 9 files changed, 109 insertions(+), 15 deletions(-) create mode 100644 unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/AndroidSupport.java create mode 100644 unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/nia/Licenses.java diff --git a/unified-prototype/unified-plugin/gradle/libs.versions.toml b/unified-prototype/unified-plugin/gradle/libs.versions.toml index 4b29cf70..b94eafad 100644 --- a/unified-prototype/unified-plugin/gradle/libs.versions.toml +++ b/unified-prototype/unified-plugin/gradle/libs.versions.toml @@ -13,13 +13,14 @@ firebasePerf = "1.4.2" gms = "4.4.1" hilt = "2.50" room = "2.6.1" -roborazzi = "1.7.0" #Other Libs apache-commons = "3.3.1" dependency-guard = "0.4.3" truth = "1.4.2" protobuf = "0.9.4" +oss-licenses = "0.10.6" +roborazzi = "1.7.0" [libraries] # Kotlin Libs @@ -43,6 +44,7 @@ room-plugin = { module = "androidx.room:room-gradle-plugin", version.ref = "room #Other Libs apache-commons-lang = { module = "org.apache.commons:commons-lang3", version.ref = "apache-commons" } dependency-guard-plugin = { module = "com.dropbox.dependency-guard:com.dropbox.dependency-guard.gradle.plugin", version.ref = "dependency-guard"} -truth = { module = "com.google.truth:truth", version.ref = "truth" } +oss-licenses-plugin = { group = "com.google.android.gms", name = "oss-licenses-plugin", version.ref = "oss-licenses" } protobuf-plugin = { module = "com.google.protobuf:protobuf-gradle-plugin", version.ref = "protobuf" } roborazzi-plugin = { module = "io.github.takahirom.roborazzi:roborazzi-gradle-plugin", version.ref = "roborazzi" } +truth = { module = "com.google.truth:truth", version.ref = "truth" } diff --git a/unified-prototype/unified-plugin/plugin-android/build.gradle.kts b/unified-prototype/unified-plugin/plugin-android/build.gradle.kts index a4c9f717..2d3bc56e 100644 --- a/unified-prototype/unified-plugin/plugin-android/build.gradle.kts +++ b/unified-prototype/unified-plugin/plugin-android/build.gradle.kts @@ -24,6 +24,7 @@ dependencies { implementation(libs.google.services.plugin) implementation(libs.firebase.perf.plugin) implementation(libs.firebase.crashlytics.plugin) + implementation(libs.oss.licenses.plugin) implementation(libs.apache.commons.lang) implementation(libs.android.tools.common) diff --git a/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/AbstractAndroidSoftwarePlugin.java b/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/AbstractAndroidSoftwarePlugin.java index 13cd0ebb..c330192e 100644 --- a/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/AbstractAndroidSoftwarePlugin.java +++ b/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/AbstractAndroidSoftwarePlugin.java @@ -5,7 +5,6 @@ import com.android.build.api.dsl.CommonExtension; import com.android.build.api.dsl.UnitTestOptions; import com.google.devtools.ksp.gradle.KspExtension; -import org.gradle.api.Action; import org.gradle.api.JavaVersion; import org.gradle.api.NamedDomainObjectContainer; import org.gradle.api.Plugin; @@ -14,11 +13,11 @@ import org.gradle.api.experimental.android.extensions.testing.AndroidTestDependencies; import org.gradle.api.experimental.android.extensions.testing.TestOptions; import org.gradle.api.experimental.android.extensions.testing.Testing; -import org.gradle.api.provider.Property; import org.jetbrains.kotlin.gradle.dsl.KotlinAndroidProjectExtension; import java.io.File; +import static org.gradle.api.experimental.android.AndroidSupport.ifPresent; import static org.gradle.api.experimental.android.extensions.ComposeSupport.configureCompose; public abstract class AbstractAndroidSoftwarePlugin implements Plugin { @@ -52,6 +51,7 @@ public void apply(Project project) { dslModel.getHilt().getEnabled().convention(false); dslModel.getRoom().getEnabled().convention(false); dslModel.getRoom().getVersion().convention("2.6.1"); + dslModel.getLicenses().getEnabled().convention(false); // Setup Test Options conventions dslModel.getTesting().getTestOptions().getIncludeAndroidResources().convention(false); @@ -108,12 +108,12 @@ protected void linkDslModelToPlugin(Project project, AndroidSoftware dslModel, C configureKotlinSerialization(project, dslModel); configureDesugaring(project, dslModel, android); - configureHilt(project, dslModel, android); + configureHilt(project, dslModel); configureCompose(project, dslModel, android); - configureRoom(project, dslModel, android); + configureRoom(project, dslModel); } - protected void configureHilt(Project project, AndroidSoftware dslModel, CommonExtension android) { + protected void configureHilt(Project project, AndroidSoftware dslModel) { if (dslModel.getHilt().getEnabled().get()) { project.getLogger().info("Hilt is enabled in: " + project.getPath()); @@ -130,7 +130,7 @@ protected void configureHilt(Project project, AndroidSoftware dslModel, CommonEx } @SuppressWarnings("UnstableApiUsage") - protected void configureRoom(Project project, AndroidSoftware dslModel, CommonExtension android) { + protected void configureRoom(Project project, AndroidSoftware dslModel) { if (dslModel.getRoom().getEnabled().get()) { project.getLogger().info("Room is enabled in: " + project.getPath()); @@ -228,10 +228,4 @@ protected void linkBuildTypeDependencies(BuildType buildType, AndroidSoftwareDep configurations.getByName(name + "CompileOnly").fromDependencyCollector(dependencies.getCompileOnly()); configurations.getByName(name + "RuntimeOnly").fromDependencyCollector(dependencies.getRuntimeOnly()); } - - protected void ifPresent(Property property, Action action) { - if (property.isPresent()) { - action.execute(property.get()); - } - } } diff --git a/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/AndroidSoftware.java b/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/AndroidSoftware.java index b921f79c..2791c9b1 100644 --- a/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/AndroidSoftware.java +++ b/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/AndroidSoftware.java @@ -10,6 +10,7 @@ import org.gradle.api.experimental.android.extensions.Room; import org.gradle.api.experimental.android.extensions.testing.Testing; import org.gradle.api.experimental.android.nia.Feature; +import org.gradle.api.experimental.android.nia.Licenses; import org.gradle.api.provider.Property; import org.gradle.api.tasks.Nested; import org.gradle.declarative.dsl.model.annotations.Configuring; @@ -119,4 +120,18 @@ default void feature(Action action) { feature.getEnabled().set(true); action.execute(feature); } + + /** + * Support for NiA projects using the com.google.android.gms.oss-licenses-plugin + * TODO: This is a temporary solution until we have a better way of applying plugins + */ + @Nested + Licenses getLicenses(); + + @Configuring + default void licenses(Action action) { + Licenses licenses = getLicenses(); + licenses.getEnabled().set(true); + action.execute(licenses); + } } diff --git a/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/AndroidSupport.java b/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/AndroidSupport.java new file mode 100644 index 00000000..4c07d45d --- /dev/null +++ b/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/AndroidSupport.java @@ -0,0 +1,33 @@ +/* + * Copyright 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.api.experimental.android; + +import org.gradle.api.Action; +import org.gradle.api.provider.Property; + +/** + * Static util class containing common methods. + */ +public class AndroidSupport { + private AndroidSupport() { /* not instantiable */ } + + public static void ifPresent(Property property, Action action) { + if (property.isPresent()) { + action.execute(property.get()); + } + } +} diff --git a/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/application/StandaloneAndroidApplicationPlugin.java b/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/application/StandaloneAndroidApplicationPlugin.java index cecad341..89dade0d 100644 --- a/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/application/StandaloneAndroidApplicationPlugin.java +++ b/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/application/StandaloneAndroidApplicationPlugin.java @@ -10,6 +10,8 @@ import org.gradle.api.experimental.android.nia.NiaSupport; import org.gradle.api.internal.plugins.software.SoftwareType; +import static org.gradle.api.experimental.android.AndroidSupport.ifPresent; + /** * Creates a declarative {@link AndroidApplication} DSL model, applies the official Android plugin, * and links the declarative model to the official plugin. @@ -36,6 +38,9 @@ public void apply(Project project) { dslModel.getFirebase().getEnabled().convention(false); dslModel.getFirebase().getVersion().convention("32.4.0"); + dslModel.getBuildTypes().getDebug().getApplicationIdSuffix().convention((String) null); + dslModel.getBuildTypes().getRelease().getApplicationIdSuffix().convention((String) null); + // Register an afterEvaluate listener before we apply the Android plugin to ensure we can // run actions before Android does. project.afterEvaluate(p -> linkDslModelToPlugin(p, dslModel)); diff --git a/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/library/StandaloneAndroidLibraryPlugin.java b/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/library/StandaloneAndroidLibraryPlugin.java index 381b0839..27a31c17 100644 --- a/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/library/StandaloneAndroidLibraryPlugin.java +++ b/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/library/StandaloneAndroidLibraryPlugin.java @@ -17,6 +17,8 @@ import java.util.Objects; import java.util.Set; +import static org.gradle.api.experimental.android.AndroidSupport.ifPresent; + /** * Creates a declarative {@link AndroidLibrary} DSL model, applies the official Android plugin, * and links the declarative model to the official plugin. diff --git a/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/nia/Licenses.java b/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/nia/Licenses.java new file mode 100644 index 00000000..abf49fc5 --- /dev/null +++ b/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/nia/Licenses.java @@ -0,0 +1,28 @@ +/* + * Copyright 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.api.experimental.android.nia; + +import org.gradle.api.provider.Property; +import org.gradle.declarative.dsl.model.annotations.Restricted; + +@Restricted +public interface Licenses { + /** + * Internal property purposely not exposed to the DSL. + */ + Property getEnabled(); +} diff --git a/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/nia/NiaSupport.java b/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/nia/NiaSupport.java index d7af23b8..f0a13df2 100644 --- a/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/nia/NiaSupport.java +++ b/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/nia/NiaSupport.java @@ -47,6 +47,8 @@ import java.util.function.BiConsumer; import java.util.stream.Collectors; +import static org.gradle.api.experimental.android.AndroidSupport.ifPresent; + // TODO: This class should be moved to the NiA project /** * This is a utility class that configures an Android project with conventions @@ -67,6 +69,8 @@ public static void configureNiaLibrary(Project project, AndroidLibrary dslModel) LibraryExtension androidLib = project.getExtensions().getByType(LibraryExtension.class); LibraryAndroidComponentsExtension androidLibComponents = project.getExtensions().getByType(LibraryAndroidComponentsExtension.class); + androidLib.setResourcePrefix(buildResourcePrefix(project)); + configureNia(project, dslModel, androidLib, androidLibComponents); disableUnnecessaryAndroidTests(project, androidLibComponents); } @@ -81,7 +85,11 @@ public static void configureNiaApplication(Project project, AndroidApplication d TestOptions testOptions = androidApp.getTestOptions(); testOptions.setAnimationsDisabled(true); + ifPresent(dslModel.getBuildTypes().getDebug().getApplicationIdSuffix(), androidApp.getBuildTypes().getByName("debug")::setApplicationIdSuffix); + ifPresent(dslModel.getBuildTypes().getRelease().getApplicationIdSuffix(), androidApp.getBuildTypes().getByName("release")::setApplicationIdSuffix); + configureBadgingTasks(project, androidAppComponents); + configureDependencyGuard(project, dslModel); configureFirebase(project, dslModel, androidApp); } @@ -91,19 +99,25 @@ private static void configureNia(Project project, AndroidSoftware dslModel, Comm dslModel.getDependencies().getImplementation().add("androidx.tracing:tracing-ktx:1.3.0-alpha02"); dslModel.getTesting().getDependencies().getImplementation().add("org.jetbrains.kotlin:kotlin-test"); - android.setResourcePrefix(buildResourcePrefix(project)); configureFlavors(android, (flavor, niaFlavor) -> {}); configureKotlin(project); configureGradleManagedDevices(android); configureLint(android); configurePrintApksTask(project, androidComponents); + configureLicenses(project, dslModel); configureJacoco(project, dslModel, android); configureFeature(project, dslModel, android); } + private static void configureLicenses(Project project, AndroidSoftware dslModel) { + if (dslModel.getLicenses().getEnabled().get()) { + project.getPlugins().apply("com.google.android.gms.oss-licenses-plugin"); + } + } + @SuppressWarnings("UnstableApiUsage") private static void configureFirebase(Project project, AndroidApplication dslModel, ApplicationExtension androidApp) { if (dslModel.getFirebase().getEnabled().get()) { From 68c1e93fe5ad34525f015270ce6cd01d5cf836ec Mon Sep 17 00:00:00 2001 From: Tom Tresansky Date: Mon, 10 Jun 2024 12:24:35 -0400 Subject: [PATCH 5/7] Fix flavorization to be opt-in for applications, add missingDimensionStrategy support --- .../application/AndroidApplication.java | 20 +++++++++++++ .../StandaloneAndroidApplicationPlugin.java | 2 ++ .../android/nia/DimensionStrategy.java | 29 +++++++++++++++++++ .../api/experimental/android/nia/Flavors.java | 28 ++++++++++++++++++ .../experimental/android/nia/NiaSupport.java | 22 ++++++++++---- 5 files changed, 95 insertions(+), 6 deletions(-) create mode 100644 unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/nia/DimensionStrategy.java create mode 100644 unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/nia/Flavors.java diff --git a/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/application/AndroidApplication.java b/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/application/AndroidApplication.java index 99ea09b1..9c39bfc8 100644 --- a/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/application/AndroidApplication.java +++ b/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/application/AndroidApplication.java @@ -21,6 +21,8 @@ import org.gradle.api.experimental.android.AndroidSoftware; import org.gradle.api.experimental.android.extensions.DependencyGuard; import org.gradle.api.experimental.android.extensions.Firebase; +import org.gradle.api.experimental.android.nia.DimensionStrategy; +import org.gradle.api.experimental.android.nia.Flavors; import org.gradle.api.provider.Property; import org.gradle.api.tasks.Nested; import org.gradle.declarative.dsl.model.annotations.Configuring; @@ -83,4 +85,22 @@ default void firebase(Action action) { firebase.getEnabled().set(true); action.execute(firebase); } + + @Nested + Flavors getFlavors(); + + @Configuring + default void flavors(Action action) { + Flavors flavors = getFlavors(); + flavors.getEnabled().set(true); + action.execute(flavors); + } + + @Nested + DimensionStrategy getMissingDimensionStrategy(); + + @Configuring + default void missingDimensionStrategy(Action action) { + action.execute(getMissingDimensionStrategy()); + } } diff --git a/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/application/StandaloneAndroidApplicationPlugin.java b/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/application/StandaloneAndroidApplicationPlugin.java index 89dade0d..ffc0398e 100644 --- a/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/application/StandaloneAndroidApplicationPlugin.java +++ b/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/application/StandaloneAndroidApplicationPlugin.java @@ -41,6 +41,8 @@ public void apply(Project project) { dslModel.getBuildTypes().getDebug().getApplicationIdSuffix().convention((String) null); dslModel.getBuildTypes().getRelease().getApplicationIdSuffix().convention((String) null); + dslModel.getFlavors().getEnabled().convention(false); + // Register an afterEvaluate listener before we apply the Android plugin to ensure we can // run actions before Android does. project.afterEvaluate(p -> linkDslModelToPlugin(p, dslModel)); diff --git a/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/nia/DimensionStrategy.java b/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/nia/DimensionStrategy.java new file mode 100644 index 00000000..a8607889 --- /dev/null +++ b/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/nia/DimensionStrategy.java @@ -0,0 +1,29 @@ +/* + * Copyright 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.api.experimental.android.nia; + +import org.gradle.api.provider.Property; +import org.gradle.declarative.dsl.model.annotations.Restricted; + +@Restricted +public interface DimensionStrategy { + @Restricted + Property getName(); + + @Restricted + Property getValue(); +} diff --git a/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/nia/Flavors.java b/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/nia/Flavors.java new file mode 100644 index 00000000..37e53555 --- /dev/null +++ b/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/nia/Flavors.java @@ -0,0 +1,28 @@ +/* + * Copyright 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.api.experimental.android.nia; + +import org.gradle.api.provider.Property; +import org.gradle.declarative.dsl.model.annotations.Restricted; + +@Restricted +public interface Flavors { + /** + * Internal property purposely not exposed to the DSL. + */ + Property getEnabled(); +} diff --git a/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/nia/NiaSupport.java b/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/nia/NiaSupport.java index f0a13df2..8cb4b466 100644 --- a/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/nia/NiaSupport.java +++ b/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/nia/NiaSupport.java @@ -44,7 +44,6 @@ import java.util.Collections; import java.util.List; import java.util.Objects; -import java.util.function.BiConsumer; import java.util.stream.Collectors; import static org.gradle.api.experimental.android.AndroidSupport.ifPresent; @@ -69,6 +68,8 @@ public static void configureNiaLibrary(Project project, AndroidLibrary dslModel) LibraryExtension androidLib = project.getExtensions().getByType(LibraryExtension.class); LibraryAndroidComponentsExtension androidLibComponents = project.getExtensions().getByType(LibraryAndroidComponentsExtension.class); + configureFlavors(androidLib); + androidLib.setResourcePrefix(buildResourcePrefix(project)); configureNia(project, dslModel, androidLib, androidLibComponents); @@ -79,6 +80,13 @@ public static void configureNiaApplication(Project project, AndroidApplication d ApplicationExtension androidApp = project.getExtensions().getByType(ApplicationExtension.class); ApplicationAndroidComponentsExtension androidAppComponents = project.getExtensions().getByType(ApplicationAndroidComponentsExtension.class); + if (dslModel.getFlavors().getEnabled().get()) { + configureFlavors(androidApp); + } + if (dslModel.getMissingDimensionStrategy().getName().isPresent()) { + androidApp.getDefaultConfig().missingDimensionStrategy(dslModel.getMissingDimensionStrategy().getName().get(), dslModel.getMissingDimensionStrategy().getValue().get()); + } + configureNia(project, dslModel, androidApp, androidAppComponents); @SuppressWarnings("UnstableApiUsage") @@ -99,7 +107,6 @@ private static void configureNia(Project project, AndroidSoftware dslModel, Comm dslModel.getDependencies().getImplementation().add("androidx.tracing:tracing-ktx:1.3.0-alpha02"); dslModel.getTesting().getDependencies().getImplementation().add("org.jetbrains.kotlin:kotlin-test"); - configureFlavors(android, (flavor, niaFlavor) -> {}); configureKotlin(project); configureGradleManagedDevices(android); @@ -202,14 +209,17 @@ private static void configureLint(CommonExtension android) { android.getLint().setCheckDependencies(true); } - private static void configureFlavors( - CommonExtension android, - BiConsumer flavorConfigurationBlock) { + /** + * All NiA Android libraries get flavors, but only NiA Applications that specifically ask + * for them will also get flavors. + * + * @param android the Android extension to configure + */ + private static void configureFlavors(CommonExtension android) { android.getFlavorDimensions().add(FlavorDimension.contentType.name()); Arrays.stream(NiaFlavor.values()).forEach(it -> android.getProductFlavors().create(it.name(), flavor -> { setDimensionReflectively(flavor, it.dimension.name()); - flavorConfigurationBlock.accept(flavor, it); if (android instanceof ApplicationExtension && flavor instanceof ApplicationProductFlavor) { if (it.applicationIdSuffix != null) { From 772b77f39ee50293012b8377b7f0f2133a27880d Mon Sep 17 00:00:00 2001 From: Tom Tresansky Date: Mon, 10 Jun 2024 14:56:04 -0400 Subject: [PATCH 6/7] Support for BaselineProfile and cleanup TODOs to be TODO:DG - Also add support for vectorDrawables. --- .../unified-plugin/gradle/libs.versions.toml | 2 + .../plugin-android/build.gradle.kts | 1 + .../AbstractAndroidSoftwarePlugin.java | 44 ++++++++++++++++--- .../experimental/android/AndroidSoftware.java | 20 +++++++-- .../android/AndroidSoftwareBuildType.java | 11 +++++ .../StandaloneAndroidApplicationPlugin.java | 2 +- .../android/extensions/BaselineProfile.java | 41 +++++++++++++++++ .../BaselineProfileDependencies.java | 25 +++++++++++ .../android/extensions/Compose.java | 2 +- .../android/{nia => extensions}/Licenses.java | 2 +- .../android/extensions/Protobuf.java | 4 +- .../android/library/AndroidLibrary.java | 2 +- .../StandaloneAndroidLibraryPlugin.java | 4 +- .../experimental/android/nia/NiaSupport.java | 9 +--- .../android/nia/PrintApkLocationTask.java | 2 +- .../android/nia/package-info.java | 2 +- 16 files changed, 147 insertions(+), 26 deletions(-) create mode 100644 unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/extensions/BaselineProfile.java create mode 100644 unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/extensions/BaselineProfileDependencies.java rename unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/{nia => extensions}/Licenses.java (93%) diff --git a/unified-prototype/unified-plugin/gradle/libs.versions.toml b/unified-prototype/unified-plugin/gradle/libs.versions.toml index b94eafad..567bae3c 100644 --- a/unified-prototype/unified-plugin/gradle/libs.versions.toml +++ b/unified-prototype/unified-plugin/gradle/libs.versions.toml @@ -8,6 +8,7 @@ ksp = "1.9.23-1.0.20" # Find latest version at: https://developer.android.com/reference/tools/gradle-api android = "8.3.0" androidTools = "31.3.0" +baselineProfile = "1.2.2" firebaseCrashlytics = "2.9.9" firebasePerf = "1.4.2" gms = "4.4.1" @@ -33,6 +34,7 @@ kotlin-serialization-plugin = { module = "org.jetbrains.kotlin:kotlin-serializat android-agp-application = { module = "com.android.application:com.android.application.gradle.plugin", version.ref = "android" } android-kotlin-android = { module = "org.jetbrains.kotlin.android:org.jetbrains.kotlin.android.gradle.plugin", version.ref = "kotlin" } android-tools-common = { module = "com.android.tools:common", version.ref = "androidTools" } +baseline-profile-plugin = { module = "androidx.baselineprofile:androidx.baselineprofile.gradle.plugin", version.ref = "baselineProfile"} firebase-perf-plugin = { module = "com.google.firebase:perf-plugin", version.ref = "firebasePerf" } firebase-crashlytics-plugin = { module = "com.google.firebase:firebase-crashlytics-gradle", version.ref = "firebaseCrashlytics" } google-services-plugin = { module = "com.google.gms.google-services:com.google.gms.google-services.gradle.plugin", version.ref = "gms" } diff --git a/unified-prototype/unified-plugin/plugin-android/build.gradle.kts b/unified-prototype/unified-plugin/plugin-android/build.gradle.kts index 2d3bc56e..eb186da6 100644 --- a/unified-prototype/unified-plugin/plugin-android/build.gradle.kts +++ b/unified-prototype/unified-plugin/plugin-android/build.gradle.kts @@ -14,6 +14,7 @@ dependencies { api(libs.android.kotlin.android) implementation(project(":plugin-jvm")) + implementation(libs.baseline.profile.plugin) implementation(libs.dependency.guard.plugin) implementation(libs.ksp.plugin) implementation(libs.hilt.android.plugin) diff --git a/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/AbstractAndroidSoftwarePlugin.java b/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/AbstractAndroidSoftwarePlugin.java index c330192e..700e07af 100644 --- a/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/AbstractAndroidSoftwarePlugin.java +++ b/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/AbstractAndroidSoftwarePlugin.java @@ -1,5 +1,6 @@ package org.gradle.api.experimental.android; +import androidx.baselineprofile.gradle.consumer.BaselineProfileConsumerExtension; import androidx.room.gradle.RoomExtension; import com.android.build.api.dsl.BuildType; import com.android.build.api.dsl.CommonExtension; @@ -10,6 +11,7 @@ import org.gradle.api.Plugin; import org.gradle.api.Project; import org.gradle.api.artifacts.ConfigurationContainer; +import org.gradle.api.experimental.android.extensions.BaselineProfile; import org.gradle.api.experimental.android.extensions.testing.AndroidTestDependencies; import org.gradle.api.experimental.android.extensions.testing.TestOptions; import org.gradle.api.experimental.android.extensions.testing.Testing; @@ -31,10 +33,13 @@ public void apply(Project project) { // Setup Android software conventions dslModel.getMinSdk().convention(DEFAULT_MIN_ANDROID_SDK); // https://developer.android.com/build/multidex#mdex-gradle + dslModel.getVectorDrawablesUseSupportLibrary().convention(false); // Setup minify conventions dslModel.getBuildTypes().getDebug().getMinify().getEnabled().convention(false); + dslModel.getBuildTypes().getDebug().getBaselineProfile().getEnabled().convention(false); dslModel.getBuildTypes().getRelease().getMinify().getEnabled().convention(false); + dslModel.getBuildTypes().getRelease().getBaselineProfile().getEnabled().convention(false); // Setup desugaring conventions and desugar automatically when JDK > 8 is targeted dslModel.getCoreLibraryDesugaring().getEnabled().convention(project.provider(() -> dslModel.getJdkVersion().get() > 8)); @@ -52,6 +57,7 @@ public void apply(Project project) { dslModel.getRoom().getEnabled().convention(false); dslModel.getRoom().getVersion().convention("2.6.1"); dslModel.getLicenses().getEnabled().convention(false); + dslModel.getBaselineProfile().getEnabled().convention(false); // Setup Test Options conventions dslModel.getTesting().getTestOptions().getIncludeAndroidResources().convention(false); @@ -76,13 +82,13 @@ protected void linkCommonDependencies(AndroidSoftwareDependencies dependencies, */ protected void linkDslModelToPlugin(Project project, AndroidSoftware dslModel, CommonExtension android) { KotlinAndroidProjectExtension kotlin = project.getExtensions().getByType(KotlinAndroidProjectExtension.class); - ConfigurationContainer configurations = project.getConfigurations(); // Link common properties ifPresent(dslModel.getNamespace(), android::setNamespace); ifPresent(dslModel.getCompileSdk(), android::setCompileSdk); android.defaultConfig(defaultConfig -> { ifPresent(dslModel.getMinSdk(), defaultConfig::setMinSdk); + ifPresent(dslModel.getVectorDrawablesUseSupportLibrary(), defaultConfig.getVectorDrawables()::setUseSupportLibrary); return null; }); android.compileOptions(compileOptions -> { @@ -101,8 +107,8 @@ protected void linkDslModelToPlugin(Project project, AndroidSoftware dslModel, C // Link build types AndroidSoftwareBuildTypes modelBuildType = dslModel.getBuildTypes(); NamedDomainObjectContainer androidBuildTypes = android.getBuildTypes(); - linkBuildType(androidBuildTypes.getByName("debug"), modelBuildType.getDebug(), configurations, android); - linkBuildType(androidBuildTypes.getByName("release"), modelBuildType.getRelease(), configurations, android); + linkBuildType(project, androidBuildTypes.getByName("debug"), modelBuildType.getDebug(), android); + linkBuildType(project, androidBuildTypes.getByName("release"), modelBuildType.getRelease(), android); configureTesting(project, dslModel, android); @@ -111,6 +117,18 @@ protected void linkDslModelToPlugin(Project project, AndroidSoftware dslModel, C configureHilt(project, dslModel); configureCompose(project, dslModel, android); configureRoom(project, dslModel); + configureLicenses(project, dslModel); + + if (project.getExtensions().findByName("baselineProfile") != null) { + BaselineProfileConsumerExtension baselineProfileExtension = project.getExtensions().getByType(BaselineProfileConsumerExtension.class); + configureBaselineProfile(project, dslModel.getBaselineProfile(), baselineProfileExtension); + } + } + + private static void configureLicenses(Project project, AndroidSoftware dslModel) { + if (dslModel.getLicenses().getEnabled().get()) { + project.getPlugins().apply("com.google.android.gms.oss-licenses-plugin"); + } } protected void configureHilt(Project project, AndroidSoftware dslModel) { @@ -205,12 +223,23 @@ protected void configureKotlinSerialization(Project project, AndroidSoftware dsl } } + @SuppressWarnings("UnstableApiUsage") + private static void configureBaselineProfile(Project project, BaselineProfile baselineProfile, BaselineProfileConsumerExtension baselineProfileExtension) { + if (baselineProfile.getEnabled().get()) { + project.getPlugins().apply("androidx.baselineprofile"); + + baselineProfileExtension.setAutomaticGenerationDuringBuild(baselineProfile.getAutomaticGenerationDuringBuild().get()); + + project.getConfigurations().getByName("baselineProfile").fromDependencyCollector(baselineProfile.getDependencies().getProfile()); + } + } + /** * Links build types from the model to the android extension. */ - protected void linkBuildType(BuildType buildType, AndroidSoftwareBuildType model, ConfigurationContainer configurations, CommonExtension android) { + protected void linkBuildType(Project project, BuildType buildType, AndroidSoftwareBuildType model, CommonExtension android) { buildType.setMinifyEnabled(model.getMinify().getEnabled().get()); - linkBuildTypeDependencies(buildType, model.getDependencies(), configurations); + linkBuildTypeDependencies(buildType, model.getDependencies(), project.getConfigurations()); model.getDefaultProguardFiles().get().forEach(proguardFile -> { File defaultProguardFile = android.getDefaultProguardFile(proguardFile.getName().get()); @@ -219,6 +248,11 @@ protected void linkBuildType(BuildType buildType, AndroidSoftwareBuildType model model.getProguardFiles().get().forEach(proguardFile -> { buildType.proguardFile(proguardFile.getName().get()); }); + + if (buildType.getExtensions().findByName("baselineProfile") != null) { + BaselineProfileConsumerExtension baselineProfileExtension = buildType.getExtensions().getByType(BaselineProfileConsumerExtension.class); + configureBaselineProfile(project, model.getBaselineProfile(), baselineProfileExtension); + } } @SuppressWarnings("UnstableApiUsage") diff --git a/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/AndroidSoftware.java b/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/AndroidSoftware.java index 2791c9b1..f593a0cd 100644 --- a/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/AndroidSoftware.java +++ b/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/AndroidSoftware.java @@ -3,6 +3,7 @@ import com.android.build.api.dsl.BaseFlavor; import com.android.build.api.dsl.CommonExtension; import org.gradle.api.Action; +import org.gradle.api.experimental.android.extensions.BaselineProfile; import org.gradle.api.experimental.android.extensions.Compose; import org.gradle.api.experimental.android.extensions.CoreLibraryDesugaring; import org.gradle.api.experimental.android.extensions.Hilt; @@ -10,7 +11,7 @@ import org.gradle.api.experimental.android.extensions.Room; import org.gradle.api.experimental.android.extensions.testing.Testing; import org.gradle.api.experimental.android.nia.Feature; -import org.gradle.api.experimental.android.nia.Licenses; +import org.gradle.api.experimental.android.extensions.Licenses; import org.gradle.api.provider.Property; import org.gradle.api.tasks.Nested; import org.gradle.declarative.dsl.model.annotations.Configuring; @@ -41,6 +42,9 @@ public interface AndroidSoftware { @Restricted Property getJdkVersion(); + @Restricted + Property getVectorDrawablesUseSupportLibrary(); + AndroidSoftwareBuildTypes getBuildTypes(); AndroidSoftwareDependencies getDependencies(); @@ -109,7 +113,7 @@ default void testing(Action action) { /** * Support for NiA convention projects defining features. - * TODO: This is a temporary solution until we have a proper feature model. + * TODO:DG This is a temporary solution until we have a proper feature model. */ @Nested Feature getFeature(); @@ -123,7 +127,7 @@ default void feature(Action action) { /** * Support for NiA projects using the com.google.android.gms.oss-licenses-plugin - * TODO: This is a temporary solution until we have a better way of applying plugins + * TODO:DG This is a temporary solution until we have a better way of applying plugins */ @Nested Licenses getLicenses(); @@ -134,4 +138,14 @@ default void licenses(Action action) { licenses.getEnabled().set(true); action.execute(licenses); } + + @Nested + BaselineProfile getBaselineProfile(); + + @Configuring + default void baselineProfile(Action action) { + BaselineProfile baselineProfile = getBaselineProfile(); + baselineProfile.getEnabled().set(true); + action.execute(baselineProfile); + } } diff --git a/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/AndroidSoftwareBuildType.java b/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/AndroidSoftwareBuildType.java index 55cb11cd..8f96c9ea 100644 --- a/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/AndroidSoftwareBuildType.java +++ b/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/AndroidSoftwareBuildType.java @@ -1,6 +1,7 @@ package org.gradle.api.experimental.android; import org.gradle.api.Action; +import org.gradle.api.experimental.android.extensions.BaselineProfile; import org.gradle.api.experimental.android.extensions.Minify; import org.gradle.api.model.ObjectFactory; import org.gradle.api.provider.ListProperty; @@ -49,4 +50,14 @@ default ProguardFile defaultProguardFile(Action configure) @Inject ObjectFactory getObjectFactory(); + + @Nested + BaselineProfile getBaselineProfile(); + + @Configuring + default void baselineProfile(Action action) { + BaselineProfile baselineProfile = getBaselineProfile(); + baselineProfile.getEnabled().set(true); + action.execute(baselineProfile); + } } diff --git a/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/application/StandaloneAndroidApplicationPlugin.java b/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/application/StandaloneAndroidApplicationPlugin.java index ffc0398e..78374634 100644 --- a/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/application/StandaloneAndroidApplicationPlugin.java +++ b/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/application/StandaloneAndroidApplicationPlugin.java @@ -69,7 +69,7 @@ private void linkDslModelToPlugin(Project project, AndroidApplication dslModel) return null; }); - // TODO: All this configuration should be moved to the NiA project + // TODO:DG All this configuration should be moved to the NiA project if (NiaSupport.isNiaProject(project)) { NiaSupport.configureNiaApplication(project, dslModel); } diff --git a/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/extensions/BaselineProfile.java b/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/extensions/BaselineProfile.java new file mode 100644 index 00000000..b7922954 --- /dev/null +++ b/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/extensions/BaselineProfile.java @@ -0,0 +1,41 @@ +/* + * Copyright 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.api.experimental.android.extensions; + +import org.gradle.api.Action; +import org.gradle.api.provider.Property; +import org.gradle.api.tasks.Nested; +import org.gradle.declarative.dsl.model.annotations.Configuring; +import org.gradle.declarative.dsl.model.annotations.Restricted; + +public interface BaselineProfile { + /** + * Internal property purposely not exposed to the DSL. + */ + Property getEnabled(); + + @Restricted + Property getAutomaticGenerationDuringBuild(); + + @Nested + BaselineProfileDependencies getDependencies(); + + @Configuring + default void dependencies(Action action) { + action.execute(getDependencies()); + } +} diff --git a/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/extensions/BaselineProfileDependencies.java b/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/extensions/BaselineProfileDependencies.java new file mode 100644 index 00000000..15fb4595 --- /dev/null +++ b/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/extensions/BaselineProfileDependencies.java @@ -0,0 +1,25 @@ +/* + * Copyright 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.api.experimental.android.extensions; + +import org.gradle.api.artifacts.dsl.Dependencies; +import org.gradle.api.artifacts.dsl.DependencyCollector; + +@SuppressWarnings("UnstableApiUsage") +public interface BaselineProfileDependencies extends Dependencies { + DependencyCollector getProfile(); +} diff --git a/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/extensions/Compose.java b/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/extensions/Compose.java index f622ca11..00308937 100644 --- a/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/extensions/Compose.java +++ b/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/extensions/Compose.java @@ -8,7 +8,7 @@ public interface Compose { @Restricted Property getEnabled(); - // TODO: This should be a file property, and not assume it's a path from the root project + // TODO:DG This should be a file property, and not assume it's a path from the root project @Restricted Property getStabilityConfigurationFilePath(); diff --git a/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/nia/Licenses.java b/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/extensions/Licenses.java similarity index 93% rename from unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/nia/Licenses.java rename to unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/extensions/Licenses.java index abf49fc5..8f74a0d9 100644 --- a/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/nia/Licenses.java +++ b/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/extensions/Licenses.java @@ -14,7 +14,7 @@ * limitations under the License. */ -package org.gradle.api.experimental.android.nia; +package org.gradle.api.experimental.android.extensions; import org.gradle.api.provider.Property; import org.gradle.declarative.dsl.model.annotations.Restricted; diff --git a/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/extensions/Protobuf.java b/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/extensions/Protobuf.java index d50ad965..e78588c4 100644 --- a/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/extensions/Protobuf.java +++ b/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/extensions/Protobuf.java @@ -35,7 +35,7 @@ default void dependencies(Action action) { action.execute(getDependencies()); } - // TODO: This is modeled in a very limited manner for now + // TODO:DG This is modeled in a very limited manner for now @Restricted Property getOption(); @@ -45,7 +45,7 @@ default void dependencies(Action action) { @Restricted Property getVersion(); - // TODO: Should be a File based property, when we support these + // TODO:DG Should be a File based property, when we support these @Restricted Property getGeneratedRootDir(); } diff --git a/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/library/AndroidLibrary.java b/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/library/AndroidLibrary.java index 5f22a5af..343d7f19 100644 --- a/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/library/AndroidLibrary.java +++ b/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/library/AndroidLibrary.java @@ -44,7 +44,7 @@ default void buildTypes(Action action) { action.execute(getBuildTypes()); } - // TODO: We really want to model a list of consumer proguard files here, but can't yet + // TODO:DG We really want to model a list of consumer proguard files here, but can't yet @Restricted Property getConsumerProguardFile(); diff --git a/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/library/StandaloneAndroidLibraryPlugin.java b/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/library/StandaloneAndroidLibraryPlugin.java index 27a31c17..2f2dae55 100644 --- a/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/library/StandaloneAndroidLibraryPlugin.java +++ b/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/library/StandaloneAndroidLibraryPlugin.java @@ -63,7 +63,7 @@ private void linkDslModelToPlugin(Project project, AndroidLibrary dslModel) { configureProtobuf(project, dslModel, android); - // TODO: All this configuration should be moved to the NiA project + // TODO:DG All this configuration should be moved to the NiA project if (NiaSupport.isNiaProject(project)) { NiaSupport.configureNiaLibrary(project, dslModel); } @@ -92,7 +92,7 @@ protected void configureProtobuf(Project project, AndroidLibrary dslModel, Commo }); /* - * TODO: We don't want to rely on beforeVariants here, but how to do without hardcoding: + * TODO:DG We don't want to rely on beforeVariants here, but how to do without hardcoding: * the NiA variants: "demoDebug, demoRelease, prodDebug, prodRelease"? * This would seem to require some sort of ProductFlavor support (and maybe enumerated buildTypes?) * which we don't want to add just yet. diff --git a/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/nia/NiaSupport.java b/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/nia/NiaSupport.java index 8cb4b466..9a559f7a 100644 --- a/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/nia/NiaSupport.java +++ b/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/nia/NiaSupport.java @@ -48,7 +48,7 @@ import static org.gradle.api.experimental.android.AndroidSupport.ifPresent; -// TODO: This class should be moved to the NiA project +// TODO:DG This class should be moved to the NiA project /** * This is a utility class that configures an Android project with conventions * for the Now in Android project. @@ -112,19 +112,12 @@ private static void configureNia(Project project, AndroidSoftware dslModel, Comm configureGradleManagedDevices(android); configureLint(android); configurePrintApksTask(project, androidComponents); - configureLicenses(project, dslModel); configureJacoco(project, dslModel, android); configureFeature(project, dslModel, android); } - private static void configureLicenses(Project project, AndroidSoftware dslModel) { - if (dslModel.getLicenses().getEnabled().get()) { - project.getPlugins().apply("com.google.android.gms.oss-licenses-plugin"); - } - } - @SuppressWarnings("UnstableApiUsage") private static void configureFirebase(Project project, AndroidApplication dslModel, ApplicationExtension androidApp) { if (dslModel.getFirebase().getEnabled().get()) { diff --git a/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/nia/PrintApkLocationTask.java b/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/nia/PrintApkLocationTask.java index e2a5427f..3af5faa5 100644 --- a/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/nia/PrintApkLocationTask.java +++ b/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/nia/PrintApkLocationTask.java @@ -36,7 +36,7 @@ import java.io.File; import java.nio.file.Path; -@DisableCachingByDefault(because = "Prints output") // TODO: Not converted +@DisableCachingByDefault(because = "Prints output") public abstract class PrintApkLocationTask extends DefaultTask { @PathSensitive(PathSensitivity.RELATIVE) @InputDirectory diff --git a/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/nia/package-info.java b/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/nia/package-info.java index 48fdecbb..4d160703 100644 --- a/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/nia/package-info.java +++ b/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/nia/package-info.java @@ -1,4 +1,4 @@ -// TODO: Everything in this package should be moved to the NiA project +// TODO:DG Everything in this package should be moved to the NiA project /** * Contains build logic necessary for the Now In Android (NiA) project as * a temporary workaround to support that project using Declarative Gradle. From 9cc94a1e8cc6558f47e38fb46c3797f0efe3569b Mon Sep 17 00:00:00 2001 From: Tom Tresansky Date: Mon, 10 Jun 2024 16:58:08 -0400 Subject: [PATCH 7/7] Support declarativizing the :lint subproject - Expand the JVM Kotlin library project type to include the possibility of linting (no longer exclusive to Android projects). - Add test dependencies support. --- .../AbstractAndroidSoftwarePlugin.java | 5 +++ .../experimental/android/AndroidSoftware.java | 15 ++++++- .../experimental/android/AndroidSupport.java | 2 +- .../experimental/android/nia/NiaSupport.java | 6 --- .../plugin-common/build.gradle.kts | 2 + .../common/extensions/HasLinting.java | 21 +++++++++ .../experimental/common/extensions/Lint.java | 34 +++++++++++++++ .../common/extensions/LintSupport.java | 43 +++++++++++++++++++ .../experimental/kotlin/KotlinJvmLibrary.java | 26 ++++++++++- .../StandaloneKotlinJvmLibraryPlugin.java | 16 +++++++ .../testing/KotlinTestDependencies.java | 27 ++++++++++++ .../experimental/kotlin/testing/Testing.java | 33 ++++++++++++++ 12 files changed, 221 insertions(+), 9 deletions(-) create mode 100644 unified-prototype/unified-plugin/plugin-common/src/main/java/org/gradle/api/experimental/common/extensions/HasLinting.java create mode 100644 unified-prototype/unified-plugin/plugin-common/src/main/java/org/gradle/api/experimental/common/extensions/Lint.java create mode 100644 unified-prototype/unified-plugin/plugin-common/src/main/java/org/gradle/api/experimental/common/extensions/LintSupport.java create mode 100644 unified-prototype/unified-plugin/plugin-kmp/src/main/java/org/gradle/api/experimental/kotlin/testing/KotlinTestDependencies.java create mode 100644 unified-prototype/unified-plugin/plugin-kmp/src/main/java/org/gradle/api/experimental/kotlin/testing/Testing.java diff --git a/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/AbstractAndroidSoftwarePlugin.java b/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/AbstractAndroidSoftwarePlugin.java index 700e07af..7614bdb6 100644 --- a/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/AbstractAndroidSoftwarePlugin.java +++ b/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/AbstractAndroidSoftwarePlugin.java @@ -50,6 +50,11 @@ public void apply(Project project) { dslModel.getKotlinSerialization().getVersion().convention("1.6.3"); dslModel.getKotlinSerialization().getJsonEnabled().convention(false); + // Setup Linting conventions + dslModel.getLint().getEnabled().convention(false); + dslModel.getLint().getXmlReport().convention(false); + dslModel.getLint().getCheckDependencies().convention(false); + // Setup other feature extension conventions dslModel.getFeature().getEnabled().convention(false); dslModel.getCompose().getEnabled().convention(false); diff --git a/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/AndroidSoftware.java b/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/AndroidSoftware.java index f593a0cd..f71421b4 100644 --- a/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/AndroidSoftware.java +++ b/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/AndroidSoftware.java @@ -12,12 +12,14 @@ import org.gradle.api.experimental.android.extensions.testing.Testing; import org.gradle.api.experimental.android.nia.Feature; import org.gradle.api.experimental.android.extensions.Licenses; +import org.gradle.api.experimental.common.extensions.HasLinting; +import org.gradle.api.experimental.common.extensions.Lint; import org.gradle.api.provider.Property; import org.gradle.api.tasks.Nested; import org.gradle.declarative.dsl.model.annotations.Configuring; import org.gradle.declarative.dsl.model.annotations.Restricted; -public interface AndroidSoftware { +public interface AndroidSoftware extends HasLinting { /** * @see CommonExtension#getCompileSdk() */ @@ -148,4 +150,15 @@ default void baselineProfile(Action action) { baselineProfile.getEnabled().set(true); action.execute(baselineProfile); } + + @Override + @Nested + Lint getLint(); + + @Configuring + default void lint(Action action) { + Lint lint = getLint(); + lint.getEnabled().set(true); + action.execute(lint); + } } diff --git a/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/AndroidSupport.java b/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/AndroidSupport.java index 4c07d45d..9610dec8 100644 --- a/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/AndroidSupport.java +++ b/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/AndroidSupport.java @@ -22,7 +22,7 @@ /** * Static util class containing common methods. */ -public class AndroidSupport { +public final class AndroidSupport { private AndroidSupport() { /* not instantiable */ } public static void ifPresent(Property property, Action action) { diff --git a/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/nia/NiaSupport.java b/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/nia/NiaSupport.java index 9a559f7a..ce846bc3 100644 --- a/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/nia/NiaSupport.java +++ b/unified-prototype/unified-plugin/plugin-android/src/main/java/org/gradle/api/experimental/android/nia/NiaSupport.java @@ -110,7 +110,6 @@ private static void configureNia(Project project, AndroidSoftware dslModel, Comm configureKotlin(project); configureGradleManagedDevices(android); - configureLint(android); configurePrintApksTask(project, androidComponents); configureJacoco(project, dslModel, android); @@ -197,11 +196,6 @@ private static void configureFeature(Project project, AndroidSoftware dslModel, } } - private static void configureLint(CommonExtension android) { - android.getLint().setXmlReport(true); - android.getLint().setCheckDependencies(true); - } - /** * All NiA Android libraries get flavors, but only NiA Applications that specifically ask * for them will also get flavors. diff --git a/unified-prototype/unified-plugin/plugin-common/build.gradle.kts b/unified-prototype/unified-plugin/plugin-common/build.gradle.kts index c5e23260..e938c041 100644 --- a/unified-prototype/unified-plugin/plugin-common/build.gradle.kts +++ b/unified-prototype/unified-plugin/plugin-common/build.gradle.kts @@ -6,6 +6,8 @@ plugins { description = "Common APIs and implementation classes shared by the Android, JVM, and KMP declarative prototypes" dependencies { + implementation(libs.android.agp.application) + implementation(gradleApi()) } diff --git a/unified-prototype/unified-plugin/plugin-common/src/main/java/org/gradle/api/experimental/common/extensions/HasLinting.java b/unified-prototype/unified-plugin/plugin-common/src/main/java/org/gradle/api/experimental/common/extensions/HasLinting.java new file mode 100644 index 00000000..80d9dda1 --- /dev/null +++ b/unified-prototype/unified-plugin/plugin-common/src/main/java/org/gradle/api/experimental/common/extensions/HasLinting.java @@ -0,0 +1,21 @@ +/* + * Copyright 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.api.experimental.common.extensions; + +public interface HasLinting { + Lint getLint(); +} diff --git a/unified-prototype/unified-plugin/plugin-common/src/main/java/org/gradle/api/experimental/common/extensions/Lint.java b/unified-prototype/unified-plugin/plugin-common/src/main/java/org/gradle/api/experimental/common/extensions/Lint.java new file mode 100644 index 00000000..7207c49e --- /dev/null +++ b/unified-prototype/unified-plugin/plugin-common/src/main/java/org/gradle/api/experimental/common/extensions/Lint.java @@ -0,0 +1,34 @@ +/* + * Copyright 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.api.experimental.common.extensions; + +import org.gradle.api.provider.Property; +import org.gradle.declarative.dsl.model.annotations.Restricted; + +@Restricted +public interface Lint { + /** + * Internal property purposely not exposed to the DSL. + */ + Property getEnabled(); + + @Restricted + Property getXmlReport(); + + @Restricted + Property getCheckDependencies(); +} diff --git a/unified-prototype/unified-plugin/plugin-common/src/main/java/org/gradle/api/experimental/common/extensions/LintSupport.java b/unified-prototype/unified-plugin/plugin-common/src/main/java/org/gradle/api/experimental/common/extensions/LintSupport.java new file mode 100644 index 00000000..9abc844f --- /dev/null +++ b/unified-prototype/unified-plugin/plugin-common/src/main/java/org/gradle/api/experimental/common/extensions/LintSupport.java @@ -0,0 +1,43 @@ +/* + * Copyright 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.api.experimental.common.extensions; + +import com.android.build.api.dsl.ApplicationExtension; +import com.android.build.api.dsl.LibraryExtension; +import org.gradle.api.Project; +import com.android.build.api.dsl.Lint; + +public final class LintSupport { + private LintSupport() { /* not instantiable */ } + + public static void configureLint(Project project, HasLinting hasLinting) { + if (project.getPlugins().hasPlugin("com.android.application")) { + ApplicationExtension extension = project.getExtensions().getByType(ApplicationExtension.class); + extension.getLint().setXmlReport(hasLinting.getLint().getXmlReport().get()); + extension.getLint().setCheckDependencies(hasLinting.getLint().getCheckDependencies().get()); + } else if (project.getPlugins().hasPlugin("com.android.library")) { + LibraryExtension extension = project.getExtensions().getByType(LibraryExtension.class); + extension.getLint().setXmlReport(hasLinting.getLint().getXmlReport().get()); + extension.getLint().setCheckDependencies(hasLinting.getLint().getCheckDependencies().get()); + } else { + project.getPlugins().apply("com.android.lint"); + Lint extension = project.getExtensions().getByType(Lint.class); + extension.setXmlReport(hasLinting.getLint().getXmlReport().get()); + extension.setCheckDependencies(hasLinting.getLint().getCheckDependencies().get()); + } + } +} diff --git a/unified-prototype/unified-plugin/plugin-kmp/src/main/java/org/gradle/api/experimental/kotlin/KotlinJvmLibrary.java b/unified-prototype/unified-plugin/plugin-kmp/src/main/java/org/gradle/api/experimental/kotlin/KotlinJvmLibrary.java index dd259b56..7cf02221 100644 --- a/unified-prototype/unified-plugin/plugin-kmp/src/main/java/org/gradle/api/experimental/kotlin/KotlinJvmLibrary.java +++ b/unified-prototype/unified-plugin/plugin-kmp/src/main/java/org/gradle/api/experimental/kotlin/KotlinJvmLibrary.java @@ -1,12 +1,36 @@ package org.gradle.api.experimental.kotlin; +import org.gradle.api.Action; +import org.gradle.api.experimental.common.extensions.HasLinting; +import org.gradle.api.experimental.common.extensions.Lint; import org.gradle.api.experimental.jvm.HasJavaTarget; import org.gradle.api.experimental.common.HasLibraryDependencies; +import org.gradle.api.experimental.kotlin.testing.Testing; +import org.gradle.api.tasks.Nested; +import org.gradle.declarative.dsl.model.annotations.Configuring; import org.gradle.declarative.dsl.model.annotations.Restricted; /** * A library implemented using Kotlin and that targets a single JVM version. */ @Restricted -public interface KotlinJvmLibrary extends HasJavaTarget, HasLibraryDependencies { +public interface KotlinJvmLibrary extends HasJavaTarget, HasLibraryDependencies, HasLinting { + @Override + @Nested + Lint getLint(); + + @Configuring + default void lint(Action action) { + Lint lint = getLint(); + lint.getEnabled().set(true); + action.execute(lint); + } + + @Nested + Testing getTesting(); + + @Configuring + default void testing(Action action) { + action.execute(getTesting()); + } } diff --git a/unified-prototype/unified-plugin/plugin-kmp/src/main/java/org/gradle/api/experimental/kotlin/StandaloneKotlinJvmLibraryPlugin.java b/unified-prototype/unified-plugin/plugin-kmp/src/main/java/org/gradle/api/experimental/kotlin/StandaloneKotlinJvmLibraryPlugin.java index e4452d0c..4ba019a8 100644 --- a/unified-prototype/unified-plugin/plugin-kmp/src/main/java/org/gradle/api/experimental/kotlin/StandaloneKotlinJvmLibraryPlugin.java +++ b/unified-prototype/unified-plugin/plugin-kmp/src/main/java/org/gradle/api/experimental/kotlin/StandaloneKotlinJvmLibraryPlugin.java @@ -2,6 +2,8 @@ import org.gradle.api.Plugin; import org.gradle.api.Project; +import org.gradle.api.artifacts.ConfigurationContainer; +import org.gradle.api.experimental.common.extensions.LintSupport; import org.gradle.api.experimental.jvm.internal.JvmPluginSupport; import org.gradle.api.experimental.kmp.internal.KotlinPluginSupport; import org.gradle.api.internal.plugins.software.SoftwareType; @@ -10,6 +12,7 @@ * Creates a declarative {@link KotlinJvmApplication} DSL model, applies the official Kotlin and application plugin, * and links the declarative model to the official plugin. */ +@SuppressWarnings("UnstableApiUsage") abstract public class StandaloneKotlinJvmLibraryPlugin implements Plugin { @SoftwareType(name = "kotlinJvmLibrary", modelPublicType = KotlinJvmLibrary.class) abstract public KotlinJvmLibrary getLibrary(); @@ -20,11 +23,24 @@ public void apply(Project project) { project.getPlugins().apply("org.jetbrains.kotlin.jvm"); + // Setup Linting conventions + dslModel.getLint().getEnabled().convention(false); + dslModel.getLint().getXmlReport().convention(false); + dslModel.getLint().getCheckDependencies().convention(false); + linkDslModelToPlugin(project, dslModel); } private void linkDslModelToPlugin(Project project, KotlinJvmLibrary dslModel) { KotlinPluginSupport.linkJavaVersion(project, dslModel); JvmPluginSupport.linkMainSourceSourceSetDependencies(project, dslModel.getDependencies()); + + LintSupport.configureLint(project, dslModel); + configureTesting(project, dslModel); + } + + private void configureTesting(Project project, KotlinJvmLibrary dslModel) { + ConfigurationContainer configurations = project.getConfigurations(); + configurations.getByName("testImplementation").fromDependencyCollector(dslModel.getTesting().getDependencies().getImplementation()); } } diff --git a/unified-prototype/unified-plugin/plugin-kmp/src/main/java/org/gradle/api/experimental/kotlin/testing/KotlinTestDependencies.java b/unified-prototype/unified-plugin/plugin-kmp/src/main/java/org/gradle/api/experimental/kotlin/testing/KotlinTestDependencies.java new file mode 100644 index 00000000..9e64184a --- /dev/null +++ b/unified-prototype/unified-plugin/plugin-kmp/src/main/java/org/gradle/api/experimental/kotlin/testing/KotlinTestDependencies.java @@ -0,0 +1,27 @@ +/* + * Copyright 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.api.experimental.kotlin.testing; + +import org.gradle.api.artifacts.dsl.Dependencies; +import org.gradle.api.artifacts.dsl.DependencyCollector; +import org.gradle.declarative.dsl.model.annotations.Restricted; + +@SuppressWarnings("UnstableApiUsage") +@Restricted +public interface KotlinTestDependencies extends Dependencies { + DependencyCollector getImplementation(); +} diff --git a/unified-prototype/unified-plugin/plugin-kmp/src/main/java/org/gradle/api/experimental/kotlin/testing/Testing.java b/unified-prototype/unified-plugin/plugin-kmp/src/main/java/org/gradle/api/experimental/kotlin/testing/Testing.java new file mode 100644 index 00000000..9432a5cd --- /dev/null +++ b/unified-prototype/unified-plugin/plugin-kmp/src/main/java/org/gradle/api/experimental/kotlin/testing/Testing.java @@ -0,0 +1,33 @@ +/* + * Copyright 2024 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.gradle.api.experimental.kotlin.testing; + +import org.gradle.api.Action; +import org.gradle.api.tasks.Nested; +import org.gradle.declarative.dsl.model.annotations.Configuring; +import org.gradle.declarative.dsl.model.annotations.Restricted; + +@Restricted +public interface Testing { + @Nested + KotlinTestDependencies getDependencies(); + + @Configuring + default void dependencies(Action action) { + action.execute(getDependencies()); + } +}