mirror of https://github.com/sbt/sbt.git
Merge pull request #3221 from eed3si9n/fport/3133
[fport] Port sbt-cross-building's ^ and ^^ commands
This commit is contained in:
commit
4d3b910a19
|
|
@ -24,7 +24,7 @@ import sbt.librarymanagement.CrossVersion
|
|||
|
||||
object Cross {
|
||||
|
||||
private def spacedFirst(name: String) = opOrIDSpaced(name) ~ any.+
|
||||
private[sbt] def spacedFirst(name: String) = opOrIDSpaced(name) ~ any.+
|
||||
|
||||
private case class Switch(version: ScalaVersion, verbose: Boolean, command: Option[String])
|
||||
private trait ScalaVersion {
|
||||
|
|
@ -77,7 +77,7 @@ object Cross {
|
|||
private def crossRestoreSessionParser(state: State): Parser[String] =
|
||||
token(CrossRestoreSessionCommand)
|
||||
|
||||
private def requireSession[T](p: State => Parser[T]): State => Parser[T] =
|
||||
private[sbt] 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] = {
|
||||
|
|
|
|||
|
|
@ -218,6 +218,10 @@ object Defaults extends BuildCommon {
|
|||
envVars :== Map.empty,
|
||||
sbtVersion := appConfiguration.value.provider.id.version,
|
||||
sbtBinaryVersion := binarySbtVersion(sbtVersion.value),
|
||||
// `pluginCrossBuild` scoping is based on sbt-cross-building plugin.
|
||||
// The idea here is to be able to define a `sbtVersion in pluginCrossBuild`, which
|
||||
// directs the dependencies of the plugin to build to the specified sbt plugin version.
|
||||
sbtVersion in pluginCrossBuild := sbtVersion.value,
|
||||
watchingMessage := Watched.defaultWatchingMessage,
|
||||
triggeredMessage := Watched.defaultTriggeredMessage,
|
||||
onLoad := idFun[State],
|
||||
|
|
@ -293,10 +297,16 @@ object Defaults extends BuildCommon {
|
|||
sourceManaged := configSrcSub(sourceManaged).value,
|
||||
scalaSource := sourceDirectory.value / "scala",
|
||||
javaSource := sourceDirectory.value / "java",
|
||||
unmanagedSourceDirectories := makeCrossSources(scalaSource.value,
|
||||
javaSource.value,
|
||||
scalaBinaryVersion.value,
|
||||
crossPaths.value),
|
||||
unmanagedSourceDirectories := {
|
||||
makeCrossSources(scalaSource.value,
|
||||
javaSource.value,
|
||||
scalaBinaryVersion.value,
|
||||
crossPaths.value) ++
|
||||
makePluginCrossSources(sbtPlugin.value,
|
||||
scalaSource.value,
|
||||
(sbtBinaryVersion in pluginCrossBuild).value,
|
||||
crossPaths.value)
|
||||
},
|
||||
unmanagedSources := collectFiles(unmanagedSourceDirectories,
|
||||
includeFilter in unmanagedSources,
|
||||
excludeFilter in unmanagedSources).value,
|
||||
|
|
@ -349,9 +359,22 @@ object Defaults extends BuildCommon {
|
|||
),
|
||||
scalaInstance := scalaInstanceTask.value,
|
||||
crossVersion := (if (crossPaths.value) CrossVersion.binary else Disabled()),
|
||||
scalaVersion := {
|
||||
val scalaV = scalaVersion.value
|
||||
val sv = (sbtBinaryVersion in pluginCrossBuild).value
|
||||
val isPlugin = sbtPlugin.value
|
||||
if (isPlugin) {
|
||||
val x = scalaVersionFromSbtBinaryVersion(sv)
|
||||
println(s"scalaVersionFromSbtBinaryVersion($sv) = $x")
|
||||
x
|
||||
} else scalaV
|
||||
},
|
||||
sbtBinaryVersion in pluginCrossBuild := binarySbtVersion(
|
||||
(sbtVersion in pluginCrossBuild).value),
|
||||
crossSbtVersions := Vector((sbtVersion in pluginCrossBuild).value),
|
||||
crossTarget := makeCrossTarget(target.value,
|
||||
scalaBinaryVersion.value,
|
||||
sbtBinaryVersion.value,
|
||||
(sbtBinaryVersion in pluginCrossBuild).value,
|
||||
sbtPlugin.value,
|
||||
crossPaths.value),
|
||||
clean := {
|
||||
|
|
@ -359,6 +382,8 @@ object Defaults extends BuildCommon {
|
|||
IvyActions.cleanCachedResolutionCache(ivyModule.value, streams.value.log)
|
||||
},
|
||||
scalaCompilerBridgeSource := {
|
||||
// This is a workaround for sbtVersion getting set to another value.
|
||||
val sv = appConfiguration.value.provider.id.version
|
||||
if (ScalaInstance.isDotty(scalaVersion.value))
|
||||
// Maintained at https://github.com/lampepfl/dotty/tree/master/sbt-bridge
|
||||
ModuleID(scalaOrganization.value, "dotty-sbt-bridge", scalaVersion.value)
|
||||
|
|
@ -382,6 +407,14 @@ object Defaults extends BuildCommon {
|
|||
derive(scalaBinaryVersion := binaryScalaVersion(scalaVersion.value))
|
||||
))
|
||||
|
||||
private[sbt] def scalaVersionFromSbtBinaryVersion(sv: String): String =
|
||||
VersionNumber(sv) match {
|
||||
case VersionNumber(Seq(0, 12, _*), _, _) => "2.9.2"
|
||||
case VersionNumber(Seq(0, 13, _*), _, _) => "2.10.6"
|
||||
case VersionNumber(Seq(1, 0, _*), _, _) => "2.12.2"
|
||||
case _ => sys.error(s"Unsupported sbt binary version: $sv")
|
||||
}
|
||||
|
||||
def makeCrossSources(scalaSrcDir: File,
|
||||
javaSrcDir: File,
|
||||
sv: String,
|
||||
|
|
@ -392,6 +425,15 @@ object Defaults extends BuildCommon {
|
|||
Seq(scalaSrcDir, javaSrcDir)
|
||||
}
|
||||
|
||||
def makePluginCrossSources(isPlugin: Boolean,
|
||||
scalaSrcDir: File,
|
||||
sbtBinaryV: String,
|
||||
cross: Boolean): Seq[File] = {
|
||||
if (cross && isPlugin)
|
||||
Vector(scalaSrcDir.getParentFile / s"${scalaSrcDir.name}-sbt-$sbtBinaryV")
|
||||
else Vector()
|
||||
}
|
||||
|
||||
def makeCrossTarget(t: File, sv: String, sbtv: String, plugin: Boolean, cross: Boolean): File = {
|
||||
val scalaBase = if (cross) t / ("scala-" + sv) else t
|
||||
if (plugin) scalaBase / ("sbt-" + sbtv) else scalaBase
|
||||
|
|
@ -1470,7 +1512,20 @@ object Defaults extends BuildCommon {
|
|||
projectCore ++ disableAggregation ++ Seq(
|
||||
// Missing but core settings
|
||||
baseDirectory := thisProject.value.base,
|
||||
target := baseDirectory.value / "target"
|
||||
target := baseDirectory.value / "target",
|
||||
// Use (sbtVersion in pluginCrossBuild) to pick the sbt module to depend from the plugin.
|
||||
// Because `sbtVersion in pluginCrossBuild` can be scoped to project level,
|
||||
// this setting needs to be set here too.
|
||||
sbtDependency in pluginCrossBuild := {
|
||||
val app = appConfiguration.value
|
||||
val id = app.provider.id
|
||||
val sv = (sbtVersion in pluginCrossBuild).value
|
||||
val scalaV = (scalaVersion in pluginCrossBuild).value
|
||||
val binVersion = (scalaBinaryVersion in pluginCrossBuild).value
|
||||
val cross = if (id.crossVersioned) CrossVersion.binary else Disabled()
|
||||
val base = ModuleID(id.groupID, id.name, sv).withCrossVersion(cross)
|
||||
CrossVersion(scalaV, binVersion)(base).withCrossVersion(Disabled())
|
||||
}
|
||||
)
|
||||
// build.sbt is treated a Scala source of metabuild, so to enable deprecation flag on build.sbt we set the option here.
|
||||
lazy val deprecationSettings: Seq[Setting[_]] =
|
||||
|
|
@ -1884,8 +1939,11 @@ object Classpaths {
|
|||
allDependencies := {
|
||||
val base = projectDependencies.value ++ libraryDependencies.value
|
||||
val dependency = sbtDependency.value
|
||||
val isPlugin = sbtPlugin.value
|
||||
val sbtdeps =
|
||||
(sbtDependency in pluginCrossBuild).value.withConfigurations(Some(Provided.name))
|
||||
val pluginAdjust =
|
||||
if (sbtPlugin.value) dependency.withConfigurations(Some(Provided.name)) +: base
|
||||
if (isPlugin) sbtdeps +: base
|
||||
else base
|
||||
val sbtOrg = scalaOrganization.value
|
||||
val version = scalaVersion.value
|
||||
|
|
@ -1919,8 +1977,8 @@ object Classpaths {
|
|||
Def.setting {
|
||||
if (sbtPlugin.value)
|
||||
sbtPluginExtra(projectID.value,
|
||||
(sbtBinaryVersion in update).value,
|
||||
(scalaBinaryVersion in update).value)
|
||||
(sbtBinaryVersion in pluginCrossBuild).value,
|
||||
(scalaBinaryVersion in pluginCrossBuild).value)
|
||||
else projectID.value
|
||||
}
|
||||
private[sbt] def ivySbt0: Initialize[Task[IvySbt]] =
|
||||
|
|
@ -1950,77 +2008,78 @@ object Classpaths {
|
|||
transitiveClassifiers in updateSbtClassifiers ~= (_.filter(_ != DocClassifier))
|
||||
))
|
||||
def sbtClassifiersTasks =
|
||||
sbtClassifiersGlobalDefaults ++ inTask(updateSbtClassifiers)(
|
||||
Seq(
|
||||
externalResolvers := {
|
||||
val explicit = buildStructure.value
|
||||
.units(thisProjectRef.value.build)
|
||||
.unit
|
||||
.plugins
|
||||
.pluginData
|
||||
.resolvers
|
||||
explicit orElse bootRepositories(appConfiguration.value) getOrElse externalResolvers.value
|
||||
},
|
||||
ivyConfiguration := new InlineIvyConfiguration(
|
||||
ivyPaths.value,
|
||||
externalResolvers.value.toVector,
|
||||
Vector.empty,
|
||||
Vector.empty,
|
||||
offline.value,
|
||||
Option(lock(appConfiguration.value)),
|
||||
checksums.value.toVector,
|
||||
Some(target.value / "resolution-cache"),
|
||||
UpdateOptions(),
|
||||
streams.value.log
|
||||
),
|
||||
ivySbt := ivySbt0.value,
|
||||
classifiersModule := classifiersModuleTask.value,
|
||||
// Redefine scalaVersion and scalaBinaryVersion specifically for the dependency graph used for updateSbtClassifiers task.
|
||||
// to fix https://github.com/sbt/sbt/issues/2686
|
||||
scalaVersion := appConfiguration.value.provider.scalaProvider.version,
|
||||
scalaBinaryVersion := binaryScalaVersion(scalaVersion.value),
|
||||
ivyScala := {
|
||||
Some(
|
||||
IvyScala(scalaVersion.value,
|
||||
scalaBinaryVersion.value,
|
||||
Vector(),
|
||||
checkExplicit = false,
|
||||
filterImplicit = false,
|
||||
overrideScalaVersion = true).withScalaOrganization(scalaOrganization.value))
|
||||
},
|
||||
updateSbtClassifiers in TaskGlobal := (Def.task {
|
||||
val s = streams.value
|
||||
val is = ivySbt.value
|
||||
val mod = classifiersModule.value
|
||||
val c = updateConfiguration.value
|
||||
val app = appConfiguration.value
|
||||
val srcTypes = sourceArtifactTypes.value
|
||||
val docTypes = docArtifactTypes.value
|
||||
val log = s.log
|
||||
val out = is.withIvy(log)(_.getSettings.getDefaultIvyUserDir)
|
||||
val uwConfig = (unresolvedWarningConfiguration in update).value
|
||||
val depDir = dependencyCacheDirectory.value
|
||||
val ivy = ivyScala.value
|
||||
val st = state.value
|
||||
withExcludes(out, mod.classifiers, lock(app)) { excludes =>
|
||||
val noExplicitCheck = ivy.map(_.withCheckExplicit(false))
|
||||
IvyActions.transitiveScratch(
|
||||
is,
|
||||
"sbt",
|
||||
GetClassifiersConfiguration(mod,
|
||||
excludes,
|
||||
c.withArtifactFilter(c.artifactFilter.invert),
|
||||
noExplicitCheck,
|
||||
srcTypes,
|
||||
docTypes),
|
||||
uwConfig,
|
||||
LogicalClock(st.hashCode),
|
||||
Some(depDir),
|
||||
log
|
||||
)
|
||||
}
|
||||
} tag (Tags.Update, Tags.Network)).value
|
||||
)) ++ Seq(bootIvyConfiguration := (ivyConfiguration in updateSbtClassifiers).value)
|
||||
sbtClassifiersGlobalDefaults ++
|
||||
inTask(updateSbtClassifiers)(
|
||||
Seq(
|
||||
externalResolvers := {
|
||||
val explicit = buildStructure.value
|
||||
.units(thisProjectRef.value.build)
|
||||
.unit
|
||||
.plugins
|
||||
.pluginData
|
||||
.resolvers
|
||||
explicit orElse bootRepositories(appConfiguration.value) getOrElse externalResolvers.value
|
||||
},
|
||||
ivyConfiguration := new InlineIvyConfiguration(
|
||||
ivyPaths.value,
|
||||
externalResolvers.value.toVector,
|
||||
Vector.empty,
|
||||
Vector.empty,
|
||||
offline.value,
|
||||
Option(lock(appConfiguration.value)),
|
||||
checksums.value.toVector,
|
||||
Some(crossTarget.value / "resolution-cache"),
|
||||
UpdateOptions(),
|
||||
streams.value.log
|
||||
),
|
||||
ivySbt := ivySbt0.value,
|
||||
classifiersModule := classifiersModuleTask.value,
|
||||
// Redefine scalaVersion and scalaBinaryVersion specifically for the dependency graph used for updateSbtClassifiers task.
|
||||
// to fix https://github.com/sbt/sbt/issues/2686
|
||||
scalaVersion := appConfiguration.value.provider.scalaProvider.version,
|
||||
scalaBinaryVersion := binaryScalaVersion(scalaVersion.value),
|
||||
ivyScala := {
|
||||
Some(
|
||||
IvyScala(scalaVersion.value,
|
||||
scalaBinaryVersion.value,
|
||||
Vector(),
|
||||
checkExplicit = false,
|
||||
filterImplicit = false,
|
||||
overrideScalaVersion = true).withScalaOrganization(scalaOrganization.value))
|
||||
},
|
||||
updateSbtClassifiers in TaskGlobal := (Def.task {
|
||||
val s = streams.value
|
||||
val is = ivySbt.value
|
||||
val mod = classifiersModule.value
|
||||
val c = updateConfiguration.value
|
||||
val app = appConfiguration.value
|
||||
val srcTypes = sourceArtifactTypes.value
|
||||
val docTypes = docArtifactTypes.value
|
||||
val log = s.log
|
||||
val out = is.withIvy(log)(_.getSettings.getDefaultIvyUserDir)
|
||||
val uwConfig = (unresolvedWarningConfiguration in update).value
|
||||
val depDir = dependencyCacheDirectory.value
|
||||
val ivy = ivyScala.value
|
||||
val st = state.value
|
||||
withExcludes(out, mod.classifiers, lock(app)) { excludes =>
|
||||
val noExplicitCheck = ivy.map(_.withCheckExplicit(false))
|
||||
IvyActions.transitiveScratch(
|
||||
is,
|
||||
"sbt",
|
||||
GetClassifiersConfiguration(mod,
|
||||
excludes,
|
||||
c.withArtifactFilter(c.artifactFilter.invert),
|
||||
noExplicitCheck,
|
||||
srcTypes,
|
||||
docTypes),
|
||||
uwConfig,
|
||||
LogicalClock(st.hashCode),
|
||||
Some(depDir),
|
||||
log
|
||||
)
|
||||
}
|
||||
} tag (Tags.Update, Tags.Network)).value
|
||||
)) ++ Seq(bootIvyConfiguration := (ivyConfiguration in updateSbtClassifiers).value)
|
||||
|
||||
def classifiersModuleTask: Initialize[Task[GetClassifiersModule]] =
|
||||
Def.task {
|
||||
|
|
@ -2433,7 +2492,7 @@ object Classpaths {
|
|||
val (rs, other) = (fullResolvers.value.toVector, otherResolvers.value.toVector)
|
||||
val s = streams.value
|
||||
warnResolversConflict(rs ++: other, s.log)
|
||||
val resCacheDir = target.value / "resolution-cache"
|
||||
val resCacheDir = crossTarget.value / "resolution-cache"
|
||||
new InlineIvyConfiguration(
|
||||
ivyPaths.value,
|
||||
rs,
|
||||
|
|
|
|||
|
|
@ -201,6 +201,8 @@ object Keys {
|
|||
val classpathOptions = SettingKey[ClasspathOptions]("classpath-options", "Configures handling of Scala classpaths.", DSetting)
|
||||
val discoveredSbtPlugins = TaskKey[PluginDiscovery.DiscoveredNames]("discovered-sbt-plugins", "The names of sbt plugin-related modules (modules that extend Build, Plugin, AutoPlugin) defined by this project.", CTask)
|
||||
val sbtPlugin = SettingKey[Boolean]("sbt-plugin", "If true, enables adding sbt as a dependency and auto-generation of the plugin descriptor file.", BMinusSetting)
|
||||
val pluginCrossBuild = TaskKey[Unit]("pluginCrossBuild", "Dummy task to scope `sbtVersion in pluginCrossBuild`, which gets used for plugin compilation.")
|
||||
val crossSbtVersions = SettingKey[Seq[String]]("crossSbtVersions", "The versions of Sbt used when cross-building an sbt plugin.")
|
||||
val printWarnings = TaskKey[Unit]("print-warnings", "Shows warnings from compilation, including ones that weren't printed initially.", BPlusTask)
|
||||
val fileInputOptions = SettingKey[Seq[String]]("file-input-options", "Options that take file input, which may invalidate the cache.", CSetting)
|
||||
val scalaCompilerBridgeSource = SettingKey[ModuleID]("scala-compiler-bridge-source", "Configures the module ID of the sources of the compiler bridge.", CSetting)
|
||||
|
|
|
|||
|
|
@ -150,6 +150,7 @@ object BuiltinCommands {
|
|||
|
||||
def ConsoleCommands: Seq[Command] =
|
||||
Seq(ignore, exit, IvyConsole.command, setLogLevel, early, act, nop)
|
||||
|
||||
def ScriptCommands: Seq[Command] =
|
||||
Seq(ignore, exit, Script.command, setLogLevel, early, act, nop)
|
||||
|
||||
|
|
@ -175,6 +176,8 @@ object BuiltinCommands {
|
|||
loadFailed,
|
||||
Cross.crossBuild,
|
||||
Cross.switchVersion,
|
||||
PluginCross.pluginCross,
|
||||
PluginCross.pluginSwitch,
|
||||
Cross.crossRestoreSession,
|
||||
setOnFailure,
|
||||
clearOnFailure,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,76 @@
|
|||
/* sbt -- Simple Build Tool
|
||||
* Copyright 2011 Mark Harrah
|
||||
* Copyright 2012 Johannes Rudolph
|
||||
*
|
||||
* This was basically copied from the sbt source code and then adapted to use
|
||||
* `sbtVersion in pluginCrossBuild`.
|
||||
*/
|
||||
package sbt
|
||||
|
||||
import sbt.internal.util.complete.{ Parser, DefaultParsers }
|
||||
import DefaultParsers._
|
||||
import sbt.Keys._
|
||||
import Project._
|
||||
import Scope.GlobalScope
|
||||
import Def.ScopedKey
|
||||
import sbt.internal.Load
|
||||
import sbt.internal.CommandStrings._
|
||||
import Cross.{ spacedFirst, requireSession }
|
||||
|
||||
/**
|
||||
* Module responsible for plugin cross building.
|
||||
*/
|
||||
private[sbt] object PluginCross {
|
||||
lazy val pluginSwitch: Command = {
|
||||
def switchParser(state: State): Parser[(String, String)] = {
|
||||
val knownVersions = Nil
|
||||
lazy val switchArgs = token(NotSpace.examples(knownVersions: _*)) ~ (token(
|
||||
Space ~> matched(state.combinedParser)) ?? "")
|
||||
lazy val nextSpaced = spacedFirst(PluginSwitchCommand)
|
||||
token(PluginSwitchCommand ~ OptSpace) flatMap { _ =>
|
||||
switchArgs & nextSpaced
|
||||
}
|
||||
}
|
||||
def crossExclude(s: Def.Setting[_]): Boolean =
|
||||
s.key match {
|
||||
case ScopedKey(Scope(_, _, pluginCrossBuild.key, _), sbtVersion.key) => true
|
||||
case _ => false
|
||||
}
|
||||
Command.arb(requireSession(switchParser), pluginSwitchHelp) {
|
||||
case (state, (version, command)) =>
|
||||
val x = Project.extract(state)
|
||||
import x._
|
||||
state.log.info(s"Setting `sbtVersion in pluginCrossBuild` to $version")
|
||||
val add = (sbtVersion in GlobalScope in pluginCrossBuild :== version) :: Nil
|
||||
val cleared = session.mergeSettings.filterNot(crossExclude)
|
||||
val newStructure = Load.reapply(cleared ++ add, structure)
|
||||
Project.setProject(session, newStructure, command :: state)
|
||||
}
|
||||
}
|
||||
|
||||
lazy val pluginCross: Command = {
|
||||
def crossParser(state: State): Parser[String] =
|
||||
token(PluginCrossCommand <~ OptSpace) flatMap { _ =>
|
||||
token(
|
||||
matched(state.combinedParser &
|
||||
spacedFirst(PluginCrossCommand)))
|
||||
}
|
||||
def crossVersions(state: State): List[String] = {
|
||||
val x = Project.extract(state)
|
||||
import x._
|
||||
((crossSbtVersions in currentRef) get structure.data getOrElse Nil).toList
|
||||
}
|
||||
Command.arb(requireSession(crossParser), pluginCrossHelp) {
|
||||
case (state, command) =>
|
||||
val x = Project.extract(state)
|
||||
import x._
|
||||
val versions = crossVersions(state)
|
||||
val current = (sbtVersion in pluginCrossBuild)
|
||||
.get(structure.data)
|
||||
.map(PluginSwitchCommand + " " + _)
|
||||
.toList
|
||||
if (versions.isEmpty) command :: state
|
||||
else versions.map(PluginSwitchCommand + " " + _ + " " + command) ::: current ::: state
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -373,4 +373,32 @@ $SwitchCommand [<scala-version>=]<scala-home>[!] [-v] [<command>]
|
|||
|
||||
See also `help $CrossCommand`
|
||||
"""
|
||||
|
||||
val PluginCrossCommand = "^"
|
||||
val PluginSwitchCommand = "^^"
|
||||
|
||||
def pluginCrossHelp: Help = Help.more(PluginCrossCommand, PluginCrossDetailed)
|
||||
def pluginSwitchHelp: Help = Help.more(PluginSwitchCommand, PluginSwitchDetailed)
|
||||
|
||||
def PluginCrossDetailed =
|
||||
s"""$PluginCrossCommand <command>
|
||||
Runs <command> for each sbt version specified for cross-building.
|
||||
|
||||
For each string in `crossSbtVersions` in the current project, this command sets the
|
||||
`sbtVersion in pluginCrossBuild` of all projects to that version, reloads the build,
|
||||
and executes <command>. When finished, it reloads the build with the original
|
||||
Scala version.
|
||||
|
||||
See also `help $PluginSwitchCommand`
|
||||
"""
|
||||
|
||||
def PluginSwitchDetailed =
|
||||
s"""$PluginSwitchCommand <sbt-version> [<command>]
|
||||
Changes the sbt version and runs a command.
|
||||
|
||||
Sets the `sbtVersion in pluginCrossBuild` of all projects to <sbt-version> and
|
||||
reloads the build. If <command> is provided, it is then executed.
|
||||
|
||||
See also `help $CrossCommand`
|
||||
"""
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,37 @@
|
|||
|
||||
### Improvements
|
||||
|
||||
- Ports sbt-cross-building's `^` and `^^` commands for plugin cross building. See below.
|
||||
|
||||
### sbt-cross-building
|
||||
|
||||
[@jrudolph][@jrudolph]'s sbt-cross-building is a plugin author's plugin.
|
||||
It adds cross command `^` and sbtVersion switch command `^^`, similar to `+` and `++`,
|
||||
but for switching between multiple sbt versions across major versions.
|
||||
sbt 0.13.16 merges these commands into sbt because the feature it provides is useful as we migrate plugins to sbt 1.0.
|
||||
|
||||
To switch the `sbtVersion in pluginCrossBuild` from the shell use:
|
||||
|
||||
```
|
||||
^^ 1.0.0-M5
|
||||
```
|
||||
|
||||
Your plugin will now build with sbt 1.0.0-M5 (and its Scala version 2.12.2).
|
||||
|
||||
If you need to make changes specific to a sbt version, you can now include them into `src/main/scala-sbt-0.13`,
|
||||
and `src/main/scala-sbt-1.0.0-M5`, where the binary sbt version number is used as postfix.
|
||||
|
||||
To run a command across multiple sbt versions, set:
|
||||
|
||||
```scala
|
||||
crossSbtVersions := Vector("0.13.15", "1.0.0-M5")
|
||||
```
|
||||
|
||||
Then, run:
|
||||
|
||||
```
|
||||
^ compile
|
||||
```
|
||||
|
||||
[@jrudolph]: https://github.com/jrudolph
|
||||
[@eed3si9n]: https://github.com/eed3si9n
|
||||
|
|
@ -2,6 +2,8 @@ libraryDependencies += "log4j" % "log4j" % "1.2.16" % "compile"
|
|||
|
||||
autoScalaLibrary := false
|
||||
|
||||
crossPaths := false
|
||||
|
||||
TaskKey[Unit]("check-last-update-time") := (streams map { (s) =>
|
||||
val fullUpdateOutput = s.cacheDirectory / "out"
|
||||
val timeDiff = System.currentTimeMillis()-fullUpdateOutput.lastModified()
|
||||
|
|
|
|||
|
|
@ -0,0 +1,24 @@
|
|||
val baseSbt = "1.0"
|
||||
|
||||
lazy val root = (project in file("."))
|
||||
.settings(
|
||||
sbtPlugin := true,
|
||||
|
||||
TaskKey[Unit]("check") := {
|
||||
val crossV = (sbtVersion in pluginCrossBuild).value
|
||||
val sv = projectID.value.extraAttributes("e:scalaVersion")
|
||||
assert(sbtVersion.value startsWith baseSbt, s"Wrong sbt version: ${sbtVersion.value}")
|
||||
assert(sv == "2.12", s"Wrong e:scalaVersion: $sv")
|
||||
assert(scalaBinaryVersion.value == "2.12", s"Wrong Scala binary version: ${scalaBinaryVersion.value}")
|
||||
assert(crossV startsWith "1.0.", s"Wrong `sbtVersion in pluginCrossBuild`: $crossV")
|
||||
},
|
||||
|
||||
TaskKey[Unit]("check2") := {
|
||||
val crossV = (sbtVersion in pluginCrossBuild).value
|
||||
val sv = projectID.value.extraAttributes("e:scalaVersion")
|
||||
assert(sbtVersion.value startsWith baseSbt, s"Wrong sbt version: ${sbtVersion.value}")
|
||||
assert(sv == "2.10", s"Wrong e:scalaVersion: $sv")
|
||||
assert(scalaBinaryVersion.value == "2.10", s"Wrong Scala binary version: ${scalaBinaryVersion.value}")
|
||||
assert(crossV startsWith "0.13", s"Wrong `sbtVersion in pluginCrossBuild`: $crossV")
|
||||
}
|
||||
)
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
> check
|
||||
|
||||
> ^^0.13.15
|
||||
|
||||
> check2
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
lazy val root = (project in file("."))
|
||||
.settings(
|
||||
sbtPlugin := true,
|
||||
sbtVersion in pluginCrossBuild := "0.13.15",
|
||||
resolvers += Resolver.typesafeIvyRepo("releases")
|
||||
)
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
// folder mustn't be included
|
||||
trait B
|
||||
|
|
@ -0,0 +1 @@
|
|||
trait A
|
||||
|
|
@ -0,0 +1 @@
|
|||
trait B
|
||||
|
|
@ -0,0 +1 @@
|
|||
object Test extends A with B
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
// should fail because the project is building for
|
||||
// 0.13.15 where E is not included
|
||||
object ErrorTest extends E
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
> show pluginCrossBuild::sbtDependency
|
||||
> compile
|
||||
-> test:compile
|
||||
|
|
@ -1,11 +1,5 @@
|
|||
scriptedSettings
|
||||
|
||||
scriptedSbt := sbtVersion.value
|
||||
|
||||
sbtPlugin := true
|
||||
|
||||
sbtVersion in Global := "0.13.0-Beta2"
|
||||
|
||||
scalaVersion in Global := "2.10.2-RC2"
|
||||
|
||||
offline := true
|
||||
lazy val root = (project in file("."))
|
||||
.settings(
|
||||
sbtPlugin := true,
|
||||
resolvers += Resolver.typesafeIvyRepo("releases")
|
||||
)
|
||||
|
|
|
|||
|
|
@ -1,5 +1,7 @@
|
|||
# This tests that this sbt scripted plugin can launch the next one
|
||||
# It is currently disabled because there is no next plugin version
|
||||
# This tests that this sbt scripted plugin can launch the previous one
|
||||
|
||||
> ++2.10.6
|
||||
> ^^0.13.16-M1
|
||||
|
||||
$ copy-file changes/A.scala src/sbt-test/a/b/A.scala
|
||||
> scripted
|
||||
|
|
@ -9,6 +9,7 @@ import sbt.internal.util.complete.{ Parser, DefaultParsers }
|
|||
import sbt.internal.inc.classpath.ClasspathUtilities
|
||||
import sbt.internal.inc.ModuleUtilities
|
||||
import java.lang.reflect.Method
|
||||
import sbt.librarymanagement.CrossVersion.binarySbtVersion
|
||||
|
||||
object ScriptedPlugin extends AutoPlugin {
|
||||
override def requires = plugins.JvmPlugin
|
||||
|
|
@ -32,13 +33,23 @@ object ScriptedPlugin extends AutoPlugin {
|
|||
import autoImport._
|
||||
override lazy val projectSettings = Seq(
|
||||
ivyConfigurations ++= Seq(scriptedConf, scriptedLaunchConf),
|
||||
scriptedSbt := sbtVersion.value,
|
||||
scriptedSbt := (sbtVersion in pluginCrossBuild).value,
|
||||
sbtLauncher := getJars(scriptedLaunchConf).map(_.get.head).value,
|
||||
sbtTestDirectory := sourceDirectory.value / "sbt-test",
|
||||
libraryDependencies ++= Seq(
|
||||
"org.scala-sbt" %% "scripted-sbt" % scriptedSbt.value % scriptedConf.toString,
|
||||
"org.scala-sbt" % "sbt-launch" % scriptedSbt.value % scriptedLaunchConf.toString
|
||||
),
|
||||
libraryDependencies ++= {
|
||||
binarySbtVersion(scriptedSbt.value) match {
|
||||
case "0.13" =>
|
||||
Seq(
|
||||
"org.scala-sbt" % "scripted-sbt" % scriptedSbt.value % scriptedConf.toString,
|
||||
"org.scala-sbt" % "sbt-launch" % scriptedSbt.value % scriptedLaunchConf.toString
|
||||
)
|
||||
case sv if sv startsWith "1.0." =>
|
||||
Seq(
|
||||
"org.scala-sbt" %% "scripted-sbt" % scriptedSbt.value % scriptedConf.toString,
|
||||
"org.scala-sbt" % "sbt-launch" % scriptedSbt.value % scriptedLaunchConf.toString
|
||||
)
|
||||
}
|
||||
},
|
||||
scriptedBufferLog := true,
|
||||
scriptedClasspath := getJars(scriptedConf).value,
|
||||
scriptedTests := scriptedTestsTask.value,
|
||||
|
|
|
|||
Loading…
Reference in New Issue