Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Generalize JDK versions #24

Open
mdedetrich opened this issue Dec 4, 2023 · 3 comments
Open

Generalize JDK versions #24

mdedetrich opened this issue Dec 4, 2023 · 3 comments

Comments

@mdedetrich
Copy link
Contributor

mdedetrich commented Dec 4, 2023

The plugins current design happens to use hardcoded JDK versions, even down to sbt keys. While this may have made sense when the plugin was originally designed, ever since then due to changes in how often JDK gets released this isn't very scalable and so its not the best idea to just keep on adding things like sbt keys that are hardcoded against a specific JDK release.

What would be most ideal is if the plugin could just automatically derive the JDK version from the source folders (i.e. 11 from scala-jdk11) and handle the rest from there.

@eed3si9n @ktoso what do you think?

@mdedetrich
Copy link
Contributor Author

mdedetrich commented Jan 15, 2024

So I had an initial stab at this (see #41) and I came across the first obstacle. Fundamentally the problem I am experiencing is that the current way that sbt is structured, it assumes that for every relevant SettingKey there is just a single javacOptions.

Or put differently, in order to generalize the JDK versions you essentially need an sbt setting that is a Map[Int, Seq[String]] since you need different jdk args (i.e. -version and -target) for every JDK version. While its definitely technically possible to do this, it would involve having to override a lot of the core sbt functionality (such as https://github.com/sbt/sbt/blob/b1e9308ebe4c10c3457d730e0f19cdaee12834c7/main/src/main/scala/sbt/Defaults.scala#L2421-L2448) since you would have to point to jdkJavacOptions rather than the standard jdkOptions which imho is not worth the effort nor the ugliness.

Due to this I only see 2 reasonable ways to solve this issue. One is that if we want to support multi-release-jar via this plugin for SBT 1.x.x, we would need to dynamically (i.e. at runtime) create SettingKey's for every JDK version we support. That is there will be a core set of SettingKey's which be defined in MultiReleaseJarKeys but at runtime the plugin will generate the following keys (where X will correspond to the JDK version)

  • jdkXJavacOption
  • jdkXClassDirectory
  • jdkXBackendOutput

Since these keys will be dynamic they won't be defined as distinct values in a trait/object but rather a result of some function, i.e.

def generateSbtSettingsForJdkVersion(jdkVersion: Int): Seq[SettingKey] = ???

def generateSbtSettings: Seq[SettingKey[_]] = {
    for (8 <- maxSupportedJdkVersion).flatMap {jdkVersion =>
        generateSbtSettingForJdkVersion(jdkVersion)    
    }
}

I don't know if this is however even possible, another idea is to dynamically create sbt Configuration's rather than SettingKey, i.e. you would have a MultiReleaseJarX configs with X being each JDK version and each of those configs would have the specific javacOptions/classDirectory set as necessary, the sbt-multi-release jar would then handled collating all of those Configuration's into one master Configuration.

Thing is I don't even know if this is possible and/or is a good idea, I know that there is a movement to limit the concept of configuration concept for SBT 2 although this may not be an issue because this plugin should only be extending Compile / Test.

Barring all of this, the second option would be to just add proper native support of multi-release-jar to SBT 2. This would involve making changes to SBT 2 so that it can support having multiple different javacOptions/classDirectory per SettingKey likely dispatching on some javacVersion SettingKey to figure out the current JDK version. This may not be the worse idea, given that it has been suggested to properly fix similar limitations (i.e. cross scala versions) and also mult-release-jar itself has been suggested as a feature of SBT 2

@eed3si9n @SethTisue wdyt? Feel free to ping anyone else that is relevant, I suspect that if it makes sense to add it to SBT 2.x an SIP (or w/e the equivalent is) would be necessary so it can be properly reviewed?

@mdedetrich
Copy link
Contributor Author

mdedetrich commented Jan 15, 2024

Another solution came to mind would be to use a similar technique that is currently done for crossScalaVersions which would basically involve implementing the solution as a Command (i.e. reloading sbt for every single JDK version as is currently done for each Scala versions in crossScalaVersions).

Initially however this doesn't seem like a good idea, as it exacerbates the already current situation of relying on Command as a workaround for crossScalaVersions and it may not even be possible to do solve this generically in a nice way at least if we want to support scala-2.12-jdk11 source folders as it would add another dimension, creating a matrix for Command's across scalaVersion/jdkVersion.

Yet another option would be to write a Scala 2.12 macro which would at compile time generate a distinct Configuration for every JDK version with each of those Configuration's having its own set of javacOption/classDirectory. The macro would generate the code when compiling this plugin so that users of this plugin would see MultiReleaseJarX configurations for every JDK version as distinct static values. Now that I think about this, if we want to solve this issue with this plugin for sbt 1.9.x this looks like the best least worst option?

@mio-19
Copy link

mio-19 commented Sep 6, 2024

This plugin asks for JDK 8 or 11, when future JDK is sufficient to do the build

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants