mirror of https://github.com/sbt/sbt.git
Merge pull request #2613 from jroper/sbt-doge
Replaced cross building support with sbt-doge
This commit is contained in:
commit
5ecbf50e85
|
|
@ -4,128 +4,269 @@
|
|||
package sbt
|
||||
|
||||
import Keys._
|
||||
import sbt.internal.{ GCUtil, CommandStrings }
|
||||
import sbt.internal.util.complete.{ DefaultParsers, Parser }
|
||||
import sbt.internal.util.AttributeKey
|
||||
import DefaultParsers._
|
||||
import Def.{ ScopedKey, Setting }
|
||||
import Scope.GlobalScope
|
||||
import sbt.internal.CommandStrings.{ CrossCommand, crossHelp, SwitchCommand, switchHelp }
|
||||
import sbt.internal.CommandStrings.{ CrossCommand, CrossRestoreSessionCommand, SwitchCommand, crossHelp, crossRestoreSessionHelp, switchHelp }
|
||||
import java.io.File
|
||||
import sbt.internal.inc.ScalaInstance
|
||||
|
||||
import sbt.internal.inc.ScalaInstance
|
||||
import sbt.io.IO
|
||||
import sbt.librarymanagement.CrossVersion
|
||||
|
||||
object Cross {
|
||||
@deprecated("Moved to CommandStrings.Switch", "0.13.0")
|
||||
final val Switch = CommandStrings.SwitchCommand
|
||||
|
||||
@deprecated("Moved to CommandStrings.Cross", "0.13.0")
|
||||
final val Cross = CommandStrings.CrossCommand
|
||||
private def spacedFirst(name: String) = opOrIDSpaced(name) ~ any.+
|
||||
|
||||
def switchParser(state: State): Parser[(String, String)] =
|
||||
{
|
||||
def versionAndCommand(spacePresent: Boolean) = {
|
||||
val knownVersions = crossVersions(state)
|
||||
val version = token(StringBasic.examples(knownVersions: _*))
|
||||
val spacedVersion = if (spacePresent) version else version & spacedFirst(SwitchCommand)
|
||||
val optionalCommand = token(Space ~> matched(state.combinedParser)) ?? ""
|
||||
spacedVersion ~ optionalCommand
|
||||
}
|
||||
token(SwitchCommand ~> OptSpace) flatMap { sp => versionAndCommand(sp.nonEmpty) }
|
||||
}
|
||||
def spacedFirst(name: String) = opOrIDSpaced(name) ~ any.+
|
||||
private case class Switch(version: ScalaVersion, verbose: Boolean, command: Option[String])
|
||||
private trait ScalaVersion {
|
||||
def force: Boolean
|
||||
}
|
||||
private case class NamedScalaVersion(name: String, force: Boolean) extends ScalaVersion
|
||||
private case class ScalaHomeVersion(home: File, resolveVersion: Option[String], force: Boolean) extends ScalaVersion
|
||||
|
||||
lazy val switchVersion = Command.arb(requireSession(switchParser), switchHelp) {
|
||||
case (state, (arg, command)) =>
|
||||
private def switchParser(state: State): Parser[Switch] = {
|
||||
import DefaultParsers._
|
||||
def versionAndCommand(spacePresent: Boolean) = {
|
||||
val x = Project.extract(state)
|
||||
import x._
|
||||
|
||||
val (resolveVersion, homePath) = arg.split("=") match {
|
||||
case Array(v, h) => (v, h)
|
||||
case _ => ("", arg)
|
||||
}
|
||||
val home = IO.resolve(x.currentProject.base, new File(homePath))
|
||||
// Basic Algorithm.
|
||||
// 1. First we figure out what the new scala instances should be, create settings for them.
|
||||
// 2. Find any non-overridden scalaVersion setting in the whole build and force it to delegate
|
||||
// to the new global settings.
|
||||
// 3. Append these to the session, so that the session is up-to-date and
|
||||
// things like set/session clear, etc. work.
|
||||
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 :== version,
|
||||
scalaHome in GlobalScope :== Some(home),
|
||||
scalaInstance in GlobalScope :== instance
|
||||
)
|
||||
(settings, excludeKeys(Set(scalaVersion.key, scalaHome.key, scalaInstance.key)))
|
||||
} else if (!resolveVersion.isEmpty) {
|
||||
sys.error("Scala home directory did not exist: " + home)
|
||||
} else {
|
||||
state.log.info("Setting version to " + arg)
|
||||
val settings = Seq(
|
||||
scalaVersion in GlobalScope :== arg,
|
||||
scalaHome in GlobalScope :== None
|
||||
)
|
||||
(settings, excludeKeys(Set(scalaVersion.key, scalaHome.key)))
|
||||
val knownVersions = crossVersions(x, currentRef)
|
||||
val version = token(StringBasic.examples(knownVersions: _*)).map { arg =>
|
||||
val force = arg.endsWith("!")
|
||||
val versionArg = if (force) arg.dropRight(1) else arg
|
||||
versionArg.split("=", 2) match {
|
||||
case Array(home) if new File(home).exists() => ScalaHomeVersion(new File(home), None, force)
|
||||
case Array(v) => NamedScalaVersion(v, force)
|
||||
case Array(v, home) => ScalaHomeVersion(new File(home), Some(v).filterNot(_.isEmpty), force)
|
||||
}
|
||||
|
||||
val isForceGc = getOpt(Keys.forcegc in Global) getOrElse GCUtil.defaultForceGarbageCollection
|
||||
// This is how to get the interval, but ignore it, and just forcegc
|
||||
// val gcInterval = getOpt(Keys.minForcegcInterval in Global) getOrElse GCUtil.defaultMinForcegcInterval
|
||||
if (isForceGc) {
|
||||
GCUtil.forceGc(state.log)
|
||||
}
|
||||
|
||||
// TODO - Track delegates and avoid regenerating.
|
||||
val delegates: Seq[Setting[_]] = session.mergeSettings collect {
|
||||
case x if exclude(x) => delegateToGlobal(x.key)
|
||||
val spacedVersion = if (spacePresent) version else version & spacedFirst(SwitchCommand)
|
||||
val verbose = Parser.opt(token(Space ~> "-v"))
|
||||
val optionalCommand = Parser.opt(token(Space ~> matched(state.combinedParser)))
|
||||
(spacedVersion ~ verbose ~ optionalCommand).map {
|
||||
case v ~ verbose ~ command =>
|
||||
Switch(v, verbose.isDefined, command)
|
||||
}
|
||||
val fixedSession = session.appendRaw(add ++ delegates)
|
||||
val fixedState = BuiltinCommands.reapply(fixedSession, structure, state)
|
||||
if (!command.isEmpty) command :: fixedState
|
||||
else fixedState
|
||||
}
|
||||
|
||||
token(SwitchCommand ~> OptSpace) flatMap { sp => versionAndCommand(sp.nonEmpty) }
|
||||
}
|
||||
|
||||
// Creates a delegate for a scoped key that pulls the setting from the global scope.
|
||||
private[this] def delegateToGlobal[T](key: ScopedKey[T]): Setting[_] =
|
||||
SettingKey[T](key.key) in key.scope := (SettingKey[T](key.key) in GlobalScope).value
|
||||
private case class CrossArgs(command: String, verbose: Boolean)
|
||||
|
||||
@deprecated("No longer used.", "0.13.0")
|
||||
def crossExclude(s: Setting[_]): Boolean = excludeKeys(Set(scalaVersion.key, scalaHome.key))(s)
|
||||
|
||||
private[this] def excludeKeys(keys: Set[AttributeKey[_]]): Setting[_] => Boolean =
|
||||
_.key match {
|
||||
case ScopedKey(Scope(_, Global, Global, _), key) if keys.contains(key) => true
|
||||
case _ => false
|
||||
private def crossParser(state: State): Parser[CrossArgs] =
|
||||
token(CrossCommand <~ OptSpace) flatMap { _ =>
|
||||
(token(Parser.opt("-v" <~ Space)) ~ token(matched(state.combinedParser))).map {
|
||||
case (verbose, command) => CrossArgs(command, verbose.isDefined)
|
||||
} & spacedFirst(CrossCommand)
|
||||
}
|
||||
|
||||
def crossParser(state: State): Parser[String] =
|
||||
token(CrossCommand <~ OptSpace) flatMap { _ => token(matched(state.combinedParser & spacedFirst(CrossCommand))) }
|
||||
private def crossRestoreSessionParser(state: State): Parser[String] = token(CrossRestoreSessionCommand)
|
||||
|
||||
lazy val crossBuild = Command.arb(requireSession(crossParser), crossHelp) { (state, command) =>
|
||||
val x = Project.extract(state)
|
||||
import x._
|
||||
val versions = crossVersions(state)
|
||||
val current = scalaVersion in currentRef get structure.data map (SwitchCommand + " " + _) toList;
|
||||
if (versions.isEmpty) command :: state
|
||||
else {
|
||||
versions.map(v => s"$SwitchCommand $v $command") ::: current ::: state
|
||||
}
|
||||
}
|
||||
def crossVersions(state: State): Seq[String] =
|
||||
{
|
||||
val x = Project.extract(state)
|
||||
import x._
|
||||
crossScalaVersions in currentRef get structure.data getOrElse Nil
|
||||
}
|
||||
|
||||
def requireSession[T](p: State => Parser[T]): State => Parser[T] = s =>
|
||||
private def requireSession[T](p: State => Parser[T]): State => Parser[T] = s =>
|
||||
if (s get sessionSettings isEmpty) failure("No project loaded") else p(s)
|
||||
|
||||
private def resolveAggregates(extracted: Extracted): Seq[ProjectRef] = {
|
||||
import extracted._
|
||||
|
||||
def findAggregates(project: ProjectRef): List[ProjectRef] = {
|
||||
project :: (structure.allProjects(project.build).find(_.id == project.project) match {
|
||||
case Some(resolved) => resolved.aggregate.toList.flatMap(findAggregates)
|
||||
case None => Nil
|
||||
})
|
||||
}
|
||||
|
||||
(currentRef :: currentProject.aggregate.toList.flatMap(findAggregates)).distinct
|
||||
}
|
||||
|
||||
private def crossVersions(extracted: Extracted, proj: ProjectRef): Seq[String] = {
|
||||
import extracted._
|
||||
(crossScalaVersions in proj get structure.data) getOrElse {
|
||||
// reading scalaVersion is a one-time deal
|
||||
(scalaVersion in proj get structure.data).toSeq
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the given command into either an aggregate command or a command for a project
|
||||
*/
|
||||
private def parseCommand(command: String): Either[String, (String, String)] = {
|
||||
import DefaultParsers._
|
||||
val parser = (OpOrID <~ charClass(_ == '/', "/")) ~ any.* map {
|
||||
case project ~ cmd => (project, cmd.mkString)
|
||||
}
|
||||
Parser.parse(command, parser).left.map(_ => command)
|
||||
}
|
||||
|
||||
def crossBuild: Command =
|
||||
Command.arb(requireSession(crossParser), crossHelp)(crossBuildCommandImpl)
|
||||
|
||||
private def crossBuildCommandImpl(state: State, args: CrossArgs): State = {
|
||||
val x = Project.extract(state)
|
||||
import x._
|
||||
|
||||
val (aggs, aggCommand) = parseCommand(args.command) match {
|
||||
case Right((project, cmd)) =>
|
||||
(structure.allProjectRefs.filter(_.project == project), cmd)
|
||||
case Left(cmd) => (resolveAggregates(x), cmd)
|
||||
}
|
||||
|
||||
// if we support scalaVersion, projVersions should be cached somewhere since
|
||||
// running ++2.11.1 is at the root level is going to mess with the scalaVersion for the aggregated subproj
|
||||
val projVersions = (aggs flatMap { proj =>
|
||||
crossVersions(x, proj) map { (proj.project, _) }
|
||||
}).toList
|
||||
|
||||
val verbose = if (args.verbose) "-v" else ""
|
||||
|
||||
if (projVersions.isEmpty) {
|
||||
state
|
||||
} else {
|
||||
// Group all the projects by scala version
|
||||
val allCommands = projVersions.groupBy(_._2).mapValues(_.map(_._1)).toSeq.flatMap {
|
||||
case (version, Seq(project)) =>
|
||||
// If only one project for a version, issue it directly
|
||||
Seq(s"$SwitchCommand $verbose $version $project/$aggCommand")
|
||||
case (version, projects) if aggCommand.contains(" ") =>
|
||||
// If the command contains a space, then the all command won't work because it doesn't support issuing
|
||||
// commands with spaces, so revert to running the command on each project one at a time
|
||||
s"$SwitchCommand $verbose $version" :: projects.map(project => s"$project/$aggCommand")
|
||||
case (version, projects) =>
|
||||
// First switch scala version, then use the all command to run the command on each project concurrently
|
||||
Seq(s"$SwitchCommand $verbose $version", projects.map(_ + "/" + aggCommand).mkString("all ", " ", ""))
|
||||
}
|
||||
|
||||
allCommands ::: CrossRestoreSessionCommand :: captureCurrentSession(state, x)
|
||||
}
|
||||
}
|
||||
|
||||
def crossRestoreSession: Command =
|
||||
Command.arb(crossRestoreSessionParser, crossRestoreSessionHelp)(crossRestoreSessionImpl)
|
||||
|
||||
private def crossRestoreSessionImpl(state: State, arg: String): State = {
|
||||
restoreCapturedSession(state, Project.extract(state))
|
||||
}
|
||||
|
||||
private val CapturedSession = AttributeKey[Seq[Setting[_]]]("crossCapturedSession")
|
||||
|
||||
private def captureCurrentSession(state: State, extracted: Extracted): State = {
|
||||
state.put(CapturedSession, extracted.session.rawAppend)
|
||||
}
|
||||
|
||||
private def restoreCapturedSession(state: State, extracted: Extracted): State = {
|
||||
state.get(CapturedSession) match {
|
||||
case Some(rawAppend) =>
|
||||
val restoredSession = extracted.session.copy(rawAppend = rawAppend)
|
||||
BuiltinCommands.reapply(restoredSession, extracted.structure, state).remove(CapturedSession)
|
||||
case None => state
|
||||
}
|
||||
}
|
||||
|
||||
def switchVersion: Command =
|
||||
Command.arb(requireSession(switchParser), switchHelp)(switchCommandImpl)
|
||||
|
||||
private def switchCommandImpl(state: State, args: Switch): State = {
|
||||
val switchedState = switchScalaVersion(args, state)
|
||||
|
||||
args.command.toSeq ::: switchedState
|
||||
}
|
||||
|
||||
private def switchScalaVersion(switch: Switch, state: State): State = {
|
||||
val x = Project.extract(state)
|
||||
import x._
|
||||
|
||||
val (version, instance) = switch.version match {
|
||||
case ScalaHomeVersion(homePath, resolveVersion, _) =>
|
||||
val home = IO.resolve(x.currentProject.base, homePath)
|
||||
if (home.exists()) {
|
||||
val instance = ScalaInstance(home)(state.classLoaderCache.apply _)
|
||||
val version = resolveVersion.getOrElse(instance.actualVersion)
|
||||
(version, Some((home, instance)))
|
||||
} else {
|
||||
sys.error(s"Scala home directory did not exist: $home")
|
||||
}
|
||||
case NamedScalaVersion(v, _) => (v, None)
|
||||
}
|
||||
|
||||
val binaryVersion = CrossVersion.binaryScalaVersion(version)
|
||||
|
||||
def logSwitchInfo(included: Seq[(ProjectRef, Seq[String])], excluded: Seq[(ProjectRef, Seq[String])]) = {
|
||||
|
||||
instance.foreach {
|
||||
case (home, instance) =>
|
||||
state.log.info(s"Using Scala home $home with actual version ${instance.actualVersion}")
|
||||
}
|
||||
if (switch.version.force) {
|
||||
state.log.info(s"Forcing Scala version to $version on all projects.")
|
||||
} else {
|
||||
state.log.info(s"Setting Scala version to $version on ${included.size} projects.")
|
||||
}
|
||||
if (excluded.nonEmpty && !switch.verbose) {
|
||||
state.log.info(s"Excluded ${excluded.size} projects, run ++ $version -v for more details.")
|
||||
}
|
||||
|
||||
def detailedLog(msg: => String) = if (switch.verbose) state.log.info(msg) else state.log.debug(msg)
|
||||
|
||||
def logProject: (ProjectRef, Seq[String]) => Unit = (proj, scalaVersions) => {
|
||||
val current = if (proj == currentRef) "*" else " "
|
||||
detailedLog(s" $current ${proj.project} ${scalaVersions.mkString("(", ", ", ")")}")
|
||||
}
|
||||
detailedLog("Switching Scala version on:")
|
||||
included.foreach(logProject.tupled)
|
||||
detailedLog("Excluding projects:")
|
||||
excluded.foreach(logProject.tupled)
|
||||
}
|
||||
|
||||
val projects: Seq[Reference] = {
|
||||
val projectScalaVersions = structure.allProjectRefs.map(proj => proj -> crossVersions(x, proj))
|
||||
if (switch.version.force) {
|
||||
logSwitchInfo(projectScalaVersions, Nil)
|
||||
structure.allProjectRefs ++ structure.units.keys.map(BuildRef.apply)
|
||||
} else {
|
||||
|
||||
val (included, excluded) = projectScalaVersions.partition {
|
||||
case (proj, scalaVersions) => scalaVersions.exists(v => CrossVersion.binaryScalaVersion(v) == binaryVersion)
|
||||
}
|
||||
logSwitchInfo(included, excluded)
|
||||
included.map(_._1)
|
||||
}
|
||||
}
|
||||
|
||||
setScalaVersionForProjects(version, instance, projects, state, x)
|
||||
}
|
||||
|
||||
private def setScalaVersionForProjects(version: String, instance: Option[(File, ScalaInstance)],
|
||||
projects: Seq[Reference], state: State, extracted: Extracted): State = {
|
||||
import extracted._
|
||||
|
||||
val newSettings = projects.flatMap { project =>
|
||||
val scope = Scope(Select(project), Global, Global, Global)
|
||||
|
||||
instance match {
|
||||
case Some((home, inst)) => Seq(
|
||||
scalaVersion in scope := version,
|
||||
scalaHome in scope := Some(home),
|
||||
scalaInstance in scope := inst
|
||||
)
|
||||
case None => Seq(
|
||||
scalaVersion in scope := version,
|
||||
scalaHome in scope := None
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
val filterKeys: Set[AttributeKey[_]] = Set(scalaVersion, scalaHome, scalaInstance).map(_.key)
|
||||
|
||||
// Filter out any old scala version settings that were added, this is just for hygiene.
|
||||
val filteredRawAppend = session.rawAppend.filter(_.key match {
|
||||
case ScopedKey(Scope(Select(ref), Global, Global, Global), key) if filterKeys.contains(key) && projects.contains(ref) => false
|
||||
case _ => true
|
||||
})
|
||||
|
||||
val newSession = session.copy(rawAppend = filteredRawAppend ++ newSettings)
|
||||
|
||||
BuiltinCommands.reapply(newSession, structure, state)
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -92,7 +92,7 @@ object BuiltinCommands {
|
|||
def ScriptCommands: Seq[Command] = Seq(ignore, exit, Script.command, setLogLevel, early, act, nop)
|
||||
def DefaultCommands: Seq[Command] = Seq(ignore, help, completionsCommand, about, tasks, settingsCommand, loadProject,
|
||||
projects, project, reboot, read, history, set, sessionCommand, inspect, loadProjectImpl, loadFailed, Cross.crossBuild, Cross.switchVersion,
|
||||
setOnFailure, clearOnFailure, stashOnFailure, popOnFailure, setLogLevel, plugin, plugins,
|
||||
Cross.crossRestoreSession, setOnFailure, clearOnFailure, stashOnFailure, popOnFailure, setLogLevel, plugin, plugins,
|
||||
ifLast, multi, shell, continuous, eval, alias, append, last, lastGrep, export, boot, nop, call, exit, early, initialize, act) ++
|
||||
compatCommands
|
||||
def DefaultBootCommands: Seq[String] = LoadProject :: (IfLast + " " + Shell) :: Nil
|
||||
|
|
|
|||
|
|
@ -293,31 +293,47 @@ defaults
|
|||
Nil
|
||||
|
||||
val CrossCommand = "+"
|
||||
val CrossRestoreSessionCommand = "+-"
|
||||
val SwitchCommand = "++"
|
||||
|
||||
def crossHelp: Help = Help.more(CrossCommand, CrossDetailed)
|
||||
def crossRestoreSessionHelp = Help.more(CrossRestoreSessionCommand, CrossRestoreSessionDetailed)
|
||||
def switchHelp: Help = Help.more(SwitchCommand, SwitchDetailed)
|
||||
|
||||
def CrossDetailed =
|
||||
s"""$CrossCommand <command>
|
||||
s"""$CrossCommand [-v] <command>
|
||||
Runs <command> for each Scala version specified for cross-building.
|
||||
|
||||
For each string in `crossScalaVersions` in the current project, this command sets the
|
||||
`scalaVersion` of all projects to that version, reloads the build, and
|
||||
executes <command>. When finished, it reloads the build with the original
|
||||
Scala version.
|
||||
For each string in `crossScalaVersions` in each project project, this command sets
|
||||
the `scalaVersion` of all projects that list that Scala version with that Scala
|
||||
version reloads the build, and then executes <command> for those projects. When
|
||||
finished, it resets the build to its original state.
|
||||
|
||||
If -v is supplied, verbose logging of the Scala version switching is done.
|
||||
|
||||
See also `help $SwitchCommand`
|
||||
"""
|
||||
|
||||
def CrossRestoreSessionDetailed =
|
||||
s"""$CrossRestoreSessionCommand
|
||||
|
||||
Restores a session that was captured by the cross command, +.
|
||||
"""
|
||||
|
||||
def SwitchDetailed =
|
||||
s"""$SwitchCommand <scala-version> [<command>]
|
||||
s"""$SwitchCommand <scala-version>[!] [-v] [<command>]
|
||||
Changes the Scala version and runs a command.
|
||||
|
||||
Sets the `scalaVersion` of all projects to <scala-version> and reloads the build.
|
||||
Sets the `scalaVersion` of all projects that define a Scala cross version that is binary
|
||||
compatible with <scala-version> and reloads the build. If ! is supplied, then the
|
||||
version is forced on all projects regardless of whether they are binary compatible or
|
||||
not.
|
||||
|
||||
If -v is supplied, verbose logging of the Scala version switching is done.
|
||||
|
||||
If <command> is provided, it is then executed.
|
||||
|
||||
$SwitchCommand [<scala-version>=]<scala-home> [<command>]
|
||||
$SwitchCommand [<scala-version>=]<scala-home>[!] [-v] [<command>]
|
||||
Uses the Scala installation at <scala-home> by configuring the scalaHome setting for
|
||||
all projects.
|
||||
|
||||
|
|
@ -325,6 +341,12 @@ $SwitchCommand [<scala-version>=]<scala-home> [<command>]
|
|||
This is important when using managed dependencies. This version will determine the
|
||||
cross-version used as well as transitive dependencies.
|
||||
|
||||
Only projects that are listed to be binary compatible with the selected Scala version
|
||||
have their Scala version switched. If ! is supplied, then all projects projects have
|
||||
their Scala version switched.
|
||||
|
||||
If -v is supplied, verbose logging of the Scala version switching is done.
|
||||
|
||||
If <command> is provided, it is then executed.
|
||||
|
||||
See also `help $CrossCommand`
|
||||
|
|
|
|||
|
|
@ -0,0 +1,10 @@
|
|||
[@jroper]: https://github.com/jroper
|
||||
[2613]: https://github.com/sbt/sbt/pull/2613
|
||||
|
||||
### Fixes with compatibility implications
|
||||
|
||||
### Improvements
|
||||
|
||||
- Replace cross building support with sbt-doge. This allows builds with projects that have multiple different combinations of cross scala versions to be cross built correctly. The behaviour of ++ is changed so that it only updates the Scala version of projects that support that Scala version, but the Scala version can be post fixed with ! to force it to change for all projects. A -v argument has been added that prints verbose information about which projects are having their settings changed along with their cross scala versions. [#2613][2613] by [@jroper][@jroper].
|
||||
|
||||
### Bug fixes
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
|
||||
lazy val rootProj = (project in file(".")).
|
||||
aggregate(libProj, fooPlugin)
|
||||
|
||||
lazy val libProj = (project in file("lib")).
|
||||
settings(
|
||||
name := "foo-lib",
|
||||
scalaVersion := "2.11.8",
|
||||
crossScalaVersions := Seq("2.11.8", "2.10.4")
|
||||
)
|
||||
|
||||
lazy val fooPlugin =(project in file("sbt-foo")).
|
||||
settings(
|
||||
name := "sbt-foo",
|
||||
sbtPlugin := true,
|
||||
scalaVersion := "2.10.4",
|
||||
crossScalaVersions := Seq("2.10.4")
|
||||
)
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
package foo
|
||||
|
||||
object Foo {
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
package foo.sbt
|
||||
|
||||
object SbtFoo {
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,46 @@
|
|||
> + compile
|
||||
|
||||
$ exists lib/target/scala-2.11
|
||||
$ exists lib/target/scala-2.10
|
||||
$ exists sbt-foo/target/scala-2.10
|
||||
-$ exists sbt-foo/target/scala-2.11
|
||||
|
||||
> clean
|
||||
> + libProj/compile
|
||||
|
||||
$ exists lib/target/scala-2.11
|
||||
$ exists lib/target/scala-2.10
|
||||
-$ exists sbt-foo/target/scala-2.10
|
||||
-$ exists sbt-foo/target/scala-2.11
|
||||
|
||||
> clean
|
||||
> ++ 2.11.1 compile
|
||||
|
||||
$ exists lib/target/scala-2.11
|
||||
-$ exists lib/target/scala-2.10
|
||||
$ exists sbt-foo/target/scala-2.10
|
||||
-$ exists sbt-foo/target/scala-2.11
|
||||
|
||||
> clean
|
||||
> ++ 2.10.4 compile
|
||||
|
||||
-$ exists lib/target/scala-2.11
|
||||
$ exists lib/target/scala-2.10
|
||||
$ exists sbt-foo/target/scala-2.10
|
||||
-$ exists sbt-foo/target/scala-2.11
|
||||
|
||||
> clean
|
||||
> ++ 2.11.5 compile
|
||||
|
||||
$ exists lib/target/scala-2.11
|
||||
-$ exists lib/target/scala-2.10
|
||||
$ exists sbt-foo/target/scala-2.10
|
||||
-$ exists sbt-foo/target/scala-2.11
|
||||
|
||||
> clean
|
||||
> ++ 2.11.5! compile
|
||||
|
||||
$ exists lib/target/scala-2.11
|
||||
-$ exists lib/target/scala-2.10
|
||||
-$ exists sbt-foo/target/scala-2.10
|
||||
$ exists sbt-foo/target/scala-2.11
|
||||
|
|
@ -1,7 +1,7 @@
|
|||
> check 2.7.7 2.9.1 2.9.0-1
|
||||
> ++ 2.8.2
|
||||
> ++ 2.8.2!
|
||||
> check 2.8.2 2.8.2 2.8.1
|
||||
> ++ 2.10.4
|
||||
> ++ 2.10.4!
|
||||
> set resolvers ++= Nil
|
||||
> check 2.10.4 2.10.4 2.10.4
|
||||
> session clear-all
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
# A.scala needs B.scala, it won't be in source list
|
||||
> ++2.11.4
|
||||
> ++2.11.4!
|
||||
-> compile
|
||||
|
||||
# A.scala needs B.scala, it would be in source list
|
||||
> ++2.10.4
|
||||
> ++2.10.4!
|
||||
> compile
|
||||
|
|
|
|||
Loading…
Reference in New Issue