【问题标题】:Compiling Scala before / alongside Java with Gradle使用 Gradle 在 Java 之前/旁边编译 Scala
【发布时间】:2014-06-09 06:38:10
【问题描述】:

默认的 scala 插件任务流在 Scala 之前编译 Java,因此在 Java 中导入 Scala 源代码会导致“错误:找不到符号”。

【问题讨论】:

    标签: java scala compiler-errors gradle cross-compiling


    【解决方案1】:

    我找到了以下 sourceSet 配置来解决问题:

    sourceSets {
        main {
            scala {
                srcDirs = ['src/main/scala', 'src/main/java']
            }
            java {
                srcDirs = []
            }
    }
    

    这是因为 scala 源集可以同时包含 java 和 scala 源。

    【讨论】:

    • 如果你想把 Java 和 Scala 的源代码放在不同的目录中,并且希望所有代码联合编译,这是正确的解决方案。另一种方法是保持默认设置,将要联合编译的 Java 代码放入 src/main/scala,将剩余的 Java 代码(如果有)放入 src/main/java
    • 谢谢。我们想知道使用 compileScala 编译的 Java 代码的行为是否与使用 compileJava 编译时的行为有所不同。我们假设它们使用相同的编译器,因此在下面生成相同的字节码,但允许链接到 scala 源。对吗?
    • 联合编译由Scala编译器控制,在这种情况下负责调用Java编译器。结果通常应该是相同的。请注意,您必须配置 compileScala.options 而不是 compileJava.options 才能影响联合编译 Java 代码的 Java 编译选项。 (Scala 编译选项通过compileScala.scalaCompileOptions 控制。)您可能希望将任何此类配置应用于所有编译任务(例如tasks.withType(ScalaCompile) { options ... })。
    • 一开始我在尝试这种技术时错过了它:如果你在 Scala srcDirs 中包含 src/main/java,那么将 Java srcDirs 设置为空数组很重要。
    【解决方案2】:

    如果你的java代码使用了Lombok等外部库,使用scala编译器构建java类会失败,因为scala编译器不知道注解。

    我的解决方案是改变任务依赖,在Java之前编译Scala。

    tasks.compileJava.dependsOn compileScala
    tasks.compileScala.dependsOn.remove("compileJava")
    

    现在任务compileScalacompileJava 之前运行,就是这样。

    如果你的java代码依赖scala代码,你需要多做两步,

    1. 分离scala和java的输出文件夹,

      sourceSets {
          main {
              scala {
                  outputDir = file("$buildDir/classes/scala/main")
              }
              java {
                  outputDir = file("$buildDir/classes/java/main")
              }
          }
      
    2. 将 scala 输出添加为 compileJava 的依赖项,

      dependencies {
          compile files("$sourceSets.main.scala.outputDir")
      }
      

    【讨论】:

    • 你救了我。谢谢你:)
    • 在 Gradle 6 中不起作用,因为不再支持任务删除。
    【解决方案3】:

    对于 gradle kotlin dsl 你可以使用这块

     sourceSets {
    
        main {
            withConvention(ScalaSourceSet::class) {
                scala {
                    setSrcDirs(listOf("src/main/scala", "src/main/java"))
                }
            }
            java {
                setSrcDirs(emptyList<String>())
            }
        }
        test {
            withConvention(ScalaSourceSet::class) {
                scala {
                    setSrcDirs(listOf("src/test/scala", "src/test/java"))
                }
            }
            java {
                setSrcDirs(emptyList<String>())
            }
        }
    }
    

    【讨论】:

      【解决方案4】:

      在这里发布未来的更新,因为它可以节省我一天的时间。

      gradle 6 不支持任务依赖修改,但是你可以这样做:

      // to compile Java after Scala
      tasks.compileScala.classpath = sourceSets.main.compileClasspath
      tasks.compileJava.classpath += files(sourceSets.main.scala.classesDirectory)
      

      这里是documentation

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-12-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多