mirror of https://github.com/sbt/sbt.git
Further Scala handling refinements. fixes #690.
* No longer override the Scala version to force it to be scalaVersion. Custom configurations might use an independent version. * Only substitute the jars from scalaHome when the major.minor versions line up for the substituted artifact * Allow the Scala version to use for dependency resolution to be specified when using ++ to change Scala home: ++ version=/path/to/scala/home
This commit is contained in:
parent
b3cbdf2bf2
commit
ada663106d
|
|
@ -283,6 +283,16 @@ s"""$SwitchCommand <scala-version> [<command>]
|
|||
Sets the `scalaVersion` of all projects to <scala-version> and reloads the build.
|
||||
If <command> is provided, it is then executed.
|
||||
|
||||
$SwitchCommand [<scala-version>=]<scala-home> [<command>]
|
||||
Uses the Scala installation at <scala-home> by configuring the scalaHome setting for
|
||||
all projects.
|
||||
|
||||
If <scala-version> is specified, it is used as the value of the scalaVersion setting.
|
||||
This is important when using managed dependencies. This version will determine the
|
||||
cross-version used as well as transitive dependencies.
|
||||
|
||||
If <command> is provided, it is then executed.
|
||||
|
||||
See also `help $CrossCommand`
|
||||
"""
|
||||
}
|
||||
|
|
|
|||
|
|
@ -32,24 +32,33 @@ object Cross
|
|||
}
|
||||
def spacedFirst(name: String) = opOrIDSpaced(name) ~ any.+
|
||||
|
||||
lazy val switchVersion = Command.arb(requireSession(switchParser), switchHelp) { case (state, (version, command)) =>
|
||||
lazy val switchVersion = Command.arb(requireSession(switchParser), switchHelp) { case (state, (arg, command)) =>
|
||||
val x = Project.extract(state)
|
||||
import x._
|
||||
val home = IO.resolve(x.currentProject.base, new File(version))
|
||||
|
||||
val (resolveVersion, homePath) = arg.split("=") match {
|
||||
case Array(v, h) => (v, h)
|
||||
case _ => ("", arg)
|
||||
}
|
||||
val home = IO.resolve(x.currentProject.base, new File(homePath))
|
||||
val (add, exclude) =
|
||||
if(home.exists) {
|
||||
val instance = ScalaInstance(home)(state.classLoaderCache.apply _)
|
||||
state.log.info("Setting Scala home to " + home + " with actual version " + instance.actualVersion)
|
||||
val version = if(resolveVersion.isEmpty) instance.actualVersion else resolveVersion
|
||||
state.log.info("\tand using " + version + " for resolving dependencies.")
|
||||
val settings = Seq(
|
||||
scalaVersion in GlobalScope :== instance.actualVersion,
|
||||
scalaVersion in GlobalScope :== version,
|
||||
scalaHome in GlobalScope :== Some(home),
|
||||
scalaInstance in GlobalScope :== instance
|
||||
)
|
||||
(settings, excludeKeys(Set(scalaVersion.key, scalaHome.key, scalaInstance.key)))
|
||||
} else if(!resolveVersion.isEmpty) {
|
||||
error("Scala home directory did not exist: " + home)
|
||||
} else {
|
||||
state.log.info("Setting version to " + version)
|
||||
state.log.info("Setting version to " + arg)
|
||||
val settings = Seq(
|
||||
scalaVersion in GlobalScope :== version,
|
||||
scalaVersion in GlobalScope :== arg,
|
||||
scalaHome in GlobalScope :== None
|
||||
)
|
||||
(settings, excludeKeys(Set(scalaVersion.key, scalaHome.key)))
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ package sbt
|
|||
import Def.{Initialize, ScopedKey, Setting, SettingsDefinition}
|
||||
import Artifact.{DocClassifier, SourceClassifier}
|
||||
import Configurations.{Compile, CompilerPlugin, IntegrationTest, names, Provided, Runtime, Test}
|
||||
import CrossVersion.{binarySbtVersion, binaryScalaVersion}
|
||||
import CrossVersion.{binarySbtVersion, binaryScalaVersion, partialVersion}
|
||||
import complete._
|
||||
import std.TaskExtra._
|
||||
import inc.{FileValueCache, Locate}
|
||||
|
|
@ -919,7 +919,7 @@ object Classpaths
|
|||
ivyXML in GlobalScope :== NodeSeq.Empty,
|
||||
ivyValidate in GlobalScope :== false,
|
||||
ivyScala <<= ivyScala or (scalaHome, scalaVersion in update, scalaBinaryVersion in update, scalaOrganization) { (sh,fv,bv,so) =>
|
||||
Some(new IvyScala(fv, bv, Nil, filterImplicit = false, checkExplicit = true, overrideScalaVersion = sh.isEmpty, scalaOrganization = so))
|
||||
Some(new IvyScala(fv, bv, Nil, filterImplicit = false, checkExplicit = true, overrideScalaVersion = false, scalaOrganization = so))
|
||||
},
|
||||
moduleConfigurations in GlobalScope :== Nil,
|
||||
publishTo in GlobalScope :== None,
|
||||
|
|
@ -1046,15 +1046,23 @@ object Classpaths
|
|||
val depsUpdated = transitiveUpdate.value.exists(!_.stats.cached)
|
||||
val isRoot = executionRoots.value contains resolvedScoped.value
|
||||
val s = streams.value
|
||||
val subScalaJars: Seq[File] = Defaults.unmanagedScalaInstanceOnly.value match {
|
||||
case Some(si) => si.jars
|
||||
case None =>
|
||||
val scalaProvider = appConfiguration.value.provider.scalaProvider
|
||||
// substitute the Scala jars from the provider so that when the provider's loader is used,
|
||||
// the jars on the classpath match the jars used by the loader
|
||||
if(scalaProvider.version == scalaVersion.value) scalaProvider.jars else Nil
|
||||
val scalaProvider = appConfiguration.value.provider.scalaProvider
|
||||
|
||||
// Only substitute unmanaged jars for managed jars when the major.minor parts of the versions the same for:
|
||||
// the resolved Scala version and the scalaHome version: compatible (weakly- no qualifier checked)
|
||||
// the resolved Scala version and the declared scalaVersion: assume the user intended scalaHome to override anything with scalaVersion
|
||||
def subUnmanaged(subVersion: String, jars: Seq[File]) = (sv: String) =>
|
||||
(partialVersion(sv), partialVersion(subVersion), partialVersion(scalaVersion.value)) match {
|
||||
case (Some(res), Some(sh), _) if res == sh => jars
|
||||
case (Some(res), _, Some(decl)) if res == decl => jars
|
||||
case _ => Nil
|
||||
}
|
||||
val subScalaJars: String => Seq[File] = Defaults.unmanagedScalaInstanceOnly.value match {
|
||||
case Some(si) => subUnmanaged(si.version, si.jars)
|
||||
case None => sv => if(scalaProvider.version == sv) scalaProvider.jars else Nil
|
||||
}
|
||||
val transform: UpdateReport => UpdateReport = if(subScalaJars.isEmpty) idFun else r => substituteScalaFiles(subScalaJars, scalaOrganization.value, r)
|
||||
val transform: UpdateReport => UpdateReport = r => substituteScalaFiles(scalaOrganization.value, r)(subScalaJars)
|
||||
|
||||
val show = Reference.display(thisProjectRef.value)
|
||||
cachedUpdate(s.cacheDirectory, show, ivyModule.value, updateConfiguration.value, transform, skip = (skip in update).value, force = isRoot, depsUpdated = depsUpdated, log = s.log)
|
||||
}
|
||||
|
|
@ -1322,16 +1330,16 @@ object Classpaths
|
|||
def substituteScalaFiles(scalaInstance: ScalaInstance, report: UpdateReport): UpdateReport =
|
||||
substituteScalaFiles(scalaInstance, ScalaArtifacts.Organization, report)
|
||||
|
||||
@deprecated("Directly provide the jar files.", "0.13.0")
|
||||
@deprecated("Directly provide the jar files per Scala version.", "0.13.0")
|
||||
def substituteScalaFiles(scalaInstance: ScalaInstance, scalaOrg: String, report: UpdateReport): UpdateReport =
|
||||
substituteScalaFiles(scalaInstance.jars, scalaOrg, report)
|
||||
substituteScalaFiles(scalaOrg, report)(const(scalaInstance.jars))
|
||||
|
||||
def substituteScalaFiles(scalaJars: Seq[File], scalaOrg: String, report: UpdateReport): UpdateReport =
|
||||
def substituteScalaFiles(scalaOrg: String, report: UpdateReport)(scalaJars: String => Seq[File]): UpdateReport =
|
||||
report.substitute { (configuration, module, arts) =>
|
||||
import ScalaArtifacts._
|
||||
if(module.organization == scalaOrg) {
|
||||
val jarName = module.name + ".jar"
|
||||
val replaceWith = scalaJars.filter(_.getName == jarName).map(f => (Artifact(f.getName.stripSuffix(".jar")), f))
|
||||
val replaceWith = scalaJars(module.revision).filter(_.getName == jarName).map(f => (Artifact(f.getName.stripSuffix(".jar")), f))
|
||||
if(replaceWith.isEmpty) arts else replaceWith
|
||||
} else
|
||||
arts
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ Features
|
|||
- Support defining Projects in .sbt files: vals of type Project are added to the Build. Details below.
|
||||
- New syntax for settings, tasks, and input tasks. Details below.
|
||||
- Automatically link to external API scaladocs of dependencies by setting ``autoAPIMappings := true``. This requires at least Scala 2.10.1 and for dependencies to define ``apiURL`` for their scaladoc location. Mappings may be manually added to the ``apiMappings`` task as well.
|
||||
- Support setting Scala home directory temporary using the switch command: ``++ /path/to/scala/home``.
|
||||
- Support setting Scala home directory temporary using the switch command: ``++ scala-version=/path/to/scala/home``. The scala-version part is optional, but is used as the version for any managed dependencies.
|
||||
- ``export`` command
|
||||
|
||||
* For tasks, prints the contents of the 'export' stream. By convention, this should be the equivalent command line(s) representation. ``compile``, ``doc``, and ``console`` show the approximate command lines for their execution. Classpath tasks print the classpath string suitable for passing as an option.
|
||||
|
|
|
|||
Loading…
Reference in New Issue