mirror of https://github.com/sbt/sbt.git
Break the dependency on LM, and thus Ivy
This patch breaks the dependency that Zinc had on sbt's Library Management (LM) library abstraction (sbt/librarymanagement) and thus, transitively, on Ivy. The reason Zinc depends on LM in the first place is to dynamically download the compiler bridge sources JAR, which it then compiles in order to bridge from binary-compatible Zinc to the never-binary-stable (and most of the time source-compatible) compiler API. From my research (that is, using GitHub Search) the only user of this feature is sbt, with all other integrations (e.g. pants, bloop, mill) providing the compiler bridge sources JAR directly (an alternative API entry point). Therefore the dependency on LM and that integration code could be untangled from Zinc and moved into sbt. That would also give an opportunity to move the code in LM (back) into sbt, which I also think would be a good idea. For now this patch leaves that integration code in the already existing `zinc-ivy-integration` module, but which is now no longer a dependency of any other module of Zinc, specifically it is no longer a dependency of the `zinc` and `zincScripted` modules. I think, though, zinc-ivy-integration should remain in the zinc repo, as a part of the build, being tested in CI, until it's been moved (back) into sbt. I'd be happy to take care of both the remaining move and removal tasks. In order to allow removing LM, Ivy and zinc-ivy-integration as transitive dependencies of Zinc, this patch has to make a breaking change to the `ZincUtil` object in the zinc module. Despite it being defined in the `sbt.internal.inc` package (i.e. not declared as public API) ZincUtil is in fact a used (Scala) API of Zinc (usages discovered via GitHub Search). Therefore I chose to leave the object in the zinc module and only drop from the object the two methods that directly depend on LM's API. Specifically (1) the `getDefaultBridgeModule` method and (2) the `scalaCompiler` overload that depends on LM were removed. These methods now live in a new `ZincLmUtil` object in zinc-ivy-integration, which sbt can switch to using. In terms of risk, from my research (GitHub Search) the only users of those methods are sbt and bloop. I need to confirm but I think bloop will be able to manage this breaking change (it looks it might be just fallback usage? TBC). For sbt we don't actual support using new Zinc with old sbt, so sbt can also just update its usage on its next release. Any other usage risks being broken but given it's internal, non-public API I think it's fair game. The remaining changes are in the testing so that zinc-ivy-integration's test suite continues to test its download-and-compile behaviour, while the rest of Zinc switches to using the prebuilt compiler bridges, reusing and generalising some pre-existing zincScripted code (as well as re-wiring some modules) so it can be used by zinc's tests too.
This commit is contained in:
parent
c61773af03
commit
146afdf8cd
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* Zinc - The incremental compiler for Scala.
|
||||
* Copyright 2011 - 2017, Lightbend, Inc.
|
||||
* Copyright 2008 - 2010, Mark Harrah
|
||||
* This software is released under the terms written in LICENSE.
|
||||
*/
|
||||
|
||||
package sbt.internal.inc
|
||||
|
||||
import java.io.File
|
||||
import java.net.URLClassLoader
|
||||
|
||||
import sbt.librarymanagement.{ DependencyResolution, ModuleID }
|
||||
import sbt.internal.inc.classpath.ClassLoaderCache
|
||||
import xsbti._
|
||||
import xsbti.compile._
|
||||
|
||||
object ZincLmUtil {
|
||||
import xsbti.compile.ScalaInstance
|
||||
|
||||
/**
|
||||
* Instantiate a Scala compiler that is instrumented to analyze dependencies.
|
||||
* This Scala compiler is useful to create your own instance of incremental
|
||||
* compilation.
|
||||
*/
|
||||
def scalaCompiler(
|
||||
scalaInstance: ScalaInstance,
|
||||
classpathOptions: ClasspathOptions,
|
||||
globalLock: GlobalLock,
|
||||
componentProvider: ComponentProvider,
|
||||
secondaryCacheDir: Option[File],
|
||||
dependencyResolution: DependencyResolution,
|
||||
compilerBridgeSource: ModuleID,
|
||||
scalaJarsTarget: File,
|
||||
log: Logger
|
||||
): AnalyzingCompiler = {
|
||||
val compilerBridgeProvider = ZincComponentCompiler.interfaceProvider(
|
||||
compilerBridgeSource,
|
||||
new ZincComponentManager(globalLock, componentProvider, secondaryCacheDir, log),
|
||||
dependencyResolution,
|
||||
scalaJarsTarget,
|
||||
)
|
||||
val loader = Some(new ClassLoaderCache(new URLClassLoader(new Array(0))))
|
||||
new AnalyzingCompiler(scalaInstance, compilerBridgeProvider, classpathOptions, _ => (), loader)
|
||||
}
|
||||
|
||||
def getDefaultBridgeModule(scalaVersion: String): ModuleID =
|
||||
ZincComponentCompiler.getDefaultBridgeModule(scalaVersion)
|
||||
}
|
||||
|
|
@ -2,7 +2,6 @@ package sbt.internal.inc
|
|||
|
||||
import java.io.File
|
||||
|
||||
import sbt.io.IO
|
||||
import sbt.io.syntax._
|
||||
import sbt.librarymanagement._
|
||||
import sbt.librarymanagement.ivy._
|
||||
|
|
@ -14,7 +13,7 @@ import xsbti.compile.CompilerBridgeProvider
|
|||
*
|
||||
* This is a very good example on how to instantiate the compiler bridge provider.
|
||||
*/
|
||||
abstract class BridgeProviderSpecification extends UnitSpec {
|
||||
abstract class IvyBridgeProviderSpecification extends UnitSpec with AbstractBridgeProviderTestkit {
|
||||
def currentBase: File = new File(".")
|
||||
def currentTarget: File = currentBase / "target" / "ivyhome"
|
||||
def currentManaged: File = currentBase / "target" / "lib_managed"
|
||||
|
|
@ -37,22 +36,6 @@ abstract class BridgeProviderSpecification extends UnitSpec {
|
|||
ZincComponentCompiler.interfaceProvider(manager, dependencyResolution, currentManaged)
|
||||
}
|
||||
|
||||
def getCompilerBridge(targetDir: File, log: Logger, scalaVersion: String): File = {
|
||||
val provider = getZincProvider(targetDir, log)
|
||||
val scalaInstance = provider.fetchScalaInstance(scalaVersion, log)
|
||||
val bridge = provider.fetchCompiledBridge(scalaInstance, log)
|
||||
val target = targetDir / s"target-bridge-$scalaVersion.jar"
|
||||
IO.copyFile(bridge, target)
|
||||
target
|
||||
}
|
||||
|
||||
def scalaInstance(scalaVersion: String,
|
||||
targetDir: File,
|
||||
logger: Logger): xsbti.compile.ScalaInstance = {
|
||||
val provider = getZincProvider(targetDir, logger)
|
||||
provider.fetchScalaInstance(scalaVersion, logger)
|
||||
}
|
||||
|
||||
private def getDefaultConfiguration(baseDirectory: File,
|
||||
ivyHome: File,
|
||||
resolvers0: Array[Resolver],
|
||||
|
|
@ -3,7 +3,7 @@ package sbt.internal.inc
|
|||
import sbt.internal.util.ConsoleLogger
|
||||
import sbt.io.IO
|
||||
|
||||
class ZincComponentCompilerSpec extends BridgeProviderSpecification {
|
||||
class ZincComponentCompilerSpec extends IvyBridgeProviderSpecification {
|
||||
val scala2105 = "2.10.5"
|
||||
val scala2106 = "2.10.6"
|
||||
val scala2118 = "2.11.8"
|
||||
|
|
|
|||
Loading…
Reference in New Issue