Task that wraps another task

Sorry, the title/subject is not the most descriptive and therefore maybe this has been answered before. All that said, I have a problem that I am not sure how best to solve.

In the Hibernate build we decided to apply “annotation processors” as a distinct and separate task/step. So for each AP we want to run we have a distinct JavaCompile task defined with ‘-proc:only’ option and we alter the main JavaCompile task with ‘-proc:none’. (mainly we do this because we want to capture the generated source files into dedicated directories).

The trouble we have is with up-to-date checking and the fact that each solution breaks with each new Gradle release.

On potential solution I have been contemplating is to define a a specialized task specifically for this ‘-proc:only’ annotation processing and having it either delegate to JavaCompile or extend JavaCompile, the main win being the ability to truly define the proper inputs/outputs.

Any suggestions on the best approach here?

Can you elaborate on which trouble you have with up-to-date checking, which solutions you have tried, and why they break with each new Gradle release?

Well the only kind of trouble I’d imagine you could have :wink: It always thinks the task needs to be run.

To be honest I dont remember the other things I have tried. I moved to what I use now and it worked for quite some time. Recently I moved to Gradle 1.7 and noticed the up-to-date checking was not working (sorry, I don’t know when it first stopped working).

Here is the crux of task as defined atm (reference https://github.com/hibernate/hibernate-orm/blob/master/build.gradle#L174 for the full task):

task generateMainLoggingClasses(type: JavaCompile) {
    ext.aptDumpDir = subProject.file( "${buildDir}/tmp/apt/logging" )
    source = sourceSets.main.originalJavaSrcDirs
    destinationDir = aptDumpDir
    options.define(
            compilerArgs: [
                    "-nowarn",
                    "-proc:only",
                    "-encoding", "UTF-8",
                    "-processor", "org.jboss.logging.processor.apt.LoggingToolsProcessor",
                    "-s", "$sourceSets.main.generatedLoggingSrcDir.absolutePath",
                    ...
            ]
    );
    outputs.dir sourceSets.main.generatedLoggingSrcDir;
    doFirst {
        sourceSets.main.generatedLoggingSrcDir.mkdirs()
    }
    doLast {
        aptDumpDir.delete()
    }
}

BTW, here is the original post that led to the above task definition in the first place: http://forums.gradle.org/gradle/topics/proper_up_to_date_check_settings_for_proc_only_compile_tasks_to_avoid_unnecessary_execution

First step is to run with ‘-i’ and check why the task is always re-run.

I found it. From the Gradle perspective it is reasonable.

The reason it comes about is the (imho) difficulty in having -proc:only tasks in Gradle. Do y’all plan any real support for this?

It might make sense to have a separate task type for annotation processing. Would you mind to flesh out the requirements a bit more and post them as an idea?

Will do as I get time to work on this. Thanks Peter.

Peter, I had a few minutes today to look at this.

I wanted to avoid the whole mess (imo) of exposing ‘org.gradle.api.tasks.compile.CompileOptions’ so I initially had my task extend ‘org.gradle.api.tasks.SourceTask’. The first obstacle I ran into is that I than do not have access to “the proper” ‘org.gradle.api.internal.tasks.compile.Compiler’ to use. Is there a means from within a task to get the ‘org.gradle.api.internal.tasks.compile.Compiler’ I should use from Gradle? The plan from there is to internally build the CompileOptions and use that to call Compiler.

Does that all seem like a reasonable approach?

The guts of Compile/JavaCompile seem like a bunch of no-no for me to in a custom task complete with lots of “internal” Gradle references.

Any advice here Peter?

When I said “It might make sense to have a separate task type for annotation processing”, what I had in mind was to add such a task to the Gradle codebase. There is no fundamentally easier way to get access to Gradle’s compiler infrastructure than what ‘JavaCompile’ does. If you are looking for a pragmatic solution implemented outside the Gradle codebase, consider wrapping an Ant task.

Really I was looking at helping y’all proof this concept by writing an initial implementation. Just trying to make sure that what I laid out seemed reasonable…

In that case, I don’t know of a better option than mimicking the 'JavaCompile 'task. I’d probably keep exposing ‘CompileOptions’, unless you are certain that it doesn’t make sense (from a user’s perspective).

The problem is that CompileOptions exposes exposes some of the things we’d explicitly want the user to not be able to set via CompileOptions; things like ‘-proc:only’ itself or ‘-d’ or ‘-s’.

I guess JavaCompile has the same issue, how does it deal with that?