Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for NiA :app project to use declarative syntax #91

Merged
merged 6 commits into from
Jun 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading