From 2775702f2e4615b0d405df2e67dbc79e7f10b6bb Mon Sep 17 00:00:00 2001 From: Akash Yadav Date: Fri, 12 Jan 2024 14:03:23 +0530 Subject: [PATCH] fix(gradle-plugin): fix build failure when 'apply plugin: ..' syntax is used in module projects (#1274, #1620) --- .../gradle/AndroidIDEInitScriptPlugin.kt | 48 ++++++++++---- .../androidide/gradle/LogSenderPlugin.kt | 8 ++- .../gradle/AndroidIDEInitScriptPluginTest.kt | 10 +++ .../com/itsaky/androidide/gradle/utils.kt | 20 +++++- .../resources/sample-project/app/.gitignore | 1 + .../sample-project/app/build.gradle.in | 58 +++++++++++++++++ .../sample-project/app/build.gradle.kts | 62 ------------------- 7 files changed, 127 insertions(+), 80 deletions(-) create mode 100755 gradle-plugin/src/test/resources/sample-project/app/build.gradle.in delete mode 100644 gradle-plugin/src/test/resources/sample-project/app/build.gradle.kts diff --git a/gradle-plugin/src/main/java/com/itsaky/androidide/gradle/AndroidIDEInitScriptPlugin.kt b/gradle-plugin/src/main/java/com/itsaky/androidide/gradle/AndroidIDEInitScriptPlugin.kt index cec689a07..745b714f1 100644 --- a/gradle-plugin/src/main/java/com/itsaky/androidide/gradle/AndroidIDEInitScriptPlugin.kt +++ b/gradle-plugin/src/main/java/com/itsaky/androidide/gradle/AndroidIDEInitScriptPlugin.kt @@ -20,6 +20,7 @@ package com.itsaky.androidide.gradle import com.itsaky.androidide.buildinfo.BuildInfo import com.itsaky.androidide.tooling.api.LogSenderConfig._PROPERTY_IS_TEST_ENV import com.itsaky.androidide.tooling.api.LogSenderConfig._PROPERTY_MAVEN_LOCAL_REPOSITORY +import org.gradle.StartParameter import org.gradle.api.Plugin import org.gradle.api.artifacts.dsl.RepositoryHandler import org.gradle.api.initialization.Settings @@ -43,14 +44,17 @@ class AndroidIDEInitScriptPlugin : Plugin { override fun apply(target: Gradle) { target.settingsEvaluated { settings -> - val (isTestEnv, mavenLocalRepos) = settings.startParameter.run { - val isTestEnv = projectProperties.containsKey(_PROPERTY_IS_TEST_ENV) - && projectProperties[_PROPERTY_IS_TEST_ENV].toString().toBoolean() - val mavenLocalRepos = projectProperties.getOrDefault(_PROPERTY_MAVEN_LOCAL_REPOSITORY, "") - isTestEnv to mavenLocalRepos - } + settings.addDependencyRepositories() + } - settings.addDependencyRepositories(isTestEnv, mavenLocalRepos) + target.rootProject { rootProject -> + rootProject.buildscript.apply { + dependencies.apply { + add("classpath", rootProject.ideDependency("gradle-plugin")) + } + + repositories.addDependencyRepositories(rootProject.gradle.startParameter) + } } target.projectsLoaded { gradle -> @@ -62,10 +66,6 @@ class AndroidIDEInitScriptPlugin : Plugin { return@subprojects } - sub.buildscript.dependencies.apply { - add("classpath", sub.ideDependency("gradle-plugin")) - } - sub.afterEvaluate { logger.info("Trying to apply plugin '${BuildInfo.PACKAGE_NAME}' to project '${sub.path}'") sub.pluginManager.apply(BuildInfo.PACKAGE_NAME) @@ -74,9 +74,16 @@ class AndroidIDEInitScriptPlugin : Plugin { } } + private fun Settings.addDependencyRepositories() { + val (isTestEnv, mavenLocalRepos) = getTestEnvProps(startParameter) + addDependencyRepositories(isTestEnv, mavenLocalRepos) + } + @Suppress("UnstableApiUsage") - private fun Settings.addDependencyRepositories(isMavenLocalEnabled: Boolean, - mavenLocalRepo: String) { + private fun Settings.addDependencyRepositories( + isMavenLocalEnabled: Boolean, + mavenLocalRepo: String + ) { dependencyResolutionManagement.run { repositories.configureRepositories(isMavenLocalEnabled, mavenLocalRepo) } @@ -86,6 +93,21 @@ class AndroidIDEInitScriptPlugin : Plugin { } } + private fun RepositoryHandler.addDependencyRepositories(startParams: StartParameter) { + val (isTestEnv, mavenLocalRepos) = getTestEnvProps(startParams) + configureRepositories(isTestEnv, mavenLocalRepos) + } + + private fun getTestEnvProps(startParameter: StartParameter): Pair { + return startParameter.run { + val isTestEnv = projectProperties.containsKey(_PROPERTY_IS_TEST_ENV) + && projectProperties[_PROPERTY_IS_TEST_ENV].toString().toBoolean() + val mavenLocalRepos = projectProperties.getOrDefault(_PROPERTY_MAVEN_LOCAL_REPOSITORY, "") + + isTestEnv to mavenLocalRepos + } + } + private fun RepositoryHandler.configureRepositories( isMavenLocalEnabled: Boolean, mavenLocalRepos: String diff --git a/gradle-plugin/src/main/java/com/itsaky/androidide/gradle/LogSenderPlugin.kt b/gradle-plugin/src/main/java/com/itsaky/androidide/gradle/LogSenderPlugin.kt index 6afaa2f03..973ccc9b7 100644 --- a/gradle-plugin/src/main/java/com/itsaky/androidide/gradle/LogSenderPlugin.kt +++ b/gradle-plugin/src/main/java/com/itsaky/androidide/gradle/LogSenderPlugin.kt @@ -17,6 +17,7 @@ package com.itsaky.androidide.gradle +import com.android.build.api.component.analytics.AnalyticsEnabledApplicationVariant import com.android.build.api.variant.ApplicationAndroidComponentsExtension import com.android.build.api.variant.ApplicationVariant import com.android.build.api.variant.impl.ApplicationVariantImpl @@ -107,7 +108,10 @@ class LogSenderPlugin : Plugin { private fun ApplicationVariant.withRuntimeConfiguration( action: Configuration.() -> Unit ) { - this as ApplicationVariantImpl - variantDependencies.runtimeClasspath.action() + if (this is ApplicationVariantImpl) { + variantDependencies.runtimeClasspath.action() + } else if (this is AnalyticsEnabledApplicationVariant) { + delegate.withRuntimeConfiguration(action) + } } } diff --git a/gradle-plugin/src/test/java/com/itsaky/androidide/gradle/AndroidIDEInitScriptPluginTest.kt b/gradle-plugin/src/test/java/com/itsaky/androidide/gradle/AndroidIDEInitScriptPluginTest.kt index 68e29ec55..9d0f302b8 100644 --- a/gradle-plugin/src/test/java/com/itsaky/androidide/gradle/AndroidIDEInitScriptPluginTest.kt +++ b/gradle-plugin/src/test/java/com/itsaky/androidide/gradle/AndroidIDEInitScriptPluginTest.kt @@ -39,6 +39,16 @@ class AndroidIDEInitScriptPluginTest { assertBasics(result) } + @Test + fun `test behavior with apply plugin syntax`() { + val result = buildProject( + agpVersion = BuildInfo.AGP_VERSION_MININUM, + gradleVersion = "7.5.1", + useApplyPluginGroovySyntax = true + ) + assertBasics(result) + } + private fun assertBasics(result: BuildResult) { // These plugins must be applied to the for ((project, plugins) in mapOf( diff --git a/gradle-plugin/src/test/java/com/itsaky/androidide/gradle/utils.kt b/gradle-plugin/src/test/java/com/itsaky/androidide/gradle/utils.kt index 9abe91d24..1dd2e0f15 100644 --- a/gradle-plugin/src/test/java/com/itsaky/androidide/gradle/utils.kt +++ b/gradle-plugin/src/test/java/com/itsaky/androidide/gradle/utils.kt @@ -30,10 +30,11 @@ import kotlin.io.path.pathString internal fun buildProject( agpVersion: String = BuildInfo.AGP_VERSION_LATEST, gradleVersion: String = "8.2", + useApplyPluginGroovySyntax: Boolean = false, configureArgs: (MutableList) -> Unit = {}, vararg plugins: String ): BuildResult { - val projectRoot = openProject(agpVersion, *plugins) + val projectRoot = openProject(agpVersion, useApplyPluginGroovySyntax, *plugins) val initScript = FileProvider.testHomeDir().resolve(".androidide/init/androidide.init.gradle") val mavenLocal = FileProvider.projectRoot().resolve("gradle-plugin/build/maven-local/repos.txt").toFile() @@ -99,6 +100,7 @@ internal fun writeInitScript(file: File, deps: List) { internal fun openProject( agpVersion: String = BuildInfo.AGP_VERSION_LATEST, + useApplyPluginGroovySyntax: Boolean = false, vararg plugins: String ): Path { val projectRoot = FileProvider.projectRoot() @@ -110,8 +112,20 @@ internal fun openProject( } run { - val pluginsText = plugins.joinToString(separator = "\n") { "id(\"$it\")" } - projectRoot.resolve("app/build.gradle.kts").toFile() + // remove existing build scripts + projectRoot.resolve("app") + .toFile() + .listFiles()!! + .filter { it.name.startsWith("build.gradle") && !it.name.endsWith(".in") } + .forEach { it.delete() } + + val pluginsText = if (!useApplyPluginGroovySyntax) { + plugins.joinToString(separator = "\n") { "id(\"$it\")" } + } else { + plugins.joinToString(separator = "\n") { "apply plugin: \"$it\"" } + } + + projectRoot.resolve("app/build.gradle" + if (useApplyPluginGroovySyntax) "" else ".kts").toFile() .replaceAllPlaceholders(mapOf("PLUGINS" to pluginsText)) } diff --git a/gradle-plugin/src/test/resources/sample-project/app/.gitignore b/gradle-plugin/src/test/resources/sample-project/app/.gitignore index 58ef9a020..8b72509bb 100755 --- a/gradle-plugin/src/test/resources/sample-project/app/.gitignore +++ b/gradle-plugin/src/test/resources/sample-project/app/.gitignore @@ -1,2 +1,3 @@ /build +build.gradle build.gradle.kts \ No newline at end of file diff --git a/gradle-plugin/src/test/resources/sample-project/app/build.gradle.in b/gradle-plugin/src/test/resources/sample-project/app/build.gradle.in new file mode 100755 index 000000000..7782c567d --- /dev/null +++ b/gradle-plugin/src/test/resources/sample-project/app/build.gradle.in @@ -0,0 +1,58 @@ +apply plugin: 'com.android.application' +@@PLUGINS@@ + +android { + namespace "com.example.myapplication2" + compileSdk 33 + buildToolsVersion "33.0.2" + + defaultConfig { + applicationId "com.example.myapplication2" + minSdk 21 + targetSdk 33 + versionCode 1 + versionName "1.0" + + vectorDrawables { + useSupportLibrary true + } + } + + compileOptions { + sourceCompatibility JavaVersion.VERSION_11 + targetCompatibility JavaVersion.VERSION_11 + } + + buildTypes { + release { + minifyEnabled true + proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro") + } + } + + buildFeatures { + viewBinding true + } + + // LogSender must be applied to all the debuggable product flavors + flavorDimensions += "version" + productFlavors { + demo { + dimension "version" + applicationIdSuffix ".demo" + versionNameSuffix "-demo" + } + + full { + dimension "version" + applicationIdSuffix ".full" + versionNameSuffix "-full" + } + } +} + +dependencies { + implementation "androidx.appcompat:appcompat:1.6.1" + implementation "androidx.constraintlayout:constraintlayout:2.1.4" + implementation "com.google.android.material:material:1.9.0" +} diff --git a/gradle-plugin/src/test/resources/sample-project/app/build.gradle.kts b/gradle-plugin/src/test/resources/sample-project/app/build.gradle.kts deleted file mode 100644 index b3ffa060e..000000000 --- a/gradle-plugin/src/test/resources/sample-project/app/build.gradle.kts +++ /dev/null @@ -1,62 +0,0 @@ - -plugins { - id("com.android.application") - -} - -android { - namespace = "com.example.myapplication2" - compileSdk = 33 - buildToolsVersion = "33.0.2" - - defaultConfig { - applicationId = "com.example.myapplication2" - minSdk = 21 - targetSdk = 33 - versionCode = 1 - versionName = "1.0" - - vectorDrawables { - useSupportLibrary = true - } - } - - compileOptions { - sourceCompatibility = JavaVersion.VERSION_11 - targetCompatibility = JavaVersion.VERSION_11 - } - - buildTypes { - release { - isMinifyEnabled = true - proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro") - } - } - - buildFeatures { - viewBinding = true - - } - - // LogSender must be applied to all the debuggable product flavors - flavorDimensions += "version" - productFlavors { - create("demo") { - dimension = "version" - applicationIdSuffix = ".demo" - versionNameSuffix = "-demo" - } - - create("full") { - dimension = "version" - applicationIdSuffix = ".full" - versionNameSuffix = "-full" - } - } -} - -dependencies { - implementation("androidx.appcompat:appcompat:1.6.1") - implementation("androidx.constraintlayout:constraintlayout:2.1.4") - implementation("com.google.android.material:material:1.9.0") -}