【问题标题】:Enforcing Java version for Scala project in sbt?在 sbt 中强制执行 Scala 项目的 Java 版本?
【发布时间】:2013-10-13 02:06:52
【问题描述】:

我的 scala 应用程序只能使用 Java 7 运行,因为它依赖于仅出现在该版本 JDK 中的库。

如何在 sbt 中强制执行,以便在启动 sbt 运行/编译应用程序时,如果用户使用了错误的 Java 版本,正确的错误消息会立即显示给用户?

注意:这里有 NO 要编译的 Java™ 源代码。我只有有 Scala 源代码。 Scala 代码需要从 Java 7 获得的 import java.nio.file.Path

【问题讨论】:

    标签: java scala sbt


    【解决方案1】:

    对于未来的任何人来说,这也是一个很好的方法。如果找不到正确的 Java 版本,它会立即停止执行:

    initialize := {
      val _ = initialize.value // run the previous initialization
      val required = "1.8"
      val current  = sys.props("java.specification.version")
      assert(current == required, s"Unsupported JDK: java.specification.version $current != $required")
    }
    

    你把这个放在你的build.sbt中。

    【讨论】:

    • 明智的做法是调用之前的initialize value
    • 这是在哪个文件中??
    • 更新了答案。它在您的build.sbt 文件中
    【解决方案2】:

    以防万一,如果您在

    中使用基于 eclipse 的 scala-ide 更改设置

    window --> pref -- scala 编译器 --> 标准 --> 目标 --> jvm-1.7

    【讨论】:

      【解决方案3】:

      在 SBT 0.13.6 中有一个新的 VersionNumber 类和 VersionNumberCompatibility 特征。调整@MarkHarrah 推荐的方法以使用此方法可能会执行以下操作:

      initialize := {
          val _ = initialize.value // run the previous initialization
          val required = VersionNumber("1.8")
          val curr = VersionNumber(sys.props("java.specification.version"))
          assert(CompatibleJavaVersion(curr, required), s"Java $required or above required")
      }
      
      ...
      /** Java specification version compatibility rule. */
      object CompatibleJavaVersion extends VersionNumberCompatibility {
          def name = "Java specification compatibility"
          def isCompatible(current: VersionNumber, required: VersionNumber) =
              current.numbers.zip(required.numbers).foldRight(required.numbers.size<=current.‌​numbers.size)((a,b) => (a._1 > a._2) || (a._1==a._2 && b))
          def apply(current: VersionNumber, required: VersionNumber) = isCompatible(current, required)
      }
      

      【讨论】:

      • 如果我们有一个 java 2.0,这个 isCompatible 定义会做错事。你想要的是current.numbers.zip(required.numbers).foldRight(required.numbers.size&lt;=current.numbers.size)((a,b) =&gt; (a._1 &gt; a._2) || (a._1==a._2 &amp;&amp; b))
      • 非常感谢@DanielMartin。更新了你的修复。
      • build.sbtproject 中的自定义插件。
      【解决方案4】:

      如果您没有 Java 源代码,则使用 javacOptions ++= Seq("-source", "1.7", "-target", "1.7") 不起作用。

      但您可以在 build.sbt 或 Build.scala 中为 Scala 编译器设置目标 JVM:

      scalacOptions += "-target:jvm-1.7"
      

      因此它在 JDK 6 上打印:

      $ sbt clean run
      [info] Set current project to default-cd5534 (in build file:/tmp/so/)
      [success] Total time: 0 s, completed 27.10.2013 14:31:43
      [info] Updating {file:/tmp/so/}default-cd5534...
      [info] Resolving org.fusesource.jansi#jansi;1.4 ...
      [info] Done updating.
      [info] Compiling 1 Scala source to /tmp/so/target/scala-2.10/classes...
      [info] Running Main 
      [error] (run-main) java.lang.UnsupportedClassVersionError: Main : Unsupported major.minor version 51.0
      java.lang.UnsupportedClassVersionError: Main : Unsupported major.minor version 51.0
              at java.lang.ClassLoader.defineClass1(Native Method)
              at java.lang.ClassLoader.defineClass(ClassLoader.java:634)
              at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
              at java.net.URLClassLoader.defineClass(URLClassLoader.java:277)
              at java.net.URLClassLoader.access$000(URLClassLoader.java:73)
              at java.net.URLClassLoader$1.run(URLClassLoader.java:212)
              at java.security.AccessController.doPrivileged(Native Method)
              at java.net.URLClassLoader.findClass(URLClassLoader.java:205)
              at java.lang.ClassLoader.loadClass(ClassLoader.java:321)
              at java.lang.ClassLoader.loadClass(ClassLoader.java:314)
      [trace] Stack trace suppressed: run last compile:run for the full output.
      java.lang.RuntimeException: Nonzero exit code: 1
              at scala.sys.package$.error(package.scala:27)
      [trace] Stack trace suppressed: run last compile:run for the full output.
      [error] (compile:run) Nonzero exit code: 1
      [error] Total time: 4 s, completed 27.10.2013 14:31:47
      

      注意:也许它只适用于最新的 SBT/Scalac 版本。

      【讨论】:

        【解决方案5】:

        作为 Scala 代码,您可以将断言放在构建定义中。 sbt 将initialize 定义为此类事情的常见位置,但您可以使用任何设置,包括自定义设置。例如,

        initialize := {
           val _ = initialize.value // run the previous initialization
           val classVersion = sys.props("java.class.version")
           val specVersion = sys.props("java.specification.version")
           assert(..., "Java N or above required")
        }
        

        【讨论】:

        • 这是有道理的。但是我错过了另一部分:我如何选择 SBT 使用哪个 JDK? (不知何故,我的 SBT 坚持使用 Java 7,而我需要 Java 8 库)。
        【解决方案6】:

        为了在 Java 7 中编译,您应该添加 javac 选项以使用源代码 1.7 进行编译。

        您应该将javacOptions ++= Seq("-source", "1.7") 添加到可以在 /project 文件夹中找到的 SBT 构建配置中。

        以下是 SBT 的参考资料: http://www.scala-sbt.org/release/docs/Detailed-Topics/Java-Sources.html

        【讨论】:

        • 好吧,如果有人会在 1.6 错误消息wouldn't be much comprehensive 上运行此代码。
        • SBT 的那部分处理“对编译 Java 源的支持”,但不涉及 Scala 使用的 Java VM。目前我没有在我的 scala 项目中编译任何 java 源代码,我只是使用 jdk6 中不可用的库,并且仅在 jdk7 中可用
        猜你喜欢
        • 2016-03-17
        • 2015-04-25
        • 1970-01-01
        • 2016-09-01
        • 2011-02-22
        • 1970-01-01
        • 2014-08-18
        • 2013-03-22
        • 2023-03-05
        相关资源
        最近更新 更多