How to projects.sourceSets.test.java.exclude(class) but include from differnt sourceSet

I am trying to keep a single code line repo where a library has forked… so if the build profile says the code is older than X I’d like to exclude Myclass.java from the default test/java/src directory but include Myclass.java from the testOlderThanX.java.srcDir.

I think the exclude pattern ends up excluding Myclass.java from the testOlderThanX.java.srcDirs even those the directory is properly added to the sourceSet.

Thoughts? I don’t want to fork the repo. I suppose I could runtime delete the Myclass.java from the test.java directory and forget about the ignore pattern… they seems less ideal though.

if ( project.hasProperty(‘olderThanX’) ) {
project.sourceSets.test.java.exclude(‘Myclass.java’)
project.sourceSets.integTest.java.exclude(‘Myclass.java’)
project.sourceSets.test.java.srcDirs+= project.sourceSets.testOlderThanX.java.srcDirs
project.sourceSets.integTest.java.srcDirs+= project.sourceSets.integTestOlderThanX.java.srcDirs
}

I’m sure it’s possible to do what you’re asking in Gradle but it would be hard to get your IDE (intellij/eclipse) to honor the exclude. I, personally, think that exclude is an anti-pattern that should be avoided. Instead, I always prefer split my files into separate directories which can be joined together depending on the context. This also has the benefit of being supported out of the box by IDEs

So, in your case I’d have:

  • src/main/java - common java sources
  • src/olderThanX/java
  • src/newerThanX/java
  • src/test/java - common test classes
  • src/olderThanXTest/java
  • src/newerThanXTest/java

You get the idea, then based on the property, you join two or or more directories together to get the result you need. Never exclude… always include!

If you don’t want to split your sources like this, another option is to have a Copy task(s) which run before compile and/or test tasks which copy sources from the two directories to “merged” directory (under $buildDir). You then compile the “merged” directory. This will be supported in IDEs too.

Thank you. I played around some more and ended up with something similar though I still have an exclude. I might optimize like yours. I only need to support the olderThanCode for maybe a year so at that point I can just dump this block. Not sure if I needed the extends portion.

if ( project.hasProperty(‘olderThanX’) ) {
project.sourceSets.test.java.exclude(‘Myclass.java’)
project.sourceSets.integTest.java.exclude(‘Myclass.java’)
project.sourceSets.testOlderThanX.java.srcDirs+=‘src/test/java8’
project.sourceSets.integTestOlderX.java.srcDirs+=‘src/integTest/java8’

configurations {
testOlderThanX.extendsFrom testImplementation
integTestOlderThanX.extendsFrom testImplmentation
}

project.sourceSets.test.compileClasspath += project.sourceSets.testOlderThanX.output
project.sourceSets.test.runtimeClasspath += project.sourceSets.testOlderThanX.output
project.sourceSets.integTest.compileClasspath += project.sourceSets.integTestOlderThanX.output
project.sourceSets.integTest.runtimeClasspath += project.sourceSets.integTestOlderThanX.output
}

The project.hasProperty('olderThanX') logic is a little hacky. Have you considered ditching this concept and instead building both in the same build? (eg two compile tasks and two jars)

This would be more inline with Gradle best practices. You could have two projects in a multi-module build. There’s a few tricks to make this easier, you can build specific projects passing command line args and you can add extra tasks to disable olderThanX / newerThanX tasks etc.

I haven’t mostly because one runs in a jdk8 context and the other in a jdk11 context. I initially thought I could have jdk11 build for jdk8 but if possible it wasn’t straightforward.

It’s certainly possible though I’ve not attempted it myself. It involves configuring a different jdk for compile & test tasks… Possibly a discussion for another thread…