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),
clean := clean.dependsOn(cleanIvy).value,
scalaCompilerBridgeBinaryJar := None,
scalaCompilerBridgeSource := ZincLmUtil.getDefaultBridgeModule(scalaVersion.value),
consoleProject / scalaCompilerBridgeSource := ZincLmUtil.getDefaultBridgeModule(
scalaCompilerBridgeBinaryJar := Def.settingDyn {
val sv = scalaVersion.value
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
),
)
@ -736,6 +740,18 @@ object Defaults extends BuildCommon {
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 = {
compilers := {
val st = state.value

View File

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

View File

@ -9,48 +9,34 @@ package sbt
package internal
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.io.IO
import sbt.internal.librarymanagement._
import sbt.internal.util.{ BufferedLogger, FullLogger }
import sbt.io.IO
import sbt.librarymanagement._
import sbt.librarymanagement.syntax._
import sbt.util.InterfaceUtil.{ toSupplier => f0 }
import xsbti.ArtifactInfo._
import xsbti.compile.{
ClasspathOptionsUtil,
CompilerBridgeProvider,
ScalaInstance => XScalaInstance
}
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 {
import xsbti.compile.ScalaInstance
final val binSeparator = "-bin_"
final val javaClassVersion = System.getProperty("java.class.version")
private[inc] final val sbtOrgTemp = JsonUtil.sbtOrgTemp
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[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. */
private class ZincCompilerBridgeProvider(
userProvidedBridgeSources: Option[ModuleID],
@ -67,7 +53,7 @@ private[sbt] object ZincComponentCompiler {
*/
def compiledBridge(
bridgeSources: ModuleID,
scalaInstance: ScalaInstance,
scalaInstance: XScalaInstance,
logger: Logger,
): File = lock.synchronized {
val raw = new RawCompiler(scalaInstance, ClasspathOptionsUtil.auto, logger)
@ -77,9 +63,10 @@ private[sbt] object ZincComponentCompiler {
zinc.compiledBridgeJar
}
override def fetchCompiledBridge(scalaInstance: ScalaInstance, logger: Logger): File = {
override def fetchCompiledBridge(scalaInstance: XScalaInstance, logger: Logger): File = {
val scalaVersion = scalaInstance.actualVersion()
val bridgeSources = userProvidedBridgeSources.getOrElse(getDefaultBridgeModule(scalaVersion))
val bridgeSources = userProvidedBridgeSources
.getOrElse(ZincLmUtil.getDefaultBridgeSourceModule(scalaVersion))
compiledBridge(bridgeSources, scalaInstance, logger)
}
@ -125,7 +112,7 @@ private[sbt] object ZincComponentCompiler {
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 scalaCompilerJar = scalaArtifacts.compilerJar
val scalaLibraryJars = scalaArtifacts.libraryJars
@ -141,7 +128,7 @@ private[sbt] object ZincComponentCompiler {
val properties = ResourceLoader.getSafePropertiesFor("compiler.properties", loader)
val loaderVersion = Option(properties.getProperty("version.number"))
val scalaV = loaderVersion.getOrElse("unknown")
new inc.ScalaInstance(
new ScalaInstance(
scalaV,
loader,
loaderLibraryOnly,

View File

@ -8,14 +8,21 @@
package sbt.internal.inc
import java.io.File
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.compile._
import xsbti.compile.{ ClasspathOptions, ScalaInstance => XScalaInstance }
object ZincLmUtil {
import xsbti.compile.ScalaInstance
/**
* Instantiate a Scala compiler that is instrumented to analyze dependencies.
@ -23,7 +30,7 @@ object ZincLmUtil {
* compilation.
*/
def scalaCompiler(
scalaInstance: ScalaInstance,
scalaInstance: XScalaInstance,
classpathOptions: ClasspathOptions,
globalLock: GlobalLock,
componentProvider: ComponentProvider,
@ -49,6 +56,48 @@ object ZincLmUtil {
)
}
def getDefaultBridgeModule(scalaVersion: String): ModuleID =
ZincComponentCompiler.getDefaultBridgeModule(scalaVersion)
def fetchDefaultBridgeModule(
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 _ => throw new IllegalStateException("No zinc version specified")
}
val bridge0 = ZincComponentCompiler.getDefaultBridgeModule(scalaVersion)
val bridge0 = ZincLmUtil.getDefaultBridgeSourceModule(scalaVersion)
// redefine the compiler bridge version
// using the version of zinc used during testing
// this way when building with zinc as a source dependency