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

Fix #8634: Support -release option #10746

Merged
merged 1 commit into from
Dec 15, 2020
Merged

Conversation

prolativ
Copy link
Contributor

  • A port of https://github.com/scala/scala/pull/6362/files with some improvements
  • When running scalac on JDK 9+ the -release option assures that code is compiled with classes specific to the release available on the classpath.
    This applies to classes from the JDK itself and from external jars.
    If the compilation succeeds, bytecode for the specified release is produced.
  • -target option gets renamed to -Xtarget. Using -release instead is preferred since -Xtarget sets the bytecode version without any checks so this might lead to producing code that breaks at runime

@prolativ prolativ requested a review from smarter December 10, 2020 16:55
@prolativ prolativ force-pushed the add-release-flag branch 2 times, most recently from 99f830e to 181b742 Compare December 10, 2020 22:08
Copy link
Member

@smarter smarter left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Otherwise LGTM!

@@ -112,9 +112,15 @@ abstract class ZipArchive(override val jpath: JPath) extends AbstractFile with E
def close(): Unit
}
/** ''Note: This library is considered experimental and should not be used unless you know what you are doing.'' */
final class FileZipArchive(jpath: JPath) extends ZipArchive(jpath) {
final class FileZipArchive(jpath: JPath, release: Option[String] = None) extends ZipArchive(jpath, release) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suggest removing the default param so we don' forget to pass release in some situations:

Suggested change
final class FileZipArchive(jpath: JPath, release: Option[String] = None) extends ZipArchive(jpath, release) {
final class FileZipArchive(jpath: JPath, release: Option[String]) extends ZipArchive(jpath, release) {


protected def supportedReleaseVersions: List[String] =
if scala.util.Properties.isJavaAtLeast("9") then
val jdkVersion = scala.util.Properties.javaSpecVersion.stripPrefix("1.").toInt
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In DirectoryClassPath we use JDK9Reflectors.runtimeVersionMajor(JDK9Reflectors.runtimeVersion()).intValue(), I think it would be better to use that everywhere since that's the recommended way to get the version on Java 9+.

@@ -123,6 +136,7 @@ class ScalaSettings extends Settings.SettingGroup with CommonScalaSettings {
val XignoreScala2Macros: Setting[Boolean] = BooleanSetting("-Xignore-scala2-macros", "Ignore errors when compiling code that calls Scala2 macros, these will fail at runtime.")
val XimportSuggestionTimeout: Setting[Int] = IntSetting("-Ximport-suggestion-timeout", "Timeout (in ms) for searching for import suggestions when errors are reported.", 8000)
val Xsemanticdb: Setting[Boolean] = BooleanSetting("-Xsemanticdb", "Store information in SemanticDB.").withAbbreviation("-Ysemanticdb")
val Xtarget: Setting[String] = ChoiceSetting("-Xtarget", "target", "Emit bytecode for the specified version of the Java platform. This setting is ignored if -release is specified.", supportedTargetVersions, supportedTargetVersions.head) withAbbreviation "--Xtarget"
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This setting is ignored if -release is specified.

That's a bit confusing, I think it's fine to let -Xtarget override the target set with -release.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For javac you get an error if you try to use -source and -target at the same time. That would be the best option IMHO but I'm not sure if this can be easily achieved with our current approach to parsing command line options.
What would be the purpose of using -source and -Xtarget at the same time with different values? Then running scalac on JDK X you would try to compile code with classes from JDK Y on classpath to emit bytecode to be run on JDK Z, which would be quite likely to break at runtime. The only use case for using -Xtarget alone seems to be cross-compiling at your own risk for a newer JDK than the one used for the compilation.

Copy link
Member

@smarter smarter Dec 11, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For javac you get an error if you try to use -source and -target at the same time. That would be the best option IMHO but I'm not sure if this can be easily achieved with our current approach to parsing command line options.

That or a warning would be fine too, that could be checked in lazy val classfileVersion.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

javac also emits a warning when you use -target explicitly but there is a mismatch with the current JDK version. Should we have it as well? (I guess we don't want to raise a warning for the default when compiling on JDK 9+)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since we renamed it to -Xtarget it's an advanced option so I don't think a warning is worth it, but the documentation of Xtarget can mention that people should consider using release instead

@prolativ
Copy link
Contributor Author

prolativ commented Dec 11, 2020

I've just found out that setting -release to something else than 8 or the current jdk leads to some errors in the ClassfileParser

Caught: java.lang.RuntimeException: bad constant pool index: 0 at pos: 5167 while parsing annotations in /CD/java.base/java/lang/Class.sig
Caught: java.lang.RuntimeException: bad constant pool index: 0 at pos: 5316 while parsing annotations in /CD/java.base/java/lang/Class.sig
Caught: java.lang.RuntimeException: bad constant pool index: 0 at pos: 1542 while parsing annotations in /9ABCDE/java.base/java/lang/Package.sig
Caught: java.lang.RuntimeException: bad constant pool index: 0 at pos: 1772 while parsing annotations in /BCDE/java.base/java/lang/reflect/Method.sig
Caught: java.lang.RuntimeException: bad constant pool index: 0 at pos: 1716 while parsing annotations in /BCDE/java.base/java/lang/reflect/Constructor.sig
Caught: java.lang.RuntimeException: bad constant pool index: 0 at pos: 1883 while parsing annotations in /BCDE/java.base/java/lang/reflect/Field.sig
Caught: java.lang.RuntimeException: bad constant pool index: 0 at pos: 1919 while parsing annotations in /BCDE/java.base/java/lang/reflect/Field.sig
Caught: java.lang.RuntimeException: bad constant pool index: 0 at pos: 1955 while parsing annotations in /BCDE/java.base/java/lang/reflect/Field.sig
Caught: java.lang.RuntimeException: bad constant pool index: 0 at pos: 1991 while parsing annotations in /BCDE/java.base/java/lang/reflect/Field.sig
Caught: java.lang.RuntimeException: bad constant pool index: 0 at pos: 2027 while parsing annotations in /BCDE/java.base/java/lang/reflect/Field.sig
Caught: java.lang.RuntimeException: bad constant pool index: 0 at pos: 2063 while parsing annotations in /BCDE/java.base/java/lang/reflect/Field.sig
Caught: java.lang.RuntimeException: bad constant pool index: 0 at pos: 2099 while parsing annotations in /BCDE/java.base/java/lang/reflect/Field.sig
Caught: java.lang.RuntimeException: bad constant pool index: 0 at pos: 2135 while parsing annotations in /BCDE/java.base/java/lang/reflect/Field.sig
Caught: java.lang.RuntimeException: bad constant pool index: 0 at pos: 2171 while parsing annotations in /BCDE/java.base/java/lang/reflect/Field.sig
Caught: java.lang.RuntimeException: bad constant pool index: 0 at pos: 2207 while parsing annotations in /BCDE/java.base/java/lang/reflect/Field.sig
Caught: java.lang.RuntimeException: bad constant pool index: 0 at pos: 2243 while parsing annotations in /BCDE/java.base/java/lang/reflect/Field.sig
Caught: java.lang.RuntimeException: bad constant pool index: 0 at pos: 2279 while parsing annotations in /BCDE/java.base/java/lang/reflect/Field.sig
Caught: java.lang.RuntimeException: bad constant pool index: 0 at pos: 2315 while parsing annotations in /BCDE/java.base/java/lang/reflect/Field.sig
Caught: java.lang.RuntimeException: bad constant pool index: 0 at pos: 2351 while parsing annotations in /BCDE/java.base/java/lang/reflect/Field.sig
Caught: java.lang.RuntimeException: bad constant pool index: 0 at pos: 2387 while parsing annotations in /BCDE/java.base/java/lang/reflect/Field.sig
Caught: java.lang.RuntimeException: bad constant pool index: 0 at pos: 2423 while parsing annotations in /BCDE/java.base/java/lang/reflect/Field.sig
Caught: java.lang.RuntimeException: bad constant pool index: 0 at pos: 2459 while parsing annotations in /BCDE/java.base/java/lang/reflect/Field.sig
Caught: java.lang.RuntimeException: bad constant pool index: 0 at pos: 2495 while parsing annotations in /BCDE/java.base/java/lang/reflect/Field.sig
Caught: java.lang.RuntimeException: bad constant pool index: 0 at pos: 4434 while parsing annotations in /BCDE/java.base/java/lang/invoke/MethodHandles.sig
24 warnings found

That might require further investigation

* A port of https://github.com/scala/scala/pull/6362/files with some improvements
* When running scalac on JDK 9+ the -release option assures that code is compiled with classes specific to the release available on the classpath.
  This applies to classes from the JDK itself and from external jars.
  If the compilation succeeds, bytecode for the specified release is produced.
* -target option gets renamed to -Xtarget. Using -release instead is preferred since -Xtarget sets the bytecode version without any checks so this might lead to producing code that breaks at runime
* Fix parsing annotations in classfiles
@prolativ
Copy link
Contributor Author

@smarter These errors were caused by an already existing bug in ClassfileParser. However fixing it didn't require much code so I integrated the fix (and an update to a test) into this PR. Have a look at that please

@smarter smarter merged commit b3486ac into scala:master Dec 15, 2020
@anatoliykmetyuk anatoliykmetyuk added the release-notes Should be mentioned in the release notes label Feb 10, 2021
@prolativ prolativ mentioned this pull request Feb 16, 2021
@mkurz mkurz mentioned this pull request Mar 10, 2022
7 tasks
@Kordyjan Kordyjan added this to the 3.0.0 milestone Aug 2, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
release-notes Should be mentioned in the release notes
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants