diff --git a/main/src/main/scala/sbt/Defaults.scala b/main/src/main/scala/sbt/Defaults.scala index f0a28d3be..3f3f1cd80 100644 --- a/main/src/main/scala/sbt/Defaults.scala +++ b/main/src/main/scala/sbt/Defaults.scala @@ -988,6 +988,22 @@ object Defaults extends BuildCommon with DefExtra { val converter = fileConverter.value val cp = cp1.map(converter.toPath).map(converter.toVirtualFile) opts.withClasspath(cp.toArray) + }, + compileInputs2 := Def.uncached { + compileScalaBackend.value + val (_, _, packedBackendOutput) = compileIncremental.value + val inputs = compileInputs.value + val c = fileConverter.value + CompileInputs2( + packedBackendOutput +: data(dependencyClasspath.value).toVector, + sourcesVF.value, + scalacOptions.value.toVector, + javacOptions.value.toVector, + c.toVirtualFile(inputs.options.classesDirectory), + c.toVirtualFile(inputs.setup.cacheFile.toPath), + extraIncOptions.value.toVector, + scalaVersion.value, + ) } ) ) ++ @@ -2317,26 +2333,50 @@ object Defaults extends BuildCommon with DefExtra { private val incCompiler = ZincUtil.defaultIncrementalCompiler private[sbt] def compileJavaTask: Initialize[Task[CompileResult]] = Def.task { - val s = streams.value - val projectId = thisProject.value.id - val r = compileScalaBackend.value - val in0 = (compileJava / compileInputs).value - val in = in0.withPreviousResult(PreviousResult.of(r.analysis, r.setup)) + val backendResult = compileScalaBackend.value + val result = cachedCompileJavaTask.result.value val reporter = (compile / bspReporter).value - val log = CompileDebugLogger(projectId, s.log) - try { - val result0 = incCompiler - .asInstanceOf[sbt.internal.inc.IncrementalCompilerImpl] - .compileAllJava(in, log) - reporter.sendSuccessReport(result0.analysis()) - result0.withHasModified(result0.hasModified || r.hasModified) - } catch { - case NonFatal(e) => - reporter.sendFailureReport(in.options.sources) - throw e + val inputs = (compileJava / compileInputs).value + val c = fileConverter.value + result match { + case Result.Value(hasModified) => + val store = analysisStore(compileAnalysisFile.value.toPath(), c) + val contents = store.unsafeGet() + reporter.sendSuccessReport(contents.getAnalysis()) + CompileResult.of( + contents.getAnalysis(), + contents.getMiniSetup(), + hasModified || backendResult.hasModified + ) + case Result.Inc(cause) => + reporter.sendFailureReport(inputs.options.sources) + throw cause } } + private val cachedCompileJavaTask = Def + .cachedTask { + val s = streams.value + val projectId = projectIdFromScope(s) + val in0 = (compileJava / compileInputs).value + val ci2 = (compileJava / compileInputs2).value + val c = fileConverter.value + val store = analysisStore(compileAnalysisFile.value.toPath(), c) + val previous = store.unsafeGet() + val in = in0.withPreviousResult( + PreviousResult.of(previous.getAnalysis(), previous.getMiniSetup()) + ) + val log = CompileDebugLogger(projectId, s.log) + val result = incCompiler + .asInstanceOf[sbt.internal.inc.IncrementalCompilerImpl] + .compileAllJava(in, log) + store.set(AnalysisContents.create(result.analysis(), result.setup())) + Def.declareOutput(c.toVirtualFile(in.setup.cacheFile.toPath)) + Def.declareOutputDirectory(c.toVirtualFile(in.options.classesDirectory)) + result.hasModified + } + .tag(Tags.Compile, Tags.CPU) + private def compileIncrementalTaskImpl( task: BspCompileTask, s: TaskStreams, @@ -4413,9 +4453,9 @@ object Classpaths { def makeProducts: Initialize[Task[Seq[File]]] = Def.task { val c = fileConverter.value val resourceDirs = resourceDirectories.value - val _ = compile.value + compile.value val backendDir = c.toPath(backendOutput.value) - val _ = resources.value + resources.value backendDir.toFile() :: resourceDirs.toList.filter(_.exists()) } diff --git a/sbt-app/src/sbt-test/source-dependencies/pipelining-java-scala-no-export/build.sbt b/sbt-app/src/sbt-test/source-dependencies/pipelining-java-scala-no-export/build.sbt index ab6b936fa..7c795b19e 100644 --- a/sbt-app/src/sbt-test/source-dependencies/pipelining-java-scala-no-export/build.sbt +++ b/sbt-app/src/sbt-test/source-dependencies/pipelining-java-scala-no-export/build.sbt @@ -1,6 +1,31 @@ ThisBuild / scalaVersion := "2.13.18" ThisBuild / usePipelining := true +def countedCompilers(counter: File)(cs: xsbti.compile.Compilers): xsbti.compile.Compilers = { + val tools = cs.javaTools() + val underlying = tools.javac() + val counted = new xsbti.compile.JavaCompiler { + override def run( + sources: Array[xsbti.VirtualFile], + options: Array[String], + output: xsbti.compile.Output, + incToolOptions: xsbti.compile.IncToolOptions, + reporter: xsbti.Reporter, + log: xsbti.Logger + ): Boolean = { + IO.append(counter, "javac\n") + underlying.run(sources, options, output, incToolOptions, reporter, log) + } + + override def supportsDirectToJar(): Boolean = + underlying.supportsDirectToJar() + } + cs.withJavaTools(new xsbti.compile.JavaTools { + override def javac(): xsbti.compile.JavaCompiler = counted + override def javadoc(): xsbti.compile.Javadoc = tools.javadoc() + }) +} + lazy val root = (project in file(".")) .aggregate(upstream, downstream) @@ -8,6 +33,7 @@ lazy val upstream = project .settings( exportJars := true, exportPipelining := false, + Compile / compilers ~= countedCompilers(file("javac-invocations")), ) lazy val downstream = project diff --git a/sbt-app/src/sbt-test/source-dependencies/pipelining-java-scala-no-export/changes/Greeter.java b/sbt-app/src/sbt-test/source-dependencies/pipelining-java-scala-no-export/changes/Greeter.java new file mode 100644 index 000000000..acf9bccbd --- /dev/null +++ b/sbt-app/src/sbt-test/source-dependencies/pipelining-java-scala-no-export/changes/Greeter.java @@ -0,0 +1,7 @@ +package example; + +public class Greeter { + public static String greet(String name) { + return "Updated, " + name; + } +} diff --git a/sbt-app/src/sbt-test/source-dependencies/pipelining-java-scala-no-export/changes/Marker.scala b/sbt-app/src/sbt-test/source-dependencies/pipelining-java-scala-no-export/changes/Marker.scala new file mode 100644 index 000000000..f1765f7f9 --- /dev/null +++ b/sbt-app/src/sbt-test/source-dependencies/pipelining-java-scala-no-export/changes/Marker.scala @@ -0,0 +1,5 @@ +package example + +object Marker { + val tag = "updated" +} diff --git a/sbt-app/src/sbt-test/source-dependencies/pipelining-java-scala-no-export/downstream/src/main/scala/example/Main.scala b/sbt-app/src/sbt-test/source-dependencies/pipelining-java-scala-no-export/downstream/src/main/scala/example/Main.scala index 2f9d069ab..6543cf0ae 100644 --- a/sbt-app/src/sbt-test/source-dependencies/pipelining-java-scala-no-export/downstream/src/main/scala/example/Main.scala +++ b/sbt-app/src/sbt-test/source-dependencies/pipelining-java-scala-no-export/downstream/src/main/scala/example/Main.scala @@ -2,4 +2,7 @@ package example object Main { def run(): String = Greeter.greet("world") + + def main(args: Array[String]): Unit = + assert(run() == "Updated, world") } diff --git a/sbt-app/src/sbt-test/source-dependencies/pipelining-java-scala-no-export/test b/sbt-app/src/sbt-test/source-dependencies/pipelining-java-scala-no-export/test index f1663090b..f8d4e566c 100644 --- a/sbt-app/src/sbt-test/source-dependencies/pipelining-java-scala-no-export/test +++ b/sbt-app/src/sbt-test/source-dependencies/pipelining-java-scala-no-export/test @@ -2,3 +2,20 @@ $ exists target/**/upstream/classes/example/Greeter.class $ exists target/**/downstream/classes/example/Main.class + +$ copy-file javac-invocations javac-before +> compile +$ must-mirror javac-before javac-invocations + +$ copy-file changes/Marker.scala upstream/src/main/scala/example/Marker.scala +> compile + +$ copy-file changes/Greeter.java upstream/src/main/java/example/Greeter.java +> compile +> downstream / run +$ copy-file javac-invocations javac-after-java + +$ delete target/out/jvm/scala-2.13.18/upstream/classes/example/Greeter.class +> compile +$ exists target/out/jvm/scala-2.13.18/upstream/classes/example/Greeter.class +$ must-mirror javac-after-java javac-invocations