Fetch Scala 3 compiler bridge binary module

Contrary to Scala 2, Scala 3 compiler bridges are tied to the compiler
version. There is one compiler bridge foreach compiler version.
Scala compiler bridges are pure java so they are binary compatible with
all Scala version. Consequently, we can fetch the binary module directly
without using the ZincCompilerBridgeProvider.
This commit is contained in:
Adrien Piquerez 2020-12-16 16:10:24 +01:00
parent c9478529e6
commit 08b83d6b31
5 changed files with 93 additions and 41 deletions

View File

@ -668,9 +668,13 @@ object Defaults extends BuildCommon {
), ),
cleanIvy := IvyActions.cleanCachedResolutionCache(ivyModule.value, streams.value.log), cleanIvy := IvyActions.cleanCachedResolutionCache(ivyModule.value, streams.value.log),
clean := clean.dependsOn(cleanIvy).value, clean := clean.dependsOn(cleanIvy).value,
scalaCompilerBridgeBinaryJar := None, scalaCompilerBridgeBinaryJar := Def.settingDyn {
scalaCompilerBridgeSource := ZincLmUtil.getDefaultBridgeModule(scalaVersion.value), val sv = scalaVersion.value
consoleProject / scalaCompilerBridgeSource := ZincLmUtil.getDefaultBridgeModule( if (ScalaArtifacts.isScala3(sv)) fetchBridgeBinaryJarTask(sv)
else Def.task[Option[File]](None)
}.value,
scalaCompilerBridgeSource := ZincLmUtil.getDefaultBridgeSourceModule(scalaVersion.value),
consoleProject / scalaCompilerBridgeSource := ZincLmUtil.getDefaultBridgeSourceModule(
appConfiguration.value.provider.scalaProvider.version appConfiguration.value.provider.scalaProvider.version
), ),
) )
@ -736,6 +740,18 @@ object Defaults extends BuildCommon {
if (plugin) scalaBase / ("sbt-" + sbtv) else scalaBase if (plugin) scalaBase / ("sbt-" + sbtv) else scalaBase
} }
private def fetchBridgeBinaryJarTask(scalaVersion: String): Initialize[Task[Option[File]]] =
Def.task {
val bridgeJar = ZincLmUtil.fetchDefaultBridgeModule(
scalaVersion,
dependencyResolution.value,
updateConfiguration.value,
(update / unresolvedWarningConfiguration).value,
streams.value.log
)
Some(bridgeJar)
}
def compilersSetting = { def compilersSetting = {
compilers := { compilers := {
val st = state.value val st = state.value

View File

@ -85,7 +85,7 @@ private[sbt] object Load {
componentProvider = app.provider.components, componentProvider = app.provider.components,
secondaryCacheDir = Option(zincDir), secondaryCacheDir = Option(zincDir),
dependencyResolution = dependencyResolution, dependencyResolution = dependencyResolution,
compilerBridgeSource = ZincLmUtil.getDefaultBridgeModule(scalaProvider.version), compilerBridgeSource = ZincLmUtil.getDefaultBridgeSourceModule(scalaProvider.version),
scalaJarsTarget = zincDir, scalaJarsTarget = zincDir,
state.get(BasicKeys.classLoaderCache), state.get(BasicKeys.classLoaderCache),
log = log log = log

View File

@ -9,48 +9,34 @@ package sbt
package internal package internal
package inc package inc
import java.io.File
import java.nio.file.{ Files, Path }
import java.util.concurrent.Callable
import sbt.internal.inc.classpath.ClasspathUtil import sbt.internal.inc.classpath.ClasspathUtil
import sbt.io.IO
import sbt.internal.librarymanagement._ import sbt.internal.librarymanagement._
import sbt.internal.util.{ BufferedLogger, FullLogger } import sbt.internal.util.{ BufferedLogger, FullLogger }
import sbt.io.IO
import sbt.librarymanagement._ import sbt.librarymanagement._
import sbt.librarymanagement.syntax._ import sbt.librarymanagement.syntax._
import sbt.util.InterfaceUtil.{ toSupplier => f0 } import sbt.util.InterfaceUtil.{ toSupplier => f0 }
import xsbti.ArtifactInfo._ import xsbti.ArtifactInfo._
import xsbti.compile.{
ClasspathOptionsUtil,
CompilerBridgeProvider,
ScalaInstance => XScalaInstance
}
import xsbti.{ ComponentProvider, GlobalLock, Logger } import xsbti.{ ComponentProvider, GlobalLock, Logger }
import xsbti.compile.{ ClasspathOptionsUtil, CompilerBridgeProvider }
import java.io.File
import java.nio.file.{ Files, Path }
import java.util.concurrent.Callable
private[sbt] object ZincComponentCompiler { private[sbt] object ZincComponentCompiler {
import xsbti.compile.ScalaInstance
final val binSeparator = "-bin_" final val binSeparator = "-bin_"
final val javaClassVersion = System.getProperty("java.class.version") final val javaClassVersion = System.getProperty("java.class.version")
private[inc] final val sbtOrgTemp = JsonUtil.sbtOrgTemp private[inc] final val sbtOrgTemp = JsonUtil.sbtOrgTemp
private[inc] final val modulePrefixTemp = "temp-module-" private[inc] final val modulePrefixTemp = "temp-module-"
private[sbt] final lazy val incrementalVersion: String = ZincComponentManager.version
private val CompileConf = Some(Configurations.Compile.name)
private val lock: AnyRef = new {} private val lock: AnyRef = new {}
private[sbt] def getDefaultBridgeModule(scalaVersion: String): ModuleID = {
val compilerBridgeId = scalaVersion match {
case sc if (sc startsWith "2.10.") => "compiler-bridge_2.10"
case sc if (sc startsWith "2.11.") => "compiler-bridge_2.11"
case sc if (sc startsWith "2.12.") => "compiler-bridge_2.12"
case "2.13.0-M1" => "compiler-bridge_2.12"
case _ => "compiler-bridge_2.13"
}
ModuleID(SbtOrganization, compilerBridgeId, incrementalVersion)
.withConfigurations(CompileConf)
.sources()
}
/** Defines the internal implementation of a bridge provider. */ /** Defines the internal implementation of a bridge provider. */
private class ZincCompilerBridgeProvider( private class ZincCompilerBridgeProvider(
userProvidedBridgeSources: Option[ModuleID], userProvidedBridgeSources: Option[ModuleID],
@ -67,7 +53,7 @@ private[sbt] object ZincComponentCompiler {
*/ */
def compiledBridge( def compiledBridge(
bridgeSources: ModuleID, bridgeSources: ModuleID,
scalaInstance: ScalaInstance, scalaInstance: XScalaInstance,
logger: Logger, logger: Logger,
): File = lock.synchronized { ): File = lock.synchronized {
val raw = new RawCompiler(scalaInstance, ClasspathOptionsUtil.auto, logger) val raw = new RawCompiler(scalaInstance, ClasspathOptionsUtil.auto, logger)
@ -77,9 +63,10 @@ private[sbt] object ZincComponentCompiler {
zinc.compiledBridgeJar zinc.compiledBridgeJar
} }
override def fetchCompiledBridge(scalaInstance: ScalaInstance, logger: Logger): File = { override def fetchCompiledBridge(scalaInstance: XScalaInstance, logger: Logger): File = {
val scalaVersion = scalaInstance.actualVersion() val scalaVersion = scalaInstance.actualVersion()
val bridgeSources = userProvidedBridgeSources.getOrElse(getDefaultBridgeModule(scalaVersion)) val bridgeSources = userProvidedBridgeSources
.getOrElse(ZincLmUtil.getDefaultBridgeSourceModule(scalaVersion))
compiledBridge(bridgeSources, scalaInstance, logger) compiledBridge(bridgeSources, scalaInstance, logger)
} }
@ -125,7 +112,7 @@ private[sbt] object ZincComponentCompiler {
ScalaArtifacts(scalaCompilerJar, Vector(scalaLibraryJar), others) ScalaArtifacts(scalaCompilerJar, Vector(scalaLibraryJar), others)
} }
override def fetchScalaInstance(scalaVersion: String, logger: Logger): ScalaInstance = { override def fetchScalaInstance(scalaVersion: String, logger: Logger): XScalaInstance = {
val scalaArtifacts = getScalaArtifacts(scalaVersion, logger) val scalaArtifacts = getScalaArtifacts(scalaVersion, logger)
val scalaCompilerJar = scalaArtifacts.compilerJar val scalaCompilerJar = scalaArtifacts.compilerJar
val scalaLibraryJars = scalaArtifacts.libraryJars val scalaLibraryJars = scalaArtifacts.libraryJars
@ -141,7 +128,7 @@ private[sbt] object ZincComponentCompiler {
val properties = ResourceLoader.getSafePropertiesFor("compiler.properties", loader) val properties = ResourceLoader.getSafePropertiesFor("compiler.properties", loader)
val loaderVersion = Option(properties.getProperty("version.number")) val loaderVersion = Option(properties.getProperty("version.number"))
val scalaV = loaderVersion.getOrElse("unknown") val scalaV = loaderVersion.getOrElse("unknown")
new inc.ScalaInstance( new ScalaInstance(
scalaV, scalaV,
loader, loader,
loaderLibraryOnly, loaderLibraryOnly,

View File

@ -8,14 +8,21 @@
package sbt.internal.inc package sbt.internal.inc
import java.io.File import java.io.File
import sbt.internal.inc.classpath.ClassLoaderCache import sbt.internal.inc.classpath.ClassLoaderCache
import sbt.librarymanagement.{ DependencyResolution, ModuleID } import sbt.internal.util.MessageOnlyException
import sbt.librarymanagement.{
DependencyResolution,
ModuleID,
ScalaArtifacts,
UnresolvedWarningConfiguration,
UpdateConfiguration
}
import sbt.librarymanagement.syntax._
import xsbti.ArtifactInfo.SbtOrganization
import xsbti._ import xsbti._
import xsbti.compile._ import xsbti.compile.{ ClasspathOptions, ScalaInstance => XScalaInstance }
object ZincLmUtil { object ZincLmUtil {
import xsbti.compile.ScalaInstance
/** /**
* Instantiate a Scala compiler that is instrumented to analyze dependencies. * Instantiate a Scala compiler that is instrumented to analyze dependencies.
@ -23,7 +30,7 @@ object ZincLmUtil {
* compilation. * compilation.
*/ */
def scalaCompiler( def scalaCompiler(
scalaInstance: ScalaInstance, scalaInstance: XScalaInstance,
classpathOptions: ClasspathOptions, classpathOptions: ClasspathOptions,
globalLock: GlobalLock, globalLock: GlobalLock,
componentProvider: ComponentProvider, componentProvider: ComponentProvider,
@ -49,6 +56,48 @@ object ZincLmUtil {
) )
} }
def getDefaultBridgeModule(scalaVersion: String): ModuleID = def fetchDefaultBridgeModule(
ZincComponentCompiler.getDefaultBridgeModule(scalaVersion) scalaVersion: String,
dependencyResolution: DependencyResolution,
updateConfiguration: UpdateConfiguration,
warningConfig: UnresolvedWarningConfiguration,
logger: Logger
): File = {
val bridgeModule = getDefaultBridgeModule(scalaVersion)
val descriptor = dependencyResolution.wrapDependencyInModule(bridgeModule)
dependencyResolution
.update(descriptor, updateConfiguration, warningConfig, logger)
.toOption
.flatMap { report =>
val jars = report.select(
configurationFilter(Compile.name),
moduleFilter(bridgeModule.organization, bridgeModule.name, bridgeModule.revision),
artifactFilter(`extension` = "jar", classifier = "")
)
if (jars.size > 1)
sys.error(s"There should be only one jar for $bridgeModule but found $jars")
else jars.headOption
}
.getOrElse(throw new MessageOnlyException(s"Missing $bridgeModule"))
}
def getDefaultBridgeModule(scalaVersion: String): ModuleID = {
if (ScalaArtifacts.isScala3(scalaVersion)) {
ModuleID(ScalaArtifacts.Organization, "scala3-sbt-bridge", scalaVersion)
.withConfigurations(Some(Compile.name))
} else {
val compilerBridgeId = scalaVersion match {
case sc if sc startsWith "2.10." => "compiler-bridge_2.10"
case sc if sc startsWith "2.11." => "compiler-bridge_2.11"
case sc if sc startsWith "2.12." => "compiler-bridge_2.12"
case "2.13.0-M1" => "compiler-bridge_2.12"
case _ => "compiler-bridge_2.13"
}
ModuleID(SbtOrganization, compilerBridgeId, ZincComponentManager.version)
.withConfigurations(Some(Compile.name))
}
}
def getDefaultBridgeSourceModule(scalaVersion: String): ModuleID =
getDefaultBridgeModule(scalaVersion).sources()
} }

View File

@ -62,7 +62,7 @@ abstract class IvyBridgeProviderSpecification
case Some(v: String) => v case Some(v: String) => v
case _ => throw new IllegalStateException("No zinc version specified") case _ => throw new IllegalStateException("No zinc version specified")
} }
val bridge0 = ZincComponentCompiler.getDefaultBridgeModule(scalaVersion) val bridge0 = ZincLmUtil.getDefaultBridgeSourceModule(scalaVersion)
// redefine the compiler bridge version // redefine the compiler bridge version
// using the version of zinc used during testing // using the version of zinc used during testing
// this way when building with zinc as a source dependency // this way when building with zinc as a source dependency