Skip to content

Commit

Permalink
Merge pull request #91 from gradle/tt/declarativize-nia-app
Browse files Browse the repository at this point in the history
Add support for NiA :app project to use declarative syntax
  • Loading branch information
tresat committed Jun 14, 2024
2 parents 0180fbb + 772b77f commit eb2a4dd
Show file tree
Hide file tree
Showing 25 changed files with 534 additions and 59 deletions.
14 changes: 13 additions & 1 deletion unified-prototype/unified-plugin/gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ 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"
hilt = "2.50"
room = "2.6.1"

Expand All @@ -16,6 +20,8 @@ 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
Expand All @@ -28,6 +34,10 @@ 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" }
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" }
Expand All @@ -36,5 +46,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" }
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,18 @@ 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)
implementation(libs.kotlin.serialization.plugin)
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.oss.licenses.plugin)

implementation(libs.apache.commons.lang)
implementation(libs.android.tools.common)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,24 +1,25 @@
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;
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;
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;
import org.gradle.api.provider.Property;
import org.jetbrains.kotlin.gradle.dsl.KotlinAndroidProjectExtension;

import java.util.Objects;
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<Project> {
Expand All @@ -32,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));
Expand All @@ -52,12 +56,15 @@ 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);
dslModel.getBaselineProfile().getEnabled().convention(false);

// Setup Test Options conventions
dslModel.getTesting().getTestOptions().getIncludeAndroidResources().convention(false);
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);
}

/**
Expand All @@ -75,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 -> {
Expand All @@ -100,19 +107,31 @@ protected void linkDslModelToPlugin(Project project, AndroidSoftware dslModel, C
// Link build types
AndroidSoftwareBuildTypes modelBuildType = dslModel.getBuildTypes();
NamedDomainObjectContainer<? extends BuildType> androidBuildTypes = android.getBuildTypes();
linkBuildType(androidBuildTypes.getByName("debug"), modelBuildType.getDebug(), configurations);
linkBuildType(androidBuildTypes.getByName("release"), modelBuildType.getRelease(), configurations);
linkBuildType(project, androidBuildTypes.getByName("debug"), modelBuildType.getDebug(), android);
linkBuildType(project, androidBuildTypes.getByName("release"), modelBuildType.getRelease(), android);

configureTesting(project, dslModel, android);

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);
configureLicenses(project, dslModel);

if (project.getExtensions().findByName("baselineProfile") != null) {
BaselineProfileConsumerExtension baselineProfileExtension = project.getExtensions().getByType(BaselineProfileConsumerExtension.class);
configureBaselineProfile(project, dslModel.getBaselineProfile(), baselineProfileExtension);
}
}

protected void configureHilt(Project project, AndroidSoftware dslModel, CommonExtension<?, ?, ?, ?, ?, ?> android) {
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) {
if (dslModel.getHilt().getEnabled().get()) {
project.getLogger().info("Hilt is enabled in: " + project.getPath());

Expand All @@ -123,11 +142,13 @@ 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");
}
}

@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());

Expand Down Expand Up @@ -178,6 +199,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")
Expand All @@ -194,12 +223,36 @@ 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) {
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());
buildType.proguardFile(defaultProguardFile);
});
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")
Expand All @@ -209,10 +262,4 @@ protected void linkBuildTypeDependencies(BuildType buildType, AndroidSoftwareDep
configurations.getByName(name + "CompileOnly").fromDependencyCollector(dependencies.getCompileOnly());
configurations.getByName(name + "RuntimeOnly").fromDependencyCollector(dependencies.getRuntimeOnly());
}

protected <T> void ifPresent(Property<T> property, Action<T> action) {
if (property.isPresent()) {
action.execute(property.get());
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,15 @@
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;
import org.gradle.api.experimental.android.extensions.KotlinSerialization;
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.extensions.Licenses;
import org.gradle.api.provider.Property;
import org.gradle.api.tasks.Nested;
import org.gradle.declarative.dsl.model.annotations.Configuring;
Expand Down Expand Up @@ -40,6 +42,9 @@ public interface AndroidSoftware {
@Restricted
Property<Integer> getJdkVersion();

@Restricted
Property<Boolean> getVectorDrawablesUseSupportLibrary();

AndroidSoftwareBuildTypes getBuildTypes();

AndroidSoftwareDependencies getDependencies();
Expand Down Expand Up @@ -108,7 +113,7 @@ default void testing(Action<? super Testing> 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();
Expand All @@ -119,4 +124,28 @@ default void feature(Action<? super Feature> action) {
feature.getEnabled().set(true);
action.execute(feature);
}

/**
* Support for NiA projects using the com.google.android.gms.oss-licenses-plugin
* TODO:DG This is a temporary solution until we have a better way of applying plugins
*/
@Nested
Licenses getLicenses();

@Configuring
default void licenses(Action<? super Licenses> action) {
Licenses licenses = getLicenses();
licenses.getEnabled().set(true);
action.execute(licenses);
}

@Nested
BaselineProfile getBaselineProfile();

@Configuring
default void baselineProfile(Action<? super BaselineProfile> action) {
BaselineProfile baselineProfile = getBaselineProfile();
baselineProfile.getEnabled().set(true);
action.execute(baselineProfile);
}
}
Original file line number Diff line number Diff line change
@@ -1,11 +1,17 @@
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;
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 {
/**
Expand All @@ -20,4 +26,38 @@ public interface AndroidSoftwareBuildType {
default void minify(Action<? super Minify> action) {
action.execute(getMinify());
}

ListProperty<ProguardFile> getProguardFiles();
ListProperty<ProguardFile> getDefaultProguardFiles();

@Adding
default ProguardFile proguardFile(Action<? super ProguardFile> configure) {
ProguardFile proguardFile = getObjectFactory().newInstance(ProguardFile.class);
proguardFile.getName().convention("<no name>");
configure.execute(proguardFile);
getProguardFiles().add(proguardFile);
return proguardFile;
}

@Adding
default ProguardFile defaultProguardFile(Action<? super ProguardFile> configure) {
ProguardFile proguardFile = getObjectFactory().newInstance(ProguardFile.class);
proguardFile.getName().convention("<no name>");
configure.execute(proguardFile);
getDefaultProguardFiles().add(proguardFile);
return proguardFile;
}

@Inject
ObjectFactory getObjectFactory();

@Nested
BaselineProfile getBaselineProfile();

@Configuring
default void baselineProfile(Action<? super BaselineProfile> action) {
BaselineProfile baselineProfile = getBaselineProfile();
baselineProfile.getEnabled().set(true);
action.execute(baselineProfile);
}
}
Loading

0 comments on commit eb2a4dd

Please sign in to comment.