Compiling Scala before / alongside Java with Gradle

If your java code use some external libraries like Lombok, using scala compiler to build java class will failed, as scala compiler don't know annotations.

My solution is to change the task dependencies, make compiling Scala before Java.

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

Now the task compileScala runs before compileJava, that's it.

If your java code depends on scala code, you need to do two more steps,

  1. Separate the output folder of scala and java,

    sourceSets {
        main {
            scala {
                outputDir = file("$buildDir/classes/scala/main")
            }
            java {
                outputDir = file("$buildDir/classes/java/main")
            }
        }
    
  2. Add the scala output as a dependency for compileJava,

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

Posting this update from the future here, as it would saved me a day.

gradle 6 doesn't support task dependencies modification, but here is what you can do:

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

And here is documentation.


Java and Scala can be combined in the scala sources to have them compiled jointly, e.g.

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

for gradle kotlin dsl you can use this piece

 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>())
        }
    }
}