After updating Gradle from 8 to 9, the plugin stopped working. I now get the error:
Execution failed for task ‘:extensions:nunl:processReleaseResources’.
Cannot mutate the dependencies of configuration ‘:extensions:nunl:releaseCompileClasspath’ after the configuration was resolved. After a configuration has been observed, it should not be modified.
I cannot pinpoint what causes it.
The plugin I am writing works in this fashion:
A settings plugin applies plugins to subprojects respectively. These plugins then configure dependencies and share artifacts to each other. Namely, “extension” projects supply artifacts to the single “patches” project. Related code:
private fun Settings.configureProjects(extension: SettingsExtension) {
// region Include the projects
val extensionsProjectPath = extension.extensions.projectsPath
if (extensionsProjectPath != null) {
objectFactory.fileTree().from(rootDir.resolve(extensionsProjectPath)).matching {
it.include("**/build.gradle.kts", "**/build.gradle")
}.forEach {
include(it.parentFile.relativeTo(rootDir).toPath().joinToString(":"))
}
}
include(extension.patchesProjectPath)
// endregion
// region Apply the plugins
gradle.rootProject { rootProject ->
if (extensionsProjectPath != null) {
val extensionsProject = try {
rootProject.project(extensionsProjectPath)
} catch (e: UnknownProjectException) {
null
}
extensionsProject?.subprojects { extensionProject ->
if (
extensionProject.buildFile.exists() &&
!extensionProject.parent!!.plugins.hasPlugin(ExtensionPlugin::class.java)
) {
extensionProject.pluginManager.apply(ExtensionPlugin::class.java)
}
}
}
// Needs to be applied after the extension plugin
// so that their extensionConfiguration is available for consumption.
rootProject.project(extension.patchesProjectPath).pluginManager.apply(PatchesPlugin::class.java)
}
The patches plugin:
/**
* Configures the project to consume the extension artifacts and add them to the resources of the patches project.
*/
private fun Project.configureConsumeExtensions(patchesExtension: PatchesExtension) {
val extensionsProject = try {
project(patchesExtension.extensionsProjectPath ?: return)
} catch (e: UnknownProjectException) {
return
}
val extensionProjects = extensionsProject.subprojects.filter { extensionProject ->
extensionProject.plugins.hasPlugin(ExtensionPlugin::class.java)
}
val extensionsDependencyScopeConfiguration =
configurations.dependencyScope("extensionsDependencyScope").get()
val extensionsConfiguration = configurations.resolvable("extensionConfiguration").apply {
configure { it.extendsFrom(extensionsDependencyScopeConfiguration) }
}
project.dependencies.apply {
extensionProjects.forEach { extensionProject ->
add(
extensionsDependencyScopeConfiguration.name,
project(
mapOf(
"path" to extensionProject.path,
"configuration" to "extensionConfiguration",
),
),
)
}
}
extensions.configure<SourceSetContainer>("sourceSets") { sources ->
sources.named("main") { main ->
main.resources.srcDir(extensionsConfiguration)
}
}
}
The extension plugin:
private fun Project.configureArtifactSharing(extension: ExtensionExtension) {
val androidExtension = extensions.getByType<BaseAppModuleExtension>()
val syncExtensionTask = tasks.register<Sync>("syncExtension") {
val dexTaskName = if (androidExtension.buildTypes.getByName("release").isMinifyEnabled) {
"minifyReleaseWithR8"
} else {
"mergeDexRelease"
}
val dexTask = tasks.getByName(dexTaskName)
dependsOn(dexTask)
val extensionName = if (extension.name != null) {
Path(extension.name!!)
} else {
projectDir.resolveSibling(project.name + ".rve").relativeTo(rootDir).toPath()
}
from(dexTask.outputs.files.asFileTree.matching { include("**/*.dex") })
into(layout.buildDirectory.dir("revanced/${extensionName.parent.pathString}"))
rename { extensionName.fileName.toString() }
}
configurations.create("extensionConfiguration").apply {
isCanBeResolved = false
isCanBeConsumed = true
outgoing.artifact(layout.buildDirectory.dir("revanced")) {
it.builtBy(syncExtensionTask)
}
}
}
Mind that there are likely bad practices involved, which could also be the source of the issue; however, I did not find any other way to achieve the behaviour I had with this in Gradle 8. Ideally, I can restore the behaviour I saw on Gradle 8.