I'm using io.freefair.aspectj.post-compile-weaving gradle plugin to apply some aspects to my classes. How this plugin works, firstly, it's runs trough the project and searching all Compile
tasks, after these tasks was found it's call #enhanceWithWeavingAction method which puts an ajc
action at the end of list actions
in each task.
Since I'm include this plugin into every project, I have to put this configuration into each build.gradle.kts
file
tasks.name1 {
configure<AjcAction> {
options {
compilerArgs.add("-Xlint:ignore")
}
}
}
tasks.name2 {
configure<AjcAction> {
options {
compilerArgs.add("-Xlint:ignore")
}
}
}
// and couple configurations of AjcAction below
So, to avoid copy pasting I decided to create a plugin, which will apply these options.
abstract class MyPlugin : Plugin<Project> {
override fun apply(project: Project): Unit = with(project) {
// applying original post-compile plugin
pluginManager.apply(AspectJPostCompileWeavingPlugin::class.java)
// some conditions
afterEvaluate {
tasks.named("name1").configure { configureCompile(it) }
tasks.named("name2").configure { configureCompile(it) }
tasks.named("name3").configure { configureCompile(it) }
}
}
/**
* TODO: find way to put modified actions into original tasks,
* for some reason they just will be ignored.
*/
private fun Project.configureCompile(compileTask: Task) {
val wrapperClass = Class.forName("org.gradle.api.internal.AbstractTask\$TaskActionWrapper")
compileTask.apply {
val ajcWrapper = wrapperClass.cast(actions.last())
if (compileTask.name == "specieficTaskName") {
actions.removeAt(actions.size - 1)
return
}
val ajcActionField = ajcWrapper.javaClass.getDeclaredField("action")
ajcActionField.trySetAccessible()
val action = ajcActionField.get(ajcWrapper)
if (action is AjcAction) {
action.options.compilerArgs.add("-Xlint:ignore")
ajcActionField.set(ajcWrapper, action)
}
}
}
}
I've used this plugin to configure my other project and faced the problem
During debugging the gradle clean assemble
I see, how actions was modified correctly:
– Everything okay – Everything okay
But, after these modifications was made, it's looks like gradle just ignores them and using original actions, why it's happen? How can I modify these actions? Or maybe there is another solution of original problem?
There are quite some problems with your plugin as you might have guessed already.
Do not use afterEvaluate
. That's practically never a solution, but duct tape. The main effect of afterEvaluate
is to introduce timing problems, ordering problems, and race conditions. It is like using SwingUtilities.invokeLater
or Platform.runLater
to "fix" a GUI problem. It just does symptom treatment, delaying the problem to a later, harder to reproduce, harder to debug, and harder to fix point in time.
I guess in your case the tasks name1
, name2
, and name3
are not yet registered when that plugin is applied and that is why you use it. But just use the reactive versions and you do not need afterEvaluate
, so instead of tasks.named("name1").configure
do tasks.named { it == "name1" }.configureEach
. You can of course also right away test for all three names in the predicate.
You are getting an internal Gradle class and fields of it by reflection. Multiple things that alone alreay cry loudly "bad practice, don't do that". Especially as it seems there is no reason at all to do that. Modifying the actions should work just fine if you really need to do it. But the documentation of that plugin shows that you can do tasks.compileJava { ajc { ... } }
in Groovy or tasks.compileJava { configure<AjcAction> { ... } }
in Kotlin to configure the action, which means it is added as extension to the task. So just do val ajcAction = compileTask.extensions.findByName("ajc") as AjcAction
to get the action and then set enabled
property for specieficTaskName
and compilerArgs
for the others without dirty tricks.