I'm writing a gradle plugin that modifies class files. I want the task to run on all the generated class files and replace them. Here's what I have so far:
public class InstrumenterTask extends DefaultTask {
private File outputDir;
private SourceSet sourceSet;
public void setOutputDir(File outputDir) {
this.outputDir = outputDir;
}
public void setSourceSet(SourceSet sourceSet) {
this.sourceSet = sourceSet;
}
@TaskAction
public void processSourceSet() {
File classesDir = sourceSet.getOutput().getClassesDir();
Path classesPath = classesDir.toPath();
Files.walk(classesPath).forEach(this::processClassFile);
}
private void processClassFile(File inputFile) {
// Omitted for brevity. Result is in outputDir
}
}
and my buildscript
apply plugin: 'java'
apply plugin: 'application'
mainClassName = 'user.Main'
jar {
manifest {
attributes 'Main-Class': 'user.Main'
}
}
task(mainInstrumenter, type: InstrumenterTask) {
outputDir = new File(buildDir, 'instrumentedClasses')
sourceSet = sourceSets.main
}
mainInstrumenter.dependsOn classes
jar.dependsOn mainInstrumenter
sourceSets.main.output.dir new File(buildDir, 'instrumentedClasses')
The problem now is that in the compiled jar, the class is there two times. How can I tell gradle not to include the classes in the default classes dir?
Alternatively, can I tell gradle to compile the classes to a different directory and put my classes in the default location?
You can simply, at the end of your task action, call
sourceSet.getOutput().setClassesDir(outputDir);
and store your outputs in outputDir
. All the following, dependant tasks will pick up on the newly set classesDir, especially jar
and run
when the task is a dependency of them.