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 {
|
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 case class Switch(version: ScalaVersion, verbose: Boolean, command: Option[String])
|
||||||
private trait ScalaVersion {
|
private trait ScalaVersion {
|
||||||
|
|
@ -77,7 +77,7 @@ object Cross {
|
||||||
private def crossRestoreSessionParser(state: State): Parser[String] =
|
private def crossRestoreSessionParser(state: State): Parser[String] =
|
||||||
token(CrossRestoreSessionCommand)
|
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)
|
s => if (s get sessionSettings isEmpty) failure("No project loaded") else p(s)
|
||||||
|
|
||||||
private def resolveAggregates(extracted: Extracted): Seq[ProjectRef] = {
|
private def resolveAggregates(extracted: Extracted): Seq[ProjectRef] = {
|
||||||
|
|
|
||||||
|
|
@ -218,6 +218,10 @@ object Defaults extends BuildCommon {
|
||||||
envVars :== Map.empty,
|
envVars :== Map.empty,
|
||||||
sbtVersion := appConfiguration.value.provider.id.version,
|
sbtVersion := appConfiguration.value.provider.id.version,
|
||||||
sbtBinaryVersion := binarySbtVersion(sbtVersion.value),
|
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,
|
watchingMessage := Watched.defaultWatchingMessage,
|
||||||
triggeredMessage := Watched.defaultTriggeredMessage,
|
triggeredMessage := Watched.defaultTriggeredMessage,
|
||||||
onLoad := idFun[State],
|
onLoad := idFun[State],
|
||||||
|
|
@ -293,10 +297,16 @@ object Defaults extends BuildCommon {
|
||||||
sourceManaged := configSrcSub(sourceManaged).value,
|
sourceManaged := configSrcSub(sourceManaged).value,
|
||||||
scalaSource := sourceDirectory.value / "scala",
|
scalaSource := sourceDirectory.value / "scala",
|
||||||
javaSource := sourceDirectory.value / "java",
|
javaSource := sourceDirectory.value / "java",
|
||||||
unmanagedSourceDirectories := makeCrossSources(scalaSource.value,
|
unmanagedSourceDirectories := {
|
||||||
javaSource.value,
|
makeCrossSources(scalaSource.value,
|
||||||
scalaBinaryVersion.value,
|
javaSource.value,
|
||||||
crossPaths.value),
|
scalaBinaryVersion.value,
|
||||||
|
crossPaths.value) ++
|
||||||
|
makePluginCrossSources(sbtPlugin.value,
|
||||||
|
scalaSource.value,
|
||||||
|
(sbtBinaryVersion in pluginCrossBuild).value,
|
||||||
|
crossPaths.value)
|
||||||
|
},
|
||||||
unmanagedSources := collectFiles(unmanagedSourceDirectories,
|
unmanagedSources := collectFiles(unmanagedSourceDirectories,
|
||||||
includeFilter in unmanagedSources,
|
includeFilter in unmanagedSources,
|
||||||
excludeFilter in unmanagedSources).value,
|
excludeFilter in unmanagedSources).value,
|
||||||
|
|
@ -349,9 +359,22 @@ object Defaults extends BuildCommon {
|
||||||
),
|
),
|
||||||
scalaInstance := scalaInstanceTask.value,
|
scalaInstance := scalaInstanceTask.value,
|
||||||
crossVersion := (if (crossPaths.value) CrossVersion.binary else Disabled()),
|
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,
|
crossTarget := makeCrossTarget(target.value,
|
||||||
scalaBinaryVersion.value,
|
scalaBinaryVersion.value,
|
||||||
sbtBinaryVersion.value,
|
(sbtBinaryVersion in pluginCrossBuild).value,
|
||||||
sbtPlugin.value,
|
sbtPlugin.value,
|
||||||
crossPaths.value),
|
crossPaths.value),
|
||||||
clean := {
|
clean := {
|
||||||
|
|
@ -359,6 +382,8 @@ object Defaults extends BuildCommon {
|
||||||
IvyActions.cleanCachedResolutionCache(ivyModule.value, streams.value.log)
|
IvyActions.cleanCachedResolutionCache(ivyModule.value, streams.value.log)
|
||||||
},
|
},
|
||||||
scalaCompilerBridgeSource := {
|
scalaCompilerBridgeSource := {
|
||||||
|
// This is a workaround for sbtVersion getting set to another value.
|
||||||
|
val sv = appConfiguration.value.provider.id.version
|
||||||
if (ScalaInstance.isDotty(scalaVersion.value))
|
if (ScalaInstance.isDotty(scalaVersion.value))
|
||||||
// Maintained at https://github.com/lampepfl/dotty/tree/master/sbt-bridge
|
// Maintained at https://github.com/lampepfl/dotty/tree/master/sbt-bridge
|
||||||
ModuleID(scalaOrganization.value, "dotty-sbt-bridge", scalaVersion.value)
|
ModuleID(scalaOrganization.value, "dotty-sbt-bridge", scalaVersion.value)
|
||||||
|
|
@ -382,6 +407,14 @@ object Defaults extends BuildCommon {
|
||||||
derive(scalaBinaryVersion := binaryScalaVersion(scalaVersion.value))
|
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,
|
def makeCrossSources(scalaSrcDir: File,
|
||||||
javaSrcDir: File,
|
javaSrcDir: File,
|
||||||
sv: String,
|
sv: String,
|
||||||
|
|
@ -392,6 +425,15 @@ object Defaults extends BuildCommon {
|
||||||
Seq(scalaSrcDir, javaSrcDir)
|
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 = {
|
def makeCrossTarget(t: File, sv: String, sbtv: String, plugin: Boolean, cross: Boolean): File = {
|
||||||
val scalaBase = if (cross) t / ("scala-" + sv) else t
|
val scalaBase = if (cross) t / ("scala-" + sv) else t
|
||||||
if (plugin) scalaBase / ("sbt-" + sbtv) else scalaBase
|
if (plugin) scalaBase / ("sbt-" + sbtv) else scalaBase
|
||||||
|
|
@ -1470,7 +1512,20 @@ object Defaults extends BuildCommon {
|
||||||
projectCore ++ disableAggregation ++ Seq(
|
projectCore ++ disableAggregation ++ Seq(
|
||||||
// Missing but core settings
|
// Missing but core settings
|
||||||
baseDirectory := thisProject.value.base,
|
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.
|
// 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[_]] =
|
lazy val deprecationSettings: Seq[Setting[_]] =
|
||||||
|
|
@ -1884,8 +1939,11 @@ object Classpaths {
|
||||||
allDependencies := {
|
allDependencies := {
|
||||||
val base = projectDependencies.value ++ libraryDependencies.value
|
val base = projectDependencies.value ++ libraryDependencies.value
|
||||||
val dependency = sbtDependency.value
|
val dependency = sbtDependency.value
|
||||||
|
val isPlugin = sbtPlugin.value
|
||||||
|
val sbtdeps =
|
||||||
|
(sbtDependency in pluginCrossBuild).value.withConfigurations(Some(Provided.name))
|
||||||
val pluginAdjust =
|
val pluginAdjust =
|
||||||
if (sbtPlugin.value) dependency.withConfigurations(Some(Provided.name)) +: base
|
if (isPlugin) sbtdeps +: base
|
||||||
else base
|
else base
|
||||||
val sbtOrg = scalaOrganization.value
|
val sbtOrg = scalaOrganization.value
|
||||||
val version = scalaVersion.value
|
val version = scalaVersion.value
|
||||||
|
|
@ -1919,8 +1977,8 @@ object Classpaths {
|
||||||
Def.setting {
|
Def.setting {
|
||||||
if (sbtPlugin.value)
|
if (sbtPlugin.value)
|
||||||
sbtPluginExtra(projectID.value,
|
sbtPluginExtra(projectID.value,
|
||||||
(sbtBinaryVersion in update).value,
|
(sbtBinaryVersion in pluginCrossBuild).value,
|
||||||
(scalaBinaryVersion in update).value)
|
(scalaBinaryVersion in pluginCrossBuild).value)
|
||||||
else projectID.value
|
else projectID.value
|
||||||
}
|
}
|
||||||
private[sbt] def ivySbt0: Initialize[Task[IvySbt]] =
|
private[sbt] def ivySbt0: Initialize[Task[IvySbt]] =
|
||||||
|
|
@ -1950,77 +2008,78 @@ object Classpaths {
|
||||||
transitiveClassifiers in updateSbtClassifiers ~= (_.filter(_ != DocClassifier))
|
transitiveClassifiers in updateSbtClassifiers ~= (_.filter(_ != DocClassifier))
|
||||||
))
|
))
|
||||||
def sbtClassifiersTasks =
|
def sbtClassifiersTasks =
|
||||||
sbtClassifiersGlobalDefaults ++ inTask(updateSbtClassifiers)(
|
sbtClassifiersGlobalDefaults ++
|
||||||
Seq(
|
inTask(updateSbtClassifiers)(
|
||||||
externalResolvers := {
|
Seq(
|
||||||
val explicit = buildStructure.value
|
externalResolvers := {
|
||||||
.units(thisProjectRef.value.build)
|
val explicit = buildStructure.value
|
||||||
.unit
|
.units(thisProjectRef.value.build)
|
||||||
.plugins
|
.unit
|
||||||
.pluginData
|
.plugins
|
||||||
.resolvers
|
.pluginData
|
||||||
explicit orElse bootRepositories(appConfiguration.value) getOrElse externalResolvers.value
|
.resolvers
|
||||||
},
|
explicit orElse bootRepositories(appConfiguration.value) getOrElse externalResolvers.value
|
||||||
ivyConfiguration := new InlineIvyConfiguration(
|
},
|
||||||
ivyPaths.value,
|
ivyConfiguration := new InlineIvyConfiguration(
|
||||||
externalResolvers.value.toVector,
|
ivyPaths.value,
|
||||||
Vector.empty,
|
externalResolvers.value.toVector,
|
||||||
Vector.empty,
|
Vector.empty,
|
||||||
offline.value,
|
Vector.empty,
|
||||||
Option(lock(appConfiguration.value)),
|
offline.value,
|
||||||
checksums.value.toVector,
|
Option(lock(appConfiguration.value)),
|
||||||
Some(target.value / "resolution-cache"),
|
checksums.value.toVector,
|
||||||
UpdateOptions(),
|
Some(crossTarget.value / "resolution-cache"),
|
||||||
streams.value.log
|
UpdateOptions(),
|
||||||
),
|
streams.value.log
|
||||||
ivySbt := ivySbt0.value,
|
),
|
||||||
classifiersModule := classifiersModuleTask.value,
|
ivySbt := ivySbt0.value,
|
||||||
// Redefine scalaVersion and scalaBinaryVersion specifically for the dependency graph used for updateSbtClassifiers task.
|
classifiersModule := classifiersModuleTask.value,
|
||||||
// to fix https://github.com/sbt/sbt/issues/2686
|
// Redefine scalaVersion and scalaBinaryVersion specifically for the dependency graph used for updateSbtClassifiers task.
|
||||||
scalaVersion := appConfiguration.value.provider.scalaProvider.version,
|
// to fix https://github.com/sbt/sbt/issues/2686
|
||||||
scalaBinaryVersion := binaryScalaVersion(scalaVersion.value),
|
scalaVersion := appConfiguration.value.provider.scalaProvider.version,
|
||||||
ivyScala := {
|
scalaBinaryVersion := binaryScalaVersion(scalaVersion.value),
|
||||||
Some(
|
ivyScala := {
|
||||||
IvyScala(scalaVersion.value,
|
Some(
|
||||||
scalaBinaryVersion.value,
|
IvyScala(scalaVersion.value,
|
||||||
Vector(),
|
scalaBinaryVersion.value,
|
||||||
checkExplicit = false,
|
Vector(),
|
||||||
filterImplicit = false,
|
checkExplicit = false,
|
||||||
overrideScalaVersion = true).withScalaOrganization(scalaOrganization.value))
|
filterImplicit = false,
|
||||||
},
|
overrideScalaVersion = true).withScalaOrganization(scalaOrganization.value))
|
||||||
updateSbtClassifiers in TaskGlobal := (Def.task {
|
},
|
||||||
val s = streams.value
|
updateSbtClassifiers in TaskGlobal := (Def.task {
|
||||||
val is = ivySbt.value
|
val s = streams.value
|
||||||
val mod = classifiersModule.value
|
val is = ivySbt.value
|
||||||
val c = updateConfiguration.value
|
val mod = classifiersModule.value
|
||||||
val app = appConfiguration.value
|
val c = updateConfiguration.value
|
||||||
val srcTypes = sourceArtifactTypes.value
|
val app = appConfiguration.value
|
||||||
val docTypes = docArtifactTypes.value
|
val srcTypes = sourceArtifactTypes.value
|
||||||
val log = s.log
|
val docTypes = docArtifactTypes.value
|
||||||
val out = is.withIvy(log)(_.getSettings.getDefaultIvyUserDir)
|
val log = s.log
|
||||||
val uwConfig = (unresolvedWarningConfiguration in update).value
|
val out = is.withIvy(log)(_.getSettings.getDefaultIvyUserDir)
|
||||||
val depDir = dependencyCacheDirectory.value
|
val uwConfig = (unresolvedWarningConfiguration in update).value
|
||||||
val ivy = ivyScala.value
|
val depDir = dependencyCacheDirectory.value
|
||||||
val st = state.value
|
val ivy = ivyScala.value
|
||||||
withExcludes(out, mod.classifiers, lock(app)) { excludes =>
|
val st = state.value
|
||||||
val noExplicitCheck = ivy.map(_.withCheckExplicit(false))
|
withExcludes(out, mod.classifiers, lock(app)) { excludes =>
|
||||||
IvyActions.transitiveScratch(
|
val noExplicitCheck = ivy.map(_.withCheckExplicit(false))
|
||||||
is,
|
IvyActions.transitiveScratch(
|
||||||
"sbt",
|
is,
|
||||||
GetClassifiersConfiguration(mod,
|
"sbt",
|
||||||
excludes,
|
GetClassifiersConfiguration(mod,
|
||||||
c.withArtifactFilter(c.artifactFilter.invert),
|
excludes,
|
||||||
noExplicitCheck,
|
c.withArtifactFilter(c.artifactFilter.invert),
|
||||||
srcTypes,
|
noExplicitCheck,
|
||||||
docTypes),
|
srcTypes,
|
||||||
uwConfig,
|
docTypes),
|
||||||
LogicalClock(st.hashCode),
|
uwConfig,
|
||||||
Some(depDir),
|
LogicalClock(st.hashCode),
|
||||||
log
|
Some(depDir),
|
||||||
)
|
log
|
||||||
}
|
)
|
||||||
} tag (Tags.Update, Tags.Network)).value
|
}
|
||||||
)) ++ Seq(bootIvyConfiguration := (ivyConfiguration in updateSbtClassifiers).value)
|
} tag (Tags.Update, Tags.Network)).value
|
||||||
|
)) ++ Seq(bootIvyConfiguration := (ivyConfiguration in updateSbtClassifiers).value)
|
||||||
|
|
||||||
def classifiersModuleTask: Initialize[Task[GetClassifiersModule]] =
|
def classifiersModuleTask: Initialize[Task[GetClassifiersModule]] =
|
||||||
Def.task {
|
Def.task {
|
||||||
|
|
@ -2433,7 +2492,7 @@ object Classpaths {
|
||||||
val (rs, other) = (fullResolvers.value.toVector, otherResolvers.value.toVector)
|
val (rs, other) = (fullResolvers.value.toVector, otherResolvers.value.toVector)
|
||||||
val s = streams.value
|
val s = streams.value
|
||||||
warnResolversConflict(rs ++: other, s.log)
|
warnResolversConflict(rs ++: other, s.log)
|
||||||
val resCacheDir = target.value / "resolution-cache"
|
val resCacheDir = crossTarget.value / "resolution-cache"
|
||||||
new InlineIvyConfiguration(
|
new InlineIvyConfiguration(
|
||||||
ivyPaths.value,
|
ivyPaths.value,
|
||||||
rs,
|
rs,
|
||||||
|
|
|
||||||
|
|
@ -201,6 +201,8 @@ object Keys {
|
||||||
val classpathOptions = SettingKey[ClasspathOptions]("classpath-options", "Configures handling of Scala classpaths.", DSetting)
|
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 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 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 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 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)
|
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] =
|
def ConsoleCommands: Seq[Command] =
|
||||||
Seq(ignore, exit, IvyConsole.command, setLogLevel, early, act, nop)
|
Seq(ignore, exit, IvyConsole.command, setLogLevel, early, act, nop)
|
||||||
|
|
||||||
def ScriptCommands: Seq[Command] =
|
def ScriptCommands: Seq[Command] =
|
||||||
Seq(ignore, exit, Script.command, setLogLevel, early, act, nop)
|
Seq(ignore, exit, Script.command, setLogLevel, early, act, nop)
|
||||||
|
|
||||||
|
|
@ -175,6 +176,8 @@ object BuiltinCommands {
|
||||||
loadFailed,
|
loadFailed,
|
||||||
Cross.crossBuild,
|
Cross.crossBuild,
|
||||||
Cross.switchVersion,
|
Cross.switchVersion,
|
||||||
|
PluginCross.pluginCross,
|
||||||
|
PluginCross.pluginSwitch,
|
||||||
Cross.crossRestoreSession,
|
Cross.crossRestoreSession,
|
||||||
setOnFailure,
|
setOnFailure,
|
||||||
clearOnFailure,
|
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`
|
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
|
autoScalaLibrary := false
|
||||||
|
|
||||||
|
crossPaths := false
|
||||||
|
|
||||||
TaskKey[Unit]("check-last-update-time") := (streams map { (s) =>
|
TaskKey[Unit]("check-last-update-time") := (streams map { (s) =>
|
||||||
val fullUpdateOutput = s.cacheDirectory / "out"
|
val fullUpdateOutput = s.cacheDirectory / "out"
|
||||||
val timeDiff = System.currentTimeMillis()-fullUpdateOutput.lastModified()
|
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
|
lazy val root = (project in file("."))
|
||||||
|
.settings(
|
||||||
scriptedSbt := sbtVersion.value
|
sbtPlugin := true,
|
||||||
|
resolvers += Resolver.typesafeIvyRepo("releases")
|
||||||
sbtPlugin := true
|
)
|
||||||
|
|
||||||
sbtVersion in Global := "0.13.0-Beta2"
|
|
||||||
|
|
||||||
scalaVersion in Global := "2.10.2-RC2"
|
|
||||||
|
|
||||||
offline := true
|
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,7 @@
|
||||||
# This tests that this sbt scripted plugin can launch the next one
|
# This tests that this sbt scripted plugin can launch the previous one
|
||||||
# It is currently disabled because there is no next plugin version
|
|
||||||
|
> ++2.10.6
|
||||||
|
> ^^0.13.16-M1
|
||||||
|
|
||||||
$ copy-file changes/A.scala src/sbt-test/a/b/A.scala
|
$ copy-file changes/A.scala src/sbt-test/a/b/A.scala
|
||||||
> scripted
|
> scripted
|
||||||
|
|
@ -9,6 +9,7 @@ import sbt.internal.util.complete.{ Parser, DefaultParsers }
|
||||||
import sbt.internal.inc.classpath.ClasspathUtilities
|
import sbt.internal.inc.classpath.ClasspathUtilities
|
||||||
import sbt.internal.inc.ModuleUtilities
|
import sbt.internal.inc.ModuleUtilities
|
||||||
import java.lang.reflect.Method
|
import java.lang.reflect.Method
|
||||||
|
import sbt.librarymanagement.CrossVersion.binarySbtVersion
|
||||||
|
|
||||||
object ScriptedPlugin extends AutoPlugin {
|
object ScriptedPlugin extends AutoPlugin {
|
||||||
override def requires = plugins.JvmPlugin
|
override def requires = plugins.JvmPlugin
|
||||||
|
|
@ -32,13 +33,23 @@ object ScriptedPlugin extends AutoPlugin {
|
||||||
import autoImport._
|
import autoImport._
|
||||||
override lazy val projectSettings = Seq(
|
override lazy val projectSettings = Seq(
|
||||||
ivyConfigurations ++= Seq(scriptedConf, scriptedLaunchConf),
|
ivyConfigurations ++= Seq(scriptedConf, scriptedLaunchConf),
|
||||||
scriptedSbt := sbtVersion.value,
|
scriptedSbt := (sbtVersion in pluginCrossBuild).value,
|
||||||
sbtLauncher := getJars(scriptedLaunchConf).map(_.get.head).value,
|
sbtLauncher := getJars(scriptedLaunchConf).map(_.get.head).value,
|
||||||
sbtTestDirectory := sourceDirectory.value / "sbt-test",
|
sbtTestDirectory := sourceDirectory.value / "sbt-test",
|
||||||
libraryDependencies ++= Seq(
|
libraryDependencies ++= {
|
||||||
"org.scala-sbt" %% "scripted-sbt" % scriptedSbt.value % scriptedConf.toString,
|
binarySbtVersion(scriptedSbt.value) match {
|
||||||
"org.scala-sbt" % "sbt-launch" % scriptedSbt.value % scriptedLaunchConf.toString
|
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,
|
scriptedBufferLog := true,
|
||||||
scriptedClasspath := getJars(scriptedConf).value,
|
scriptedClasspath := getJars(scriptedConf).value,
|
||||||
scriptedTests := scriptedTestsTask.value,
|
scriptedTests := scriptedTestsTask.value,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue