Search code examples
javagradlesource-sets

Omit class file from jar in gradle


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?


Solution

  • 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.