import java.util.concurrent.Callable apply plugin: SourceGenerationPlugin /** * A plugin for dealing with AnnotationProcessor-based source generation. *

* Creates (or reuses) a grouping task named `generateSources` which is responsible * for coordinating (via task deps) the running of all source-generation tasks. *

* Additionally a grouping task is created for each SourceSet to hold the generation * task for that SourceSet. This task is named following the `run{SourceSet.name}SourceGenerators`. * This task is also injected into the SourceSet as `sourceGeneratorsTask` for scripts to access */ class SourceGenerationPlugin implements Plugin { public static final String GROUP = "sourceGeneration"; public static final String GENERATE_SOURCES_TASK_NAME = "generateSources"; @Override public void apply(Project project) { final JavaPluginConvention javaPluginConvention = project.getConvention().findPlugin( JavaPluginConvention.class ); if ( javaPluginConvention == null ) { // something seriously awry return; } project.convention.plugins[GROUP] = new SourceGenerationPluginConvention( project ); // first set up the overall generateSources task Task generateSourcesTask = project.getTasks().findByName( GENERATE_SOURCES_TASK_NAME ); if ( generateSourcesTask == null ) { generateSourcesTask = project.getTasks().create( GENERATE_SOURCES_TASK_NAME ); generateSourcesTask.setGroup( GROUP ); generateSourcesTask.setDescription( "Grouping task for all source generation tasks" ); } // for each source set, define the specific grouping tasks (and associate with the generateSources as a // task dependency) for ( SourceSet sourceSet : javaPluginConvention.getSourceSets() ) { final ExtraPropertiesExtension extProps = ( (ExtensionAware) sourceSet ).getExtensions().getExtraProperties(); // find the main javac task for this sourceSet (so we can add dependsOn to it) final JavaCompile javaCompileTask = (JavaCompile) project.getTasks().getByName( sourceSet.getCompileJavaTaskName() ); // create the pre-apt generation grouping task final String sourceGeneratorsTaskName = sourceSet.getTaskName( "run", "sourceGenerators" ); final Task sourceGeneratorsTask = project.getTasks().create( sourceGeneratorsTaskName ); sourceGeneratorsTask.setGroup( GROUP ); sourceGeneratorsTask.setDescription( String.format( "Grouping task for running all source generation tasks for the %s source-set of the %s project", sourceSet.getName(), project.getName() ) ); generateSourcesTask.dependsOn( sourceGeneratorsTask ); javaCompileTask.dependsOn( sourceGeneratorsTask ); final File aptDir = new File( new File( project.getBuildDir(), "generated-src/apt" ), sourceSet.name ); javaCompileTask.options.compilerArgs += [ "-s", aptDir.absolutePath ]; javaCompileTask.doFirst({ if ( !aptDir.exists() ) { if ( !aptDir.mkdirs() ) { project.logger.warn( "Unable to create APT dir : " + aptDir.absolutePath ) } } }) generateSourcesTask.dependsOn( javaCompileTask ) extProps.set( "sourceGeneratorsTask", sourceGeneratorsTask ); extProps.set( "aptDir", aptDir ); } } } class SourceGenerationPluginConvention { public static final String METAGEN_DEPENDENCY_CONFIG_NAME = "hibernateJpaModelGenTool"; public static final String METAGEN_PROCESSOR_NAME = "org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor"; private final Project project; // practicality says we only ever deal with 2 source-sets: private JavaCompile mainProcOnlyTask; private JavaCompile testProcOnlyTask; SourceGenerationPluginConvention(Project project) { this.project = project } /** * Exposed to the build scripts to be able to apply JPA Metamodel Generation support to the * SourceSet it specifies. * * @param sourceSet The SourceSet to which JPA Metamodel Generation support should be applied. */ public void addMetaGenProcessor(SourceSet sourceSet) { if ( sourceSet.name.equals( "main" ) ) { if ( mainProcOnlyTask == null ) { mainProcOnlyTask = generateProcessorOnlyTask( sourceSet ) } } else if ( sourceSet.name.equals( "test" ) ) { if ( testProcOnlyTask == null ) { testProcOnlyTask = generateProcessorOnlyTask( sourceSet ) } } else { throw new IllegalArgumentException( "SourceSet (" + sourceSet.name + ") not valid for source generation" ) } } private JavaCompile generateProcessorOnlyTask(SourceSet sourceSet) { final File targetDir = sourceSet.aptDir; // find the main javac task for this sourceSet (we will alter it a bit later on) final JavaCompile javaCompileTask = (JavaCompile) project.getTasks().getByName( sourceSet.getCompileJavaTaskName() ); final ExtraPropertiesExtension extProps = ( (ExtensionAware) sourceSet ).getExtensions().getExtraProperties(); final String aptTaskName = sourceSet.getTaskName( "run", "annotationProcessors" ); // final AnnotationProcessorOnlyTask aptTask = project.getTasks().create( aptTaskName, AnnotationProcessorOnlyTask.class ); final JavaCompile aptTask = project.getTasks().create( aptTaskName, JavaCompile.class ); aptTask.options.compilerArgs += [ "-nowarn", "-proc:only", "-encoding", "UTF-8", "-s", targetDir.getAbsolutePath(), "-processor", METAGEN_PROCESSOR_NAME ] aptTask.setGroup( SourceGenerationPlugin.GROUP ); aptTask.setDescription( String.format( "Grouping task for running all AnnotationProcessors (javac -proc:only) for the %s sourceSet of the %s project", sourceSet.getName(), project.getName() ) ); // sourceSet.getAllJava() returns a SourceDirectorySet which is a "live view" meaning it keeps expanding // even as we add to it. The problem is that later on here we will add the output directory of this task // to this SourceDirectorySet; we need to make sure that we use the view of the SourceDirectorySet *before* that // happens as the source for this task. getSrcDirs() does that aptTask.source( sourceSet.getAllJava() ) aptTask.destinationDir = targetDir aptTask.setSourceCompatibility( javaCompileTask.getSourceCompatibility() ); aptTask.setTargetCompatibility( javaCompileTask.getTargetCompatibility() ); aptTask.setDependencyCacheDir( javaCompileTask.getDependencyCacheDir() ); aptTask.getConventionMapping().map( "classpath", new Callable() { public FileCollection call() throws Exception { return javaCompileTask.getClasspath() + project.configurations[METAGEN_DEPENDENCY_CONFIG_NAME] } } ); aptTask.mustRunAfter( extProps.get( "sourceGeneratorsTask" ) ); javaCompileTask.dependsOn( aptTask ); project.tasks.findByName( SourceGenerationPlugin.GENERATE_SOURCES_TASK_NAME ).dependsOn( aptTask ) // Add the APT output dir to the source set // - so that the generated sources get compiled during main javac sourceSet.getJava().srcDir( targetDir ); return aptTask } }