How can MRJARs be created from two sourcesets?

Case in point, the Ikonli project defines classes that depend on JavaFX 8. Unfortunately these classes are marked as private. In JDK9 these classes were moved to a public space, thus a binary compatibility problem arises. See for more details.

There are (at least) two possible solutions: The old and tried by releasing multiple artifacts using a classifier, such as ikonli-javafx-jdk9 (for JDK9 and newer) and ikonli-javafx (for JDK8). The new way using MRJARs, which would allow different versions of the same class to be packaged inside the same JAR, thus allowing developers to configure a single dependency instead of trying to match the right classifier.

I’d rather go with the new way as that keeps things simpler for consumers of the project. Unfortuantely the Gradle Java9 Guide does not mention MRJARs at all, nor does it show how multiple sourceSects may be compiled targeting different JDK versions, say src/main/java (set to JDK8) and src/main/java9 (set to JDK9).

Any help would be appreciated.

Hi Andrés,

Creating a multi-release jar is fairly easy with Gradle. There are multiple ways to set it up, depending on why, actually, you need a MRJAR (hint: you don’t need it), and what are the dependencies between your classes. It also depends whether you want the META-INF/versions/9 directory to be bloated with duplicate classes or not.

I have setup a minimal example that you can find here:

Note that I really don’t recommend using MRJARs. I promised a blog post about why, and I will soon write it. I think variants are the solution (hint 2: classifiers are not). In the meantime, let me know if it helps.

Thanks! I’m puzzled by what you meant with variants. If this ends with more than one artifact then it essentially becomes the same thing as multiple artifacts with different classifiers IMHO.

I also would like to know more about the gotchas and traps that MRJARs my pose as I see you’re not a fan of them.

Variants are basically multiple artifacts, yes, but qualified. Meaning that metadata participates in dependency resolution.

I really need to explain in that blog post :slight_smile: