The directory structure I proposed is probably better for everyone.
In my initial post on the directory, I tried to explain why this is probably better, but maybe I didn’t effectively communicate my reasoning.
My comparison below is based on my guess that you implemented your plugin in a certain way. Maybe I’m wrong, but I assume that you create a JavaCompile
for each target Java version, use the corresponding source directory (e.g., src/main/java9
for Java 9), configure a version-specific output directory, place the main
& older Java versioned code on the classpath, and set the correct --release
option (e.g., --release 9
). If you do something different, please let me know.
Creating an extra source should automatically perform much of this wiring for you. This becomes more important when you try to support more than just the most basic Java-only scenarios.
Normally, each SourceSet
has an AbstractCompile
task for each language plugin that has been applied to a project (e.g., Java, Kotlin, Scala, etc).
Imagine if someone has Kotlin code that they want to include in the mrjar, with certain Kotlin as the baseline (main
), other Kotlin for Java 9+ (java9
), etc. How would you support distributing classes compiled from Kotlin into different version directories in the mrjar?
In your setup, you shouldn’t put the Kotlin code under src/main/java9
because it is Kotlin, not Java. Would you use src/main/kotlin9
? What about other languages? Do you know how to associate every language’s directory name with its corresponding AbstractCompile
task?
What if the default source directory name for a language ends with numbers? How could you disambiguate between a hypothetical language named Plan 9 with default directory name plan9
& a language named Plan with a default directory name plan
which is to be built for java 9+, so it would be plan9
with the suffix?
Even if you allow people to manually configure this in mrjar {}
in build.gradle.kts
, that’s extra work, plus the directory name is still ambiguous without checking the build.gradle.kts
.
With my setup, wiring source directories to AbstractCompile
s would automatically occur for all languages, since each language will be stored under its default directory. e.g., Java & Kotlin for 9 would be under src/java9/java
& src/java9/kotlin
, respectively.
Thus,. the easiest way to separate code from many languages into separate target JVM versions is probably to have the directories within, e.g., src/main
(e.g., java
, kotlin
, groovy
, etc.) just segment based on language, and to have the segmentation for target JVM (java9
, java11
, etc.) be at the source set level, e.g., src/main
(i.e. baseline), src/java9
, etc.
This plugin is only for Gradle. If you’re in the Gradle world, you should follow the Gradle conventions. It will make it easier for you to integrate your plugin into the Gradle APIs & ecosystem, and it will make it easier for other Gradle users to understand & work with your plugin.
e.g., Java & C# use different method naming conventions. Even if there’s tons more Java code than C# in the world, you shouldn’t use Java naming conventions in C# code.
Most of the examples didn’t appear to be for Gradle. A few random people using a certain directory structure for their Gradle projects doesn’t mean that it is optimal.
Also, these projects are all standalone projects, not plugins for a whole ecosystem built around specific conventions & interoperability. None of these few projects had non-Java JVM code (like Kotlin, Scala, Groovy, etc.), so they didn’t need to figure out how to deal with including version-specific class files from languages other than Java within a mrjar. If you want your plugin to be used by many people, you need to support all of their needs, not just your own limited use cases.
If anyone has any criticisms of my proposal, I’d like to hear them, as I haven’t really used multiple source sets within a project (other than just for testing that plugins work with them), so maybe there are some issues that I’ve missed.