Creating/upgrading aspectj plugin - unable to manage multiproject dependencies

Hi, I need to build a multiproject using aspectj I looked at “http://wiki.gradle.org/display/GRADLE/Plugins#Plugins-AspectJplugin” buit it seems to be not updated, so I tried to upgrade it to gradle rc1.0-rc3.

Here is my attempt:

package com.amadego.utilities.gradle
  import org.gradle.api.Project
import org.gradle.api.Plugin
import org.gradle.api.plugins.JavaPlugin
  class AspectJPlugin implements Plugin<Project> {
    public static final String ANT_ASPECTJ_TASK_DEFINITION_NAME = "org/aspectj/tools/ant/taskdefs/aspectjTaskdefs.properties";
    public static final String AJC_CONFIGURATION_NAME = "ajc";
    public static final String ASPECT_LIBS_CONFIGURATION_NAME = "aspectLibs";
   @Override
 void apply(Project project) {
  // println "AspectJPlugin apply called"
   project.getPlugins().apply(JavaPlugin.class);
    project.configurations.add(AJC_CONFIGURATION_NAME)
  project.configurations.add(ASPECT_LIBS_CONFIGURATION_NAME)
    project.task(JavaPlugin.COMPILE_JAVA_TASK_NAME, overwrite: true) {
   dependsOn project.configurations.ajc.getTaskDependencyFromProjectDependency(true, JavaPlugin.COMPILE_JAVA_TASK_NAME)
      doLast {
    // println "AspectJPlugin Called. classpath="+project.configurations.compile.asPath
    project.ant.taskdef(resource: ANT_ASPECTJ_TASK_DEFINITION_NAME, classpath: project.configurations.ajc.asPath)
          project.ant.iajc (
     debug: "on",
     showWeaveInfo: "false",
     classpath: project.configurations.compile.asPath,
     destDir: project.sourceSets.main.output.classesDir.absolutePath,
     //fork: "true", maxmem: "512m", // fork is not needed
     aspectpath: project.configurations.aspectLibs.asPath,
// Similar to classpath, aspectpath contains read-only, binary aspect libraries that are woven into sources but not included in the output. aspectpath accepts jar/zip files (but, unlike classpath, not directories).
      //inpath: project.configurations.ajInpath.asPath,
// Read .class files for bytecode weaving from directories or zip files (like classpath).
      //sourceRootCopyFilter:"**/.svn/*,**/*.java,**/*.aj", // do not copy anything, resources must be in separate dir
     source: project.sourceCompatibility,
     target: project.targetCompatibility,
     verbose: "false"
    ) {
     sourceroots{
      project.sourceSets.main.java.srcDirs.each {
       pathelement(location:it.absolutePath)
      }
     }
    }
   }
  }
 }
}

The plugin works fine (more or less… :slight_smile: ) But when I use it in a multiproject it fails to calculate dependencies, while the java plugin works fine.

This is my project tree:

main/settings.gradle main/build.gradle main/prjA/build.gradle main/prjA/src/main/java/A.java main/prjB/build.gradle main/prjB/src/main/java/B.java

settings.gradle is:

include 'prjA', 'prjB'

main/build.gradle is:

subprojects {
 group = "com.amadego.utilities"
 version = "2.0"
}

main/prjA/build.gradle is:

apply plugin: "aspectj"
sourceCompatibility = 1.6
dependencies {
 ajc "org.aspectj:aspectjtools:1.6.6"
 aspectLibs project(":prjB")
 compile project(":prjB")
 compile "org.aspectj:aspectjrt:1.6.6"
}
jar {
 manifest {
  attributes "Implementation-Title": "${rootProject.description} - ${project.description}", "Implementation-Version": version
 }
}
  uploadArchives {
 repositories {
  flatDir {
   dirs USER_REPOSITORY_LIB_PATH
  }
 }
}

main/prjB/build.gradle is:

apply plugin: "aspectj"
sourceCompatibility = 1.6
dependencies {
 ajc "org.aspectj:aspectjtools:1.6.6"
 compile "org.aspectj:aspectjrt:1.6.6"
}
jar {
 manifest {
  attributes "Implementation-Title": "${rootProject.description} - ${project.description}", "Implementation-Version": version
 }
}
  uploadArchives {
 repositories {
  flatDir {
   dirs USER_REPOSITORY_LIB_PATH
  }
 }
}

Now, I would expect that, if I run “gradle build” from root project, gradle would build first prjB, then prjA (according to dependecies).

Indeed, this is what happens if I apply the java plugin, but, when I apply the aspectj.plugin, gradle builds projects in alphabetical order, as if was ignoring the interproject dependencies.

I guess there is something wrong in my aspectj pluginn, but I’m unable to spot it.

Can you help me? Thanks, Luca

In Gradle, execution order is only determined by task dependencies. (Roughly speaking, a project dependency in a ‘dependencies’ block results in a dependency from the tasks that consume that project’s artifacts, to the tasks producing them.) Often, Gradle will run some tasks from project A, then some from project B, and then again some from project A. You can influence task execution order by adding further task dependencies.

Thanks for your reply but I think don’t understand exactly your post.

I undestand that some tasks of project A may be executed before some tasks of project B, but I don’t understand that the A:compileJava can be executed BEFORE B:compileJava, given that A:compilejava has a dependency from project B.

As I said, the build works fine if I apply the java plugin, but fails if I apply the aspectj plugin, so it’s clear that a dependency went lost from java plugin to aspectj plugin, but I’m not able to spot the missing dependency.

I thought that the line:

dependsOn project.configurations.ajc.getTaskDependencyFromProjectDependency(true, JavaPlugin.COMPILE_JAVA_TASK_NAME)

would mean:

this task has the same dependency of “JavaPlugin.COMPILE_JAVA_TASK_NAME”

but it seems that I’m wrong.

Can you help me to spot the missing dependency?

Thanks again, Luca

Another test:

I need the project Jar, so I defined the dependecy from the entire build, or at least from the jar task, not simply from the compile task.

So I changed the line:

dependsOn project.configurations.ajc.getTaskDependencyFromProjectDependency(true, JavaPlugin.COMPILE_JAVA_TASK_NAME)

with the line:

dependsOn project.configurations.ajc.getTaskDependencyFromProjectDependency(true, JavaPlugin.JAR_TASK_NAME) // or JavaBasePlugin.BUILD task name, if needed

But it still doesn’t work. Any idea? Thanks, Luca

The line you quote adds dependencies on tasks named “compileJava” in projects depended on by the ‘ajc’ configuration, which is zero. It would have to be ‘compile’ instead, but even that isn’t correct. I’d try ‘dependsOn project.configurations.compile’.

Man You Are Great, it works !!!

I used the line:

dependsOn project.configurations.compile.getTaskDependencyFromProjectDependency(true, JavaPlugin.JAR_TASK_NAME)

But (alas) I have to admit that I don’t yet fully understand the configurations.

Can you point me to some place in the doc that gives more info on this issue?

Start with the [Dependency configurations] (http://gradle.org/docs/current/userguide/userguide_single.html#configurations) chapter in the Gradle user guide.

OK, now I think I’ve got it.

since I’m using also

aspectLibs project(":prjB")

I need to put in the plugin also the depencies from aspectlibs:

dependsOn project.configurations.aspectLibs.getTaskDependencyFromProjectDependency(true, JavaPlugin.JAR_TASK_NAME)
dependsOn project.configurations.compile.getTaskDependencyFromProjectDependency(true, JavaPlugin.JAR_TASK_NAME)

Let’s hope that this solves all the problems.

What about putting this plugin in the gradle distribution? I saw many people fighting with aspectj…

Yes, proper out of the box support for AspectJ would be very nice.

I just created http://issues.gradle.org/browse/GRADLE-2601

sorry for the delay I was working on another project. If you want to take a look this is my last release. I’m using it under gradle 1.1 and 1.5rc3,

https://www.box.com/s/kxd2cdbvrjopipb830b5

I hope it helps. Thanks for gradle!