mirror of https://github.com/sbt/sbt.git
Merge pull request #2106 from Duhemm/interface-specific-sources-clean
Find most specific version of compiler interface sources
This commit is contained in:
commit
5824ef6d7f
78
build.sbt
78
build.sbt
|
|
@ -81,17 +81,6 @@ lazy val bundledLauncherProj =
|
||||||
packageBin in Compile := sbtLaunchJar.value
|
packageBin in Compile := sbtLaunchJar.value
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
// This is used only for command aggregation
|
|
||||||
lazy val allPrecompiled: Project = (project in file("all-precompiled")).
|
|
||||||
aggregate(precompiled282, precompiled292, precompiled293).
|
|
||||||
settings(
|
|
||||||
buildLevelSettings,
|
|
||||||
minimalSettings,
|
|
||||||
publish := {},
|
|
||||||
publishLocal := {}
|
|
||||||
)
|
|
||||||
|
|
||||||
/* ** subproject declarations ** */
|
/* ** subproject declarations ** */
|
||||||
|
|
||||||
// defines Java structures used across Scala versions, such as the API structures and relationships extracted by
|
// defines Java structures used across Scala versions, such as the API structures and relationships extracted by
|
||||||
|
|
@ -199,7 +188,7 @@ lazy val logProj = (project in utilPath / "log").
|
||||||
testedBaseSettings,
|
testedBaseSettings,
|
||||||
name := "Logging",
|
name := "Logging",
|
||||||
libraryDependencies += jline
|
libraryDependencies += jline
|
||||||
)
|
)
|
||||||
|
|
||||||
// Relation
|
// Relation
|
||||||
lazy val relationProj = (project in utilPath / "relation").
|
lazy val relationProj = (project in utilPath / "relation").
|
||||||
|
|
@ -317,7 +306,7 @@ lazy val compileInterfaceProj = (project in compilePath / "interface").
|
||||||
dependsOn(interfaceProj % "compile;test->test", ioProj % "test->test", logProj % "test->test", /*launchProj % "test->test",*/ apiProj % "test->test").
|
dependsOn(interfaceProj % "compile;test->test", ioProj % "test->test", logProj % "test->test", /*launchProj % "test->test",*/ apiProj % "test->test").
|
||||||
settings(
|
settings(
|
||||||
baseSettings,
|
baseSettings,
|
||||||
precompiledSettings,
|
libraryDependencies += scalaCompiler.value % "provided",
|
||||||
name := "Compiler Interface",
|
name := "Compiler Interface",
|
||||||
exportJars := true,
|
exportJars := true,
|
||||||
// we need to fork because in unit tests we set usejavacp = true which means
|
// we need to fork because in unit tests we set usejavacp = true which means
|
||||||
|
|
@ -327,13 +316,9 @@ lazy val compileInterfaceProj = (project in compilePath / "interface").
|
||||||
// needed because we fork tests and tests are ran in parallel so we have multiple Scala
|
// needed because we fork tests and tests are ran in parallel so we have multiple Scala
|
||||||
// compiler instances that are memory hungry
|
// compiler instances that are memory hungry
|
||||||
javaOptions in Test += "-Xmx1G",
|
javaOptions in Test += "-Xmx1G",
|
||||||
artifact in (Compile, packageSrc) := Artifact(srcID).copy(configurations = Compile :: Nil).extra("e:component" -> srcID)
|
publishArtifact in (Compile, packageSrc) := true
|
||||||
)
|
)
|
||||||
|
|
||||||
lazy val precompiled282 = precompiled(scala282)
|
|
||||||
lazy val precompiled292 = precompiled(scala292)
|
|
||||||
lazy val precompiled293 = precompiled(scala293)
|
|
||||||
|
|
||||||
// Implements the core functionality of detecting and propagating changes incrementally.
|
// Implements the core functionality of detecting and propagating changes incrementally.
|
||||||
// Defines the data structures for representing file fingerprints and relationships and the overall source analysis
|
// Defines the data structures for representing file fingerprints and relationships and the overall source analysis
|
||||||
lazy val compileIncrementalProj = (project in compilePath / "inc").
|
lazy val compileIncrementalProj = (project in compilePath / "inc").
|
||||||
|
|
@ -442,7 +427,7 @@ lazy val mainProj = (project in mainPath).
|
||||||
// technically, we need a dependency on all of mainProj's dependencies, but we don't do that since this is strictly an integration project
|
// technically, we need a dependency on all of mainProj's dependencies, but we don't do that since this is strictly an integration project
|
||||||
// with the sole purpose of providing certain identifiers without qualification (with a package object)
|
// with the sole purpose of providing certain identifiers without qualification (with a package object)
|
||||||
lazy val sbtProj = (project in sbtPath).
|
lazy val sbtProj = (project in sbtPath).
|
||||||
dependsOn(mainProj, compileInterfaceProj, precompiled282, precompiled292, precompiled293, scriptedSbtProj % "test->test").
|
dependsOn(mainProj, compileInterfaceProj, scriptedSbtProj % "test->test").
|
||||||
settings(
|
settings(
|
||||||
baseSettings,
|
baseSettings,
|
||||||
name := "sbt",
|
name := "sbt",
|
||||||
|
|
@ -512,7 +497,7 @@ def otherRootSettings = Seq(
|
||||||
}
|
}
|
||||||
))
|
))
|
||||||
lazy val docProjects: ScopeFilter = ScopeFilter(
|
lazy val docProjects: ScopeFilter = ScopeFilter(
|
||||||
inAnyProject -- inProjects(sbtRoot, sbtProj, scriptedBaseProj, scriptedSbtProj, scriptedPluginProj, precompiled282, precompiled292, precompiled293, mavenResolverPluginProj),
|
inAnyProject -- inProjects(sbtRoot, sbtProj, scriptedBaseProj, scriptedSbtProj, scriptedPluginProj, mavenResolverPluginProj),
|
||||||
inConfigurations(Compile)
|
inConfigurations(Compile)
|
||||||
)
|
)
|
||||||
def fullDocSettings = Util.baseScalacOptions ++ Docs.settings ++ Sxr.settings ++ Seq(
|
def fullDocSettings = Util.baseScalacOptions ++ Docs.settings ++ Sxr.settings ++ Seq(
|
||||||
|
|
@ -539,36 +524,6 @@ def utilPath = file("util")
|
||||||
def compilePath = file("compile")
|
def compilePath = file("compile")
|
||||||
def mainPath = file("main")
|
def mainPath = file("main")
|
||||||
|
|
||||||
def precompiledSettings = Seq(
|
|
||||||
artifact in packageBin <<= (appConfiguration, scalaVersion) { (app, sv) =>
|
|
||||||
val launcher = app.provider.scalaProvider.launcher
|
|
||||||
val bincID = binID + "_" + ScalaInstance(sv, launcher).actualVersion
|
|
||||||
Artifact(binID) extra ("e:component" -> bincID)
|
|
||||||
},
|
|
||||||
target <<= (target, scalaVersion) { (base, sv) => base / ("precompiled_" + sv) },
|
|
||||||
scalacOptions := Nil,
|
|
||||||
ivyScala ~= { _.map(_.copy(checkExplicit = false, overrideScalaVersion = false)) },
|
|
||||||
exportedProducts in Compile := Nil,
|
|
||||||
libraryDependencies += scalaCompiler.value % "provided"
|
|
||||||
)
|
|
||||||
|
|
||||||
def precompiled(scalav: String): Project = Project(id = normalize("Precompiled " + scalav.replace('.', '_')), base = compilePath / "interface").
|
|
||||||
dependsOn(interfaceProj).
|
|
||||||
settings(
|
|
||||||
baseSettings,
|
|
||||||
precompiledSettings,
|
|
||||||
name := "Precompiled " + scalav.replace('.', '_'),
|
|
||||||
scalaHome := None,
|
|
||||||
scalaVersion <<= (scalaVersion in ThisBuild) { sbtScalaV =>
|
|
||||||
assert(sbtScalaV != scalav, "Precompiled compiler interface cannot have the same Scala version (" + scalav + ") as sbt.")
|
|
||||||
scalav
|
|
||||||
},
|
|
||||||
crossScalaVersions := Seq(scalav),
|
|
||||||
// we disable compiling and running tests in precompiled Projprojects of compiler interface
|
|
||||||
// so we do not need to worry about cross-versioning testing dependencies
|
|
||||||
sources in Test := Nil
|
|
||||||
)
|
|
||||||
|
|
||||||
lazy val safeUnitTests = taskKey[Unit]("Known working tests (for both 2.10 and 2.11)")
|
lazy val safeUnitTests = taskKey[Unit]("Known working tests (for both 2.10 and 2.11)")
|
||||||
lazy val safeProjects: ScopeFilter = ScopeFilter(
|
lazy val safeProjects: ScopeFilter = ScopeFilter(
|
||||||
inProjects(mainSettingsProj, mainProj, ivyProj, completeProj,
|
inProjects(mainSettingsProj, mainProj, ivyProj, completeProj,
|
||||||
|
|
@ -616,9 +571,6 @@ def customCommands: Seq[Setting[_]] = Seq(
|
||||||
},
|
},
|
||||||
commands += Command.command("release-sbt-local") { state =>
|
commands += Command.command("release-sbt-local") { state =>
|
||||||
"clean" ::
|
"clean" ::
|
||||||
"allPrecompiled/clean" ::
|
|
||||||
"allPrecompiled/compile" ::
|
|
||||||
"allPrecompiled/publishLocal" ::
|
|
||||||
"so compile" ::
|
"so compile" ::
|
||||||
"so publishLocal" ::
|
"so publishLocal" ::
|
||||||
"reload" ::
|
"reload" ::
|
||||||
|
|
@ -626,26 +578,17 @@ def customCommands: Seq[Setting[_]] = Seq(
|
||||||
},
|
},
|
||||||
/** There are several complications with sbt's build.
|
/** There are several complications with sbt's build.
|
||||||
* First is the fact that interface project is a Java-only project
|
* First is the fact that interface project is a Java-only project
|
||||||
* that uses source generator from datatype subproject in Scala 2.10.4,
|
* that uses source generator from datatype subproject in Scala 2.10.5.
|
||||||
* which is depended on by Scala 2.8.2, Scala 2.9.2, and Scala 2.9.3 precompiled project.
|
|
||||||
*
|
*
|
||||||
* Second is the fact that sbt project (currently using Scala 2.10.4) depends on
|
* Second is the fact that all subprojects are released with crossPaths
|
||||||
* the precompiled projects (that uses Scala 2.8.2 etc.)
|
* turned off for the sbt's Scala version 2.10.5, but some of them are also
|
||||||
*
|
|
||||||
* Finally, there's the fact that all subprojects are released with crossPaths
|
|
||||||
* turned off for the sbt's Scala version 2.10.4, but some of them are also
|
|
||||||
* cross published against 2.11.1 with crossPaths turned on.
|
* cross published against 2.11.1 with crossPaths turned on.
|
||||||
*
|
*
|
||||||
* Because of the way ++ (and its improved version wow) is implemented
|
* `so compile` handles 2.10.x/2.11.x cross building.
|
||||||
* precompiled compiler briges are handled outside of doge aggregation on root.
|
|
||||||
* `so compile` handles 2.10.x/2.11.x cross building.
|
|
||||||
*/
|
*/
|
||||||
commands += Command.command("release-sbt") { state =>
|
commands += Command.command("release-sbt") { state =>
|
||||||
// TODO - Any sort of validation
|
// TODO - Any sort of validation
|
||||||
"clean" ::
|
"clean" ::
|
||||||
"allPrecompiled/clean" ::
|
|
||||||
"allPrecompiled/compile" ::
|
|
||||||
"allPrecompiled/publishSigned" ::
|
|
||||||
"conscript-configs" ::
|
"conscript-configs" ::
|
||||||
"so compile" ::
|
"so compile" ::
|
||||||
"so publishSigned" ::
|
"so publishSigned" ::
|
||||||
|
|
@ -656,9 +599,6 @@ def customCommands: Seq[Setting[_]] = Seq(
|
||||||
commands += Command.command("release-nightly") { state =>
|
commands += Command.command("release-nightly") { state =>
|
||||||
"stamp-version" ::
|
"stamp-version" ::
|
||||||
"clean" ::
|
"clean" ::
|
||||||
"allPrecompiled/clean" ::
|
|
||||||
"allPrecompiled/compile" ::
|
|
||||||
"allPrecompiled/publish" ::
|
|
||||||
"compile" ::
|
"compile" ::
|
||||||
"publish" ::
|
"publish" ::
|
||||||
"bintrayRelease" ::
|
"bintrayRelease" ::
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ package sbt
|
||||||
package compiler
|
package compiler
|
||||||
|
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
import scala.util.Try
|
||||||
|
|
||||||
object ComponentCompiler {
|
object ComponentCompiler {
|
||||||
val xsbtiID = "xsbti"
|
val xsbtiID = "xsbti"
|
||||||
|
|
@ -14,6 +15,7 @@ object ComponentCompiler {
|
||||||
val compilerInterfaceSrcID = compilerInterfaceID + srcExtension
|
val compilerInterfaceSrcID = compilerInterfaceID + srcExtension
|
||||||
val javaVersion = System.getProperty("java.class.version")
|
val javaVersion = System.getProperty("java.class.version")
|
||||||
|
|
||||||
|
@deprecated("Use `interfaceProvider(ComponentManager, IvyConfiguration)`.", "0.13.10")
|
||||||
def interfaceProvider(manager: ComponentManager): CompilerInterfaceProvider = new CompilerInterfaceProvider {
|
def interfaceProvider(manager: ComponentManager): CompilerInterfaceProvider = new CompilerInterfaceProvider {
|
||||||
def apply(scalaInstance: xsbti.compile.ScalaInstance, log: Logger): File =
|
def apply(scalaInstance: xsbti.compile.ScalaInstance, log: Logger): File =
|
||||||
{
|
{
|
||||||
|
|
@ -23,12 +25,23 @@ object ComponentCompiler {
|
||||||
componentCompiler(compilerInterfaceID)
|
componentCompiler(compilerInterfaceID)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
def interfaceProvider(manager: ComponentManager, ivyConfiguration: IvyConfiguration): CompilerInterfaceProvider = new CompilerInterfaceProvider {
|
||||||
|
def apply(scalaInstance: xsbti.compile.ScalaInstance, log: Logger): File =
|
||||||
|
{
|
||||||
|
// this is the instance used to compile the interface component
|
||||||
|
val componentCompiler = new IvyComponentCompiler(new RawCompiler(scalaInstance, ClasspathOptions.auto, log), manager, ivyConfiguration, log)
|
||||||
|
log.debug("Getting " + compilerInterfaceID + " from component compiler for Scala " + scalaInstance.version)
|
||||||
|
componentCompiler(compilerInterfaceID)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* This class provides source components compiled with the provided RawCompiler.
|
* This class provides source components compiled with the provided RawCompiler.
|
||||||
* The compiled classes are cached using the provided component manager according
|
* The compiled classes are cached using the provided component manager according
|
||||||
* to the actualVersion field of the RawCompiler.
|
* to the actualVersion field of the RawCompiler.
|
||||||
*/
|
*/
|
||||||
|
@deprecated("Replaced by IvyComponentCompiler.", "0.13.10")
|
||||||
class ComponentCompiler(compiler: RawCompiler, manager: ComponentManager) {
|
class ComponentCompiler(compiler: RawCompiler, manager: ComponentManager) {
|
||||||
import ComponentCompiler._
|
import ComponentCompiler._
|
||||||
def apply(id: String): File =
|
def apply(id: String): File =
|
||||||
|
|
@ -64,4 +77,132 @@ class ComponentCompiler(compiler: RawCompiler, manager: ComponentManager) {
|
||||||
manager.define(binID, Seq(targetJar))
|
manager.define(binID, Seq(targetJar))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Component compiler which is able to find the most specific version available of
|
||||||
|
* the compiler interface sources using Ivy.
|
||||||
|
* The compiled classes are cached using the provided component manager according
|
||||||
|
* to the actualVersion field of the RawCompiler.
|
||||||
|
*/
|
||||||
|
private[compiler] class IvyComponentCompiler(compiler: RawCompiler, manager: ComponentManager, ivyConfiguration: IvyConfiguration, log: Logger) {
|
||||||
|
import ComponentCompiler._
|
||||||
|
|
||||||
|
private val sbtOrgTemp = JsonUtil.sbtOrgTemp
|
||||||
|
private val modulePrefixTemp = "temp-module-"
|
||||||
|
private val ivySbt: IvySbt = new IvySbt(ivyConfiguration)
|
||||||
|
private val sbtVersion = ComponentManager.version
|
||||||
|
|
||||||
|
def apply(id: String): File = {
|
||||||
|
val binID = binaryID(id)
|
||||||
|
manager.file(binID)(new IfMissing.Define(true, compileAndInstall(id, binID)))
|
||||||
|
}
|
||||||
|
|
||||||
|
private def binaryID(id: String): String = {
|
||||||
|
val base = id + binSeparator + compiler.scalaInstance.actualVersion
|
||||||
|
base + "__" + javaVersion
|
||||||
|
}
|
||||||
|
|
||||||
|
private def compileAndInstall(id: String, binID: String): Unit = {
|
||||||
|
def interfaceSources(moduleVersions: Vector[VersionNumber]): Iterable[File] =
|
||||||
|
moduleVersions match {
|
||||||
|
case Vector() =>
|
||||||
|
def getAndDefineDefaultSources() =
|
||||||
|
update(getModule(id))(_.getName endsWith "-sources.jar") map { sourcesJar =>
|
||||||
|
manager.define(id, sourcesJar)
|
||||||
|
sourcesJar
|
||||||
|
} getOrElse (throw new InvalidComponent(s"Couldn't retrieve default sources: module '$id'"))
|
||||||
|
|
||||||
|
log.debug(s"Fetching default sources: module '$id'")
|
||||||
|
manager.files(id)(new IfMissing.Fallback(getAndDefineDefaultSources()))
|
||||||
|
|
||||||
|
case version +: rest =>
|
||||||
|
val moduleName = s"${id}_$version"
|
||||||
|
def getAndDefineVersionSpecificSources() =
|
||||||
|
update(getModule(moduleName))(_.getName endsWith "-sources.jar") map { sourcesJar =>
|
||||||
|
manager.define(moduleName, sourcesJar)
|
||||||
|
sourcesJar
|
||||||
|
} getOrElse interfaceSources(rest)
|
||||||
|
|
||||||
|
log.debug(s"Fetching version-specific sources: module '$moduleName'")
|
||||||
|
manager.files(moduleName)(new IfMissing.Fallback(getAndDefineVersionSpecificSources()))
|
||||||
|
}
|
||||||
|
IO.withTemporaryDirectory { binaryDirectory =>
|
||||||
|
|
||||||
|
val targetJar = new File(binaryDirectory, s"$binID.jar")
|
||||||
|
val xsbtiJars = manager.files(xsbtiID)(IfMissing.Fail)
|
||||||
|
|
||||||
|
val sourceModuleVersions = VersionNumber(compiler.scalaInstance.actualVersion).cascadingVersions
|
||||||
|
AnalyzingCompiler.compileSources(interfaceSources(sourceModuleVersions), targetJar, xsbtiJars, id, compiler, log)
|
||||||
|
|
||||||
|
manager.define(binID, Seq(targetJar))
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns a dummy module that depends on "org.scala-sbt" % `id` % `sbtVersion`.
|
||||||
|
* Note: Sbt's implementation of Ivy requires us to do this, because only the dependencies
|
||||||
|
* of the specified module will be downloaded.
|
||||||
|
*/
|
||||||
|
private def getModule(id: String): ivySbt.Module = {
|
||||||
|
val sha1 = Hash.toHex(Hash(id))
|
||||||
|
val dummyID = ModuleID(sbtOrgTemp, modulePrefixTemp + sha1, sbtVersion, Some("component"))
|
||||||
|
val moduleID = ModuleID(xsbti.ArtifactInfo.SbtOrganization, id, sbtVersion, Some("component")).sources()
|
||||||
|
getModule(dummyID, Seq(moduleID))
|
||||||
|
}
|
||||||
|
|
||||||
|
private def getModule(moduleID: ModuleID, deps: Seq[ModuleID], uo: UpdateOptions = UpdateOptions()): ivySbt.Module = {
|
||||||
|
val moduleSetting = InlineConfiguration(
|
||||||
|
module = moduleID,
|
||||||
|
moduleInfo = ModuleInfo(moduleID.name),
|
||||||
|
dependencies = deps,
|
||||||
|
configurations = Seq(Configurations.Component),
|
||||||
|
ivyScala = None)
|
||||||
|
|
||||||
|
new ivySbt.Module(moduleSetting)
|
||||||
|
}
|
||||||
|
|
||||||
|
private def dependenciesNames(module: ivySbt.Module): String = module.moduleSettings match {
|
||||||
|
// `module` is a dummy module, we will only fetch its dependencies.
|
||||||
|
case ic: InlineConfiguration =>
|
||||||
|
ic.dependencies map {
|
||||||
|
case mID: ModuleID =>
|
||||||
|
import mID._
|
||||||
|
s"$organization % $name % $revision"
|
||||||
|
} mkString ", "
|
||||||
|
case _ =>
|
||||||
|
s"unknown"
|
||||||
|
}
|
||||||
|
|
||||||
|
private def update(module: ivySbt.Module)(predicate: File => Boolean): Option[Seq[File]] = {
|
||||||
|
|
||||||
|
val retrieveDirectory = new File(ivyConfiguration.baseDirectory, "component")
|
||||||
|
val retrieveConfiguration = new RetrieveConfiguration(retrieveDirectory, Resolver.defaultRetrievePattern, false)
|
||||||
|
val updateConfiguration = new UpdateConfiguration(Some(retrieveConfiguration), true, UpdateLogging.DownloadOnly)
|
||||||
|
|
||||||
|
log.info(s"Attempting to fetch ${dependenciesNames(module)}. This operation may fail.")
|
||||||
|
IvyActions.updateEither(module, updateConfiguration, UnresolvedWarningConfiguration(), LogicalClock.unknown, None, log) match {
|
||||||
|
case Left(unresolvedWarning) =>
|
||||||
|
log.debug("Couldn't retrieve module ${dependenciesNames(module)}.")
|
||||||
|
None
|
||||||
|
|
||||||
|
case Right(updateReport) =>
|
||||||
|
val allFiles =
|
||||||
|
for {
|
||||||
|
conf <- updateReport.configurations
|
||||||
|
m <- conf.modules
|
||||||
|
(_, f) <- m.artifacts
|
||||||
|
} yield f
|
||||||
|
|
||||||
|
log.debug(s"Files retrieved for ${dependenciesNames(module)}:")
|
||||||
|
log.debug(allFiles mkString ", ")
|
||||||
|
|
||||||
|
allFiles filter predicate match {
|
||||||
|
case Seq() => None
|
||||||
|
case files => Some(files)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -39,6 +39,8 @@ class ComponentManager(globalLock: xsbti.GlobalLock, provider: xsbti.ComponentPr
|
||||||
d()
|
d()
|
||||||
if (d.cache) cache(id)
|
if (d.cache) cache(id)
|
||||||
getOrElse(notFound)
|
getOrElse(notFound)
|
||||||
|
case f: IfMissing.Fallback =>
|
||||||
|
f()
|
||||||
}
|
}
|
||||||
|
|
||||||
lockLocalCache { getOrElse(fromGlobal) }
|
lockLocalCache { getOrElse(fromGlobal) }
|
||||||
|
|
@ -73,6 +75,7 @@ sealed trait IfMissing extends NotNull
|
||||||
object IfMissing {
|
object IfMissing {
|
||||||
object Fail extends IfMissing
|
object Fail extends IfMissing
|
||||||
final class Define(val cache: Boolean, define: => Unit) extends IfMissing { def apply() = define }
|
final class Define(val cache: Boolean, define: => Unit) extends IfMissing { def apply() = define }
|
||||||
|
final class Fallback(f: => Iterable[File]) extends IfMissing { def apply() = f }
|
||||||
}
|
}
|
||||||
object ComponentManager {
|
object ComponentManager {
|
||||||
lazy val (version, timestamp) =
|
lazy val (version, timestamp) =
|
||||||
|
|
@ -86,4 +89,4 @@ object ComponentManager {
|
||||||
|
|
||||||
import java.net.URL
|
import java.net.URL
|
||||||
private def versionResource: URL = getClass.getResource("/xsbt.version.properties")
|
private def versionResource: URL = getClass.getResource("/xsbt.version.properties")
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,7 @@ object Configurations {
|
||||||
|
|
||||||
lazy val ScalaTool = config("scala-tool") hide
|
lazy val ScalaTool = config("scala-tool") hide
|
||||||
lazy val CompilerPlugin = config("plugin") hide
|
lazy val CompilerPlugin = config("plugin") hide
|
||||||
|
lazy val Component = config("component") hide
|
||||||
|
|
||||||
private[sbt] val DefaultMavenConfiguration = defaultConfiguration(true)
|
private[sbt] val DefaultMavenConfiguration = defaultConfiguration(true)
|
||||||
private[sbt] val DefaultIvyConfiguration = defaultConfiguration(false)
|
private[sbt] val DefaultIvyConfiguration = defaultConfiguration(false)
|
||||||
|
|
|
||||||
|
|
@ -13,6 +13,11 @@ final class VersionNumber private[sbt] (
|
||||||
else Some(numbers(idx))
|
else Some(numbers(idx))
|
||||||
def size: Int = numbers.size
|
def size: Int = numbers.size
|
||||||
|
|
||||||
|
/** The vector of version numbers from more to less specific from this version number. */
|
||||||
|
lazy val cascadingVersions: Vector[VersionNumber] =
|
||||||
|
(Vector(this) ++
|
||||||
|
(numbers.inits filter (_.length >= 2) map (VersionNumber(_, Nil, Nil)))).distinct
|
||||||
|
|
||||||
private[this] val versionStr: String =
|
private[this] val versionStr: String =
|
||||||
numbers.mkString(".") +
|
numbers.mkString(".") +
|
||||||
(tags match {
|
(tags match {
|
||||||
|
|
|
||||||
|
|
@ -10,15 +10,18 @@ class VersionNumberSpec extends Specification {
|
||||||
1 should
|
1 should
|
||||||
${beParsedAs("1", Seq(1), Seq(), Seq())}
|
${beParsedAs("1", Seq(1), Seq(), Seq())}
|
||||||
${breakDownTo("1", Some(1))}
|
${breakDownTo("1", Some(1))}
|
||||||
|
${generateCorrectCascadingNumbers("1", Seq("1"))}
|
||||||
|
|
||||||
1.0 should
|
1.0 should
|
||||||
${beParsedAs("1.0", Seq(1, 0), Seq(), Seq())}
|
${beParsedAs("1.0", Seq(1, 0), Seq(), Seq())}
|
||||||
${breakDownTo("1.0", Some(1), Some(0))}
|
${breakDownTo("1.0", Some(1), Some(0))}
|
||||||
|
${generateCorrectCascadingNumbers("1.0", Seq("1.0"))}
|
||||||
|
|
||||||
1.0.0 should
|
1.0.0 should
|
||||||
${beParsedAs("1.0.0", Seq(1, 0, 0), Seq(), Seq())}
|
${beParsedAs("1.0.0", Seq(1, 0, 0), Seq(), Seq())}
|
||||||
${breakDownTo("1.0.0", Some(1), Some(0), Some(0))}
|
${breakDownTo("1.0.0", Some(1), Some(0), Some(0))}
|
||||||
|
${generateCorrectCascadingNumbers("1.0.0", Seq("1.0.0", "1.0"))}
|
||||||
|
|
||||||
${beSemVerCompatWith("1.0.0", "1.0.1")}
|
${beSemVerCompatWith("1.0.0", "1.0.1")}
|
||||||
${beSemVerCompatWith("1.0.0", "1.1.1")}
|
${beSemVerCompatWith("1.0.0", "1.1.1")}
|
||||||
${notBeSemVerCompatWith("1.0.0", "2.0.0")}
|
${notBeSemVerCompatWith("1.0.0", "2.0.0")}
|
||||||
|
|
@ -32,10 +35,12 @@ class VersionNumberSpec extends Specification {
|
||||||
1.0.0.0 should
|
1.0.0.0 should
|
||||||
${beParsedAs("1.0.0.0", Seq(1, 0, 0, 0), Seq(), Seq())}
|
${beParsedAs("1.0.0.0", Seq(1, 0, 0, 0), Seq(), Seq())}
|
||||||
${breakDownTo("1.0.0.0", Some(1), Some(0), Some(0), Some(0))}
|
${breakDownTo("1.0.0.0", Some(1), Some(0), Some(0), Some(0))}
|
||||||
|
${generateCorrectCascadingNumbers("1.0.0.0", Seq("1.0.0.0", "1.0.0", "1.0"))}
|
||||||
|
|
||||||
0.12.0 should
|
0.12.0 should
|
||||||
${beParsedAs("0.12.0", Seq(0, 12, 0), Seq(), Seq())}
|
${beParsedAs("0.12.0", Seq(0, 12, 0), Seq(), Seq())}
|
||||||
${breakDownTo("0.12.0", Some(0), Some(12), Some(0))}
|
${breakDownTo("0.12.0", Some(0), Some(12), Some(0))}
|
||||||
|
${generateCorrectCascadingNumbers("0.12.0", Seq("0.12.0", "0.12"))}
|
||||||
|
|
||||||
${notBeSemVerCompatWith("0.12.0", "0.12.0-RC1")}
|
${notBeSemVerCompatWith("0.12.0", "0.12.0-RC1")}
|
||||||
${notBeSemVerCompatWith("0.12.0", "0.12.1")}
|
${notBeSemVerCompatWith("0.12.0", "0.12.1")}
|
||||||
|
|
@ -47,6 +52,7 @@ class VersionNumberSpec extends Specification {
|
||||||
|
|
||||||
0.1.0-SNAPSHOT should
|
0.1.0-SNAPSHOT should
|
||||||
${beParsedAs("0.1.0-SNAPSHOT", Seq(0, 1, 0), Seq("SNAPSHOT"), Seq())}
|
${beParsedAs("0.1.0-SNAPSHOT", Seq(0, 1, 0), Seq("SNAPSHOT"), Seq())}
|
||||||
|
${generateCorrectCascadingNumbers("0.1.0-SNAPSHOT", Seq("0.1.0-SNAPSHOT", "0.1.0", "0.1"))}
|
||||||
|
|
||||||
${beSemVerCompatWith("0.1.0-SNAPSHOT", "0.1.0-SNAPSHOT")}
|
${beSemVerCompatWith("0.1.0-SNAPSHOT", "0.1.0-SNAPSHOT")}
|
||||||
${notBeSemVerCompatWith("0.1.0-SNAPSHOT", "0.1.0")}
|
${notBeSemVerCompatWith("0.1.0-SNAPSHOT", "0.1.0")}
|
||||||
|
|
@ -58,15 +64,20 @@ class VersionNumberSpec extends Specification {
|
||||||
|
|
||||||
0.1.0-M1 should
|
0.1.0-M1 should
|
||||||
${beParsedAs("0.1.0-M1", Seq(0, 1, 0), Seq("M1"), Seq())}
|
${beParsedAs("0.1.0-M1", Seq(0, 1, 0), Seq("M1"), Seq())}
|
||||||
|
${generateCorrectCascadingNumbers("0.1.0-M1", Seq("0.1.0-M1", "0.1.0", "0.1"))}
|
||||||
|
|
||||||
0.1.0-RC1 should
|
0.1.0-RC1 should
|
||||||
${beParsedAs("0.1.0-RC1", Seq(0, 1, 0), Seq("RC1"), Seq())}
|
${beParsedAs("0.1.0-RC1", Seq(0, 1, 0), Seq("RC1"), Seq())}
|
||||||
|
${generateCorrectCascadingNumbers("0.1.0-RC1", Seq("0.1.0-RC1", "0.1.0", "0.1"))}
|
||||||
|
|
||||||
0.1.0-MSERVER-1 should
|
0.1.0-MSERVER-1 should
|
||||||
${beParsedAs("0.1.0-MSERVER-1", Seq(0, 1, 0), Seq("MSERVER", "1"), Seq())}
|
${beParsedAs("0.1.0-MSERVER-1", Seq(0, 1, 0), Seq("MSERVER", "1"), Seq())}
|
||||||
|
${generateCorrectCascadingNumbers("0.1.0-MSERVER-1", Seq("0.1.0-MSERVER-1", "0.1.0", "0.1"))}
|
||||||
|
|
||||||
|
|
||||||
2.10.4-20140115-000117-b3a-sources should
|
2.10.4-20140115-000117-b3a-sources should
|
||||||
${beParsedAs("2.10.4-20140115-000117-b3a-sources", Seq(2, 10, 4), Seq("20140115", "000117", "b3a", "sources"), Seq())}
|
${beParsedAs("2.10.4-20140115-000117-b3a-sources", Seq(2, 10, 4), Seq("20140115", "000117", "b3a", "sources"), Seq())}
|
||||||
|
${generateCorrectCascadingNumbers("2.10.4-20140115-000117-b3a-sources", Seq("2.10.4-20140115-000117-b3a-sources", "2.10.4", "2.10"))}
|
||||||
|
|
||||||
${beSemVerCompatWith("2.10.4-20140115-000117-b3a-sources", "2.0.0")}
|
${beSemVerCompatWith("2.10.4-20140115-000117-b3a-sources", "2.0.0")}
|
||||||
|
|
||||||
|
|
@ -74,12 +85,15 @@ class VersionNumberSpec extends Specification {
|
||||||
|
|
||||||
20140115000117-b3a-sources should
|
20140115000117-b3a-sources should
|
||||||
${beParsedAs("20140115000117-b3a-sources", Seq(20140115000117L), Seq("b3a", "sources"), Seq())}
|
${beParsedAs("20140115000117-b3a-sources", Seq(20140115000117L), Seq("b3a", "sources"), Seq())}
|
||||||
|
${generateCorrectCascadingNumbers("20140115000117-b3a-sources", Seq("20140115000117-b3a-sources"))}
|
||||||
|
|
||||||
1.0.0-alpha+001+002 should
|
1.0.0-alpha+001+002 should
|
||||||
${beParsedAs("1.0.0-alpha+001+002", Seq(1, 0, 0), Seq("alpha"), Seq("+001", "+002"))}
|
${beParsedAs("1.0.0-alpha+001+002", Seq(1, 0, 0), Seq("alpha"), Seq("+001", "+002"))}
|
||||||
|
${generateCorrectCascadingNumbers("1.0.0-alpha+001+002", Seq("1.0.0-alpha+001+002", "1.0.0", "1.0"))}
|
||||||
|
|
||||||
non.space.!?string should
|
non.space.!?string should
|
||||||
${beParsedAs("non.space.!?string", Seq(), Seq(), Seq("non.space.!?string"))}
|
${beParsedAs("non.space.!?string", Seq(), Seq(), Seq("non.space.!?string"))}
|
||||||
|
${generateCorrectCascadingNumbers("non.space.!?string", Seq("non.space.!?string"))}
|
||||||
|
|
||||||
space !?string should
|
space !?string should
|
||||||
${beParsedAsError("space !?string")}
|
${beParsedAsError("space !?string")}
|
||||||
|
|
@ -119,4 +133,8 @@ class VersionNumberSpec extends Specification {
|
||||||
VersionNumber.SecondSegment.isCompatible(VersionNumber(v1), VersionNumber(v2)) must_== true
|
VersionNumber.SecondSegment.isCompatible(VersionNumber(v1), VersionNumber(v2)) must_== true
|
||||||
def notBeSecSegCompatWith(v1: String, v2: String) =
|
def notBeSecSegCompatWith(v1: String, v2: String) =
|
||||||
VersionNumber.SecondSegment.isCompatible(VersionNumber(v1), VersionNumber(v2)) must_== false
|
VersionNumber.SecondSegment.isCompatible(VersionNumber(v1), VersionNumber(v2)) must_== false
|
||||||
|
def generateCorrectCascadingNumbers(s: String, ns: Seq[String]) = {
|
||||||
|
val versionNumbers = ns.toVector map VersionNumber.apply
|
||||||
|
VersionNumber(s).cascadingVersions must_== versionNumbers
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -54,6 +54,7 @@ object Compiler {
|
||||||
def compilers(instance: ScalaInstance, cpOptions: ClasspathOptions)(implicit app: AppConfiguration, log: Logger): Compilers =
|
def compilers(instance: ScalaInstance, cpOptions: ClasspathOptions)(implicit app: AppConfiguration, log: Logger): Compilers =
|
||||||
compilers(instance, cpOptions, None)
|
compilers(instance, cpOptions, None)
|
||||||
|
|
||||||
|
@deprecated("Use `compilers(ScalaInstance, ClasspathOptions, Option[File], IvyConfiguration)`.", "0.13.10")
|
||||||
def compilers(instance: ScalaInstance, cpOptions: ClasspathOptions, javaHome: Option[File])(implicit app: AppConfiguration, log: Logger): Compilers =
|
def compilers(instance: ScalaInstance, cpOptions: ClasspathOptions, javaHome: Option[File])(implicit app: AppConfiguration, log: Logger): Compilers =
|
||||||
{
|
{
|
||||||
val javac =
|
val javac =
|
||||||
|
|
@ -68,6 +69,21 @@ object Compiler {
|
||||||
}
|
}
|
||||||
compilers(instance, cpOptions, CheaterJavaTool(javac2, javac))
|
compilers(instance, cpOptions, CheaterJavaTool(javac2, javac))
|
||||||
}
|
}
|
||||||
|
def compilers(instance: ScalaInstance, cpOptions: ClasspathOptions, javaHome: Option[File], ivyConfiguration: IvyConfiguration)(implicit app: AppConfiguration, log: Logger): Compilers =
|
||||||
|
{
|
||||||
|
val javac =
|
||||||
|
AggressiveCompile.directOrFork(instance, cpOptions, javaHome)
|
||||||
|
val javac2 =
|
||||||
|
JavaTools.directOrFork(instance, cpOptions, javaHome)
|
||||||
|
// Hackery to enable both the new and deprecated APIs to coexist peacefully.
|
||||||
|
case class CheaterJavaTool(newJavac: IncrementalCompilerJavaTools, delegate: JavaTool) extends JavaTool with JavaToolWithNewInterface {
|
||||||
|
def compile(contract: JavacContract, sources: Seq[File], classpath: Seq[File], outputDirectory: File, options: Seq[String])(implicit log: Logger): Unit =
|
||||||
|
javac.compile(contract, sources, classpath, outputDirectory, options)(log)
|
||||||
|
def onArgs(f: Seq[String] => Unit): JavaTool = CheaterJavaTool(newJavac, delegate.onArgs(f))
|
||||||
|
}
|
||||||
|
val scalac = scalaCompiler(instance, cpOptions, ivyConfiguration)
|
||||||
|
new Compilers(scalac, CheaterJavaTool(javac2, javac))
|
||||||
|
}
|
||||||
@deprecated("Deprecated in favor of new sbt.compiler.javac package.", "0.13.8")
|
@deprecated("Deprecated in favor of new sbt.compiler.javac package.", "0.13.8")
|
||||||
def compilers(instance: ScalaInstance, cpOptions: ClasspathOptions, javac: sbt.compiler.JavaCompiler.Fork)(implicit app: AppConfiguration, log: Logger): Compilers =
|
def compilers(instance: ScalaInstance, cpOptions: ClasspathOptions, javac: sbt.compiler.JavaCompiler.Fork)(implicit app: AppConfiguration, log: Logger): Compilers =
|
||||||
{
|
{
|
||||||
|
|
@ -80,6 +96,7 @@ object Compiler {
|
||||||
val scalac = scalaCompiler(instance, cpOptions)
|
val scalac = scalaCompiler(instance, cpOptions)
|
||||||
new Compilers(scalac, javac)
|
new Compilers(scalac, javac)
|
||||||
}
|
}
|
||||||
|
@deprecated("Use `scalaCompiler(ScalaInstance, ClasspathOptions, IvyConfiguration)`.", "0.13.10")
|
||||||
def scalaCompiler(instance: ScalaInstance, cpOptions: ClasspathOptions)(implicit app: AppConfiguration, log: Logger): AnalyzingCompiler =
|
def scalaCompiler(instance: ScalaInstance, cpOptions: ClasspathOptions)(implicit app: AppConfiguration, log: Logger): AnalyzingCompiler =
|
||||||
{
|
{
|
||||||
val launcher = app.provider.scalaProvider.launcher
|
val launcher = app.provider.scalaProvider.launcher
|
||||||
|
|
@ -87,6 +104,13 @@ object Compiler {
|
||||||
val provider = ComponentCompiler.interfaceProvider(componentManager)
|
val provider = ComponentCompiler.interfaceProvider(componentManager)
|
||||||
new AnalyzingCompiler(instance, provider, cpOptions)
|
new AnalyzingCompiler(instance, provider, cpOptions)
|
||||||
}
|
}
|
||||||
|
def scalaCompiler(instance: ScalaInstance, cpOptions: ClasspathOptions, ivyConfiguration: IvyConfiguration)(implicit app: AppConfiguration, log: Logger): AnalyzingCompiler =
|
||||||
|
{
|
||||||
|
val launcher = app.provider.scalaProvider.launcher
|
||||||
|
val componentManager = new ComponentManager(launcher.globalLock, app.provider.components, Option(launcher.ivyHome), log)
|
||||||
|
val provider = ComponentCompiler.interfaceProvider(componentManager, ivyConfiguration)
|
||||||
|
new AnalyzingCompiler(instance, provider, cpOptions)
|
||||||
|
}
|
||||||
|
|
||||||
@deprecated("Use the `compile` method instead.", "0.13.8")
|
@deprecated("Use the `compile` method instead.", "0.13.8")
|
||||||
def apply(in: Inputs, log: Logger): Analysis = {
|
def apply(in: Inputs, log: Logger): Analysis = {
|
||||||
|
|
|
||||||
|
|
@ -261,7 +261,7 @@ object Defaults extends BuildCommon {
|
||||||
if (plugin) scalaBase / ("sbt-" + sbtv) else scalaBase
|
if (plugin) scalaBase / ("sbt-" + sbtv) else scalaBase
|
||||||
}
|
}
|
||||||
|
|
||||||
def compilersSetting = compilers := Compiler.compilers(scalaInstance.value, classpathOptions.value, javaHome.value)(appConfiguration.value, streams.value.log)
|
def compilersSetting = compilers := Compiler.compilers(scalaInstance.value, classpathOptions.value, javaHome.value, ivyConfiguration.value)(appConfiguration.value, streams.value.log)
|
||||||
|
|
||||||
lazy val configTasks = docTaskSettings(doc) ++ inTask(compile)(compileInputsSettings) ++ configGlobal ++ compileAnalysisSettings ++ Seq(
|
lazy val configTasks = docTaskSettings(doc) ++ inTask(compile)(compileInputsSettings) ++ configGlobal ++ compileAnalysisSettings ++ Seq(
|
||||||
compile <<= compileTask,
|
compile <<= compileTask,
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
|
||||||
|
[@Duhemm]: http://github.com/Duhemm
|
||||||
|
[2106]: https://github.com/sbt/sbt/pull/2106
|
||||||
|
|
||||||
|
### Fixes with compatibility implications
|
||||||
|
|
||||||
|
### Improvements
|
||||||
|
|
||||||
|
- Fetch the most specific version of the compiler-interface sources available using Ivy [#2106][2106] by [@Duhemm][@Duhemm]
|
||||||
|
|
||||||
|
### Bug fixes
|
||||||
|
|
@ -4,7 +4,8 @@ def commonSettings: Seq[Def.Setting[_]] =
|
||||||
dependencyCacheDirectory := (baseDirectory in LocalRootProject).value / "dependency",
|
dependencyCacheDirectory := (baseDirectory in LocalRootProject).value / "dependency",
|
||||||
scalaVersion := "2.10.4",
|
scalaVersion := "2.10.4",
|
||||||
organization in ThisBuild := "org.example",
|
organization in ThisBuild := "org.example",
|
||||||
version in ThisBuild := "1.0-SNAPSHOT"
|
version in ThisBuild := "1.0-SNAPSHOT",
|
||||||
|
resolvers += Resolver.file("old-local", file(sys.props("user.home") + "/.ivy2/local"))(Resolver.ivyStylePatterns)
|
||||||
)
|
)
|
||||||
|
|
||||||
lazy val main = project.
|
lazy val main = project.
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue