Split Defaults.scala into three plugins: Global,Ivy,Jvm.

* GlobalPlugin has defaults for controlling parallelism on tasks, basic command stuff.
* IvyModule has the configuration for resolving/publishing modules to ivy, assuming
  each project is a single module.
* JvmModule has the configuration for compiling/running/testing/packaging Java/Scala
  projects.
This commit is contained in:
Josh Suereth 2014-03-05 17:43:49 -05:00
parent a44a14f2c8
commit 3576baa76c
7 changed files with 218 additions and 82 deletions

View File

@ -12,6 +12,7 @@ trait Build
{
def projectDefinitions(baseDirectory: File): Seq[Project] = projects
def projects: Seq[Project] = ReflectUtilities.allVals[Project](this).values.toSeq
// TODO: Should we grab the build core setting shere or in a plugin?
def settings: Seq[Setting[_]] = Defaults.buildCore
def buildLoaders: Seq[BuildLoader.Components] = Nil
/** Explicitly defines the root project.
@ -46,8 +47,16 @@ object Build
@deprecated("Explicitly specify the ID", "0.13.0")
def defaultProject(base: File): Project = defaultProject(defaultID(base), base)
def defaultProject(id: String, base: File): Project = Project(id, base).settings(
// TODO - Can we move this somewhere else? ordering of settings is causing this to get borked.
// if the user has overridden the name, use the normal organization that is derived from the name.
organization <<= (thisProject, organization, name) { (p, o, n) => if(p.id == n) "default" else o }
organization := {
val overridden = thisProject.value.id == name.value
organization.?.value match {
case Some(o) if !overridden => o
case _ => "default"
}
//(thisProject, organization, name) { (p, o, n) => if(p.id == n) "default" else o }
}
)
def defaultAggregatedProject(id: String, base: File, agg: Seq[ProjectRef]): Project =
defaultProject(id, base).aggregate(agg : _*)

View File

@ -56,94 +56,107 @@ object Defaults extends BuildCommon
def thisBuildCore: Seq[Setting[_]] = inScope(GlobalScope.copy(project = Select(ThisBuild)))(Seq(
managedDirectory := baseDirectory.value / "lib_managed"
))
@deprecated("0.13.2", "Use AutoPlugins and globalSbtCore instead.")
lazy val globalCore: Seq[Setting[_]] = globalDefaults(defaultTestTasks(test) ++ defaultTestTasks(testOnly) ++ defaultTestTasks(testQuick) ++ Seq(
excludeFilter :== HiddenFileFilter
) ++ globalIvyCore ++ globalJvmCore) ++ globalSbtCore
private[sbt] lazy val globalJvmCore: Seq[Setting[_]] =
Seq(
compilerCache := state.value get Keys.stateCompilerCache getOrElse compiler.CompilerCache.fresh,
crossVersion :== CrossVersion.Disabled,
sourcesInBase :== true,
autoAPIMappings := false,
apiMappings := Map.empty,
autoScalaLibrary :== true,
managedScalaInstance :== true,
definesClass :== FileValueCache(Locate.definesClass _ ).get,
traceLevel in run :== 0,
traceLevel in runMain :== 0,
traceLevel in console :== Int.MaxValue,
traceLevel in consoleProject :== Int.MaxValue,
autoCompilerPlugins :== true,
scalaHome :== None,
apiURL := None,
javaHome :== None,
testForkedParallel :== false,
javaOptions :== Nil,
sbtPlugin :== false,
crossPaths :== true,
sourcePositionMappers :== Nil,
artifactClassifier in packageSrc :== Some(SourceClassifier),
artifactClassifier in packageDoc :== Some(DocClassifier),
includeFilter :== NothingFilter,
includeFilter in unmanagedSources :== "*.java" | "*.scala",
includeFilter in unmanagedJars :== "*.jar" | "*.so" | "*.dll" | "*.jnilib" | "*.zip",
includeFilter in unmanagedResources :== AllPassFilter
)
private[sbt] lazy val globalIvyCore: Seq[Setting[_]] =
Seq(
internalConfigurationMap :== Configurations.internalMap _,
credentials :== Nil,
exportJars :== false,
retrieveManaged :== false,
scalaOrganization :== ScalaArtifacts.Organization,
sbtResolver := { if(sbtVersion.value endsWith "-SNAPSHOT") Classpaths.typesafeSnapshots else Classpaths.typesafeReleases },
crossVersion :== CrossVersion.Disabled,
buildDependencies <<= Classpaths.constructBuildDependencies,
version :== "0.1-SNAPSHOT",
classpathTypes :== Set("jar", "bundle") ++ CustomPomParser.JarPackagings,
artifactClassifier :== None,
checksums := Classpaths.bootChecksums(appConfiguration.value),
conflictManager := ConflictManager.default,
pomExtra :== NodeSeq.Empty,
pomPostProcess :== idFun,
pomAllRepositories :== false,
pomIncludeRepository :== Classpaths.defaultRepositoryFilter
)
/** Core non-plugin settings for sbt builds. These *must* be on every build or the sbt engine will fail to run at all. */
private[sbt] lazy val globalSbtCore: Seq[Setting[_]] = globalDefaults(Seq(
outputStrategy :== None, // TODO - This might belong elsewhere.
buildStructure := Project.structure(state.value),
settingsData := buildStructure.value.data,
trapExit :== true,
connectInput :== false,
cancelable :== false,
envVars :== Map.empty,
sbtVersion := appConfiguration.value.provider.id.version,
sbtBinaryVersion := binarySbtVersion(sbtVersion.value),
watchingMessage := Watched.defaultWatchingMessage,
triggeredMessage := Watched.defaultTriggeredMessage,
onLoad := idFun[State],
onUnload := idFun[State],
onUnload := { s => try onUnload.value(s) finally IO.delete(taskTemporaryDirectory.value) },
extraLoggers :== { _ => Nil },
watchSources :== Nil,
skip :== false,
taskTemporaryDirectory := { val dir = IO.createTemporaryDirectory; dir.deleteOnExit(); dir },
onComplete := { val dir = taskTemporaryDirectory.value; () => {IO.delete(dir); IO.createDirectory(dir) }},
Previous.cache <<= Previous.cacheSetting,
Previous.references :== new Previous.References,
concurrentRestrictions <<= defaultRestrictions,
parallelExecution :== true,
sbtVersion := appConfiguration.value.provider.id.version,
sbtBinaryVersion := binarySbtVersion(sbtVersion.value),
sbtResolver := { if(sbtVersion.value endsWith "-SNAPSHOT") Classpaths.typesafeSnapshots else Classpaths.typesafeReleases },
pollInterval :== 500,
logBuffered :== false,
connectInput :== false,
cancelable :== false,
envVars :== Map.empty,
sourcesInBase :== true,
autoAPIMappings := false,
apiMappings := Map.empty,
autoScalaLibrary :== true,
managedScalaInstance :== true,
onLoad := idFun[State],
onUnload := idFun[State],
onUnload := { s => try onUnload.value(s) finally IO.delete(taskTemporaryDirectory.value) },
watchingMessage := Watched.defaultWatchingMessage,
triggeredMessage := Watched.defaultTriggeredMessage,
definesClass :== FileValueCache(Locate.definesClass _ ).get,
trapExit :== true,
traceLevel in run :== 0,
traceLevel in runMain :== 0,
traceLevel in console :== Int.MaxValue,
traceLevel in consoleProject :== Int.MaxValue,
autoCompilerPlugins :== true,
internalConfigurationMap :== Configurations.internalMap _,
initialize :== {},
credentials :== Nil,
scalaHome :== None,
apiURL := None,
javaHome :== None,
extraLoggers :== { _ => Nil },
skip :== false,
watchSources :== Nil,
version :== "0.1-SNAPSHOT",
outputStrategy :== None,
exportJars :== false,
fork :== false,
testForkedParallel :== false,
javaOptions :== Nil,
sbtPlugin :== false,
crossPaths :== true,
classpathTypes :== Set("jar", "bundle") ++ CustomPomParser.JarPackagings,
aggregate :== true,
maxErrors :== 100,
sourcePositionMappers :== Nil,
commands :== Nil,
showSuccess :== true,
showTiming :== true,
timingFormat :== Aggregation.defaultFormat,
showSuccess :== true,
commands :== Nil,
retrieveManaged :== false,
buildStructure := Project.structure(state.value),
settingsData := buildStructure.value.data,
artifactClassifier :== None,
artifactClassifier in packageSrc :== Some(SourceClassifier),
artifactClassifier in packageDoc :== Some(DocClassifier),
checksums := Classpaths.bootChecksums(appConfiguration.value),
conflictManager := ConflictManager.default,
pomExtra :== NodeSeq.Empty,
pomPostProcess :== idFun,
pomAllRepositories :== false,
includeFilter :== NothingFilter,
includeFilter in unmanagedSources :== "*.java" | "*.scala",
includeFilter in unmanagedJars :== "*.jar" | "*.so" | "*.dll" | "*.jnilib" | "*.zip",
includeFilter in unmanagedResources :== AllPassFilter,
excludeFilter :== HiddenFileFilter,
pomIncludeRepository :== Classpaths.defaultRepositoryFilter
aggregate :== true,
maxErrors :== 100,
fork :== false,
initialize :== {}
))
def defaultTestTasks(key: Scoped): Seq[Setting[_]] = inTask(key)(Seq(
tags := Seq(Tags.Test -> 1),
logBuffered := true
))
// TODO: This should be on the new default settings for a project.
def projectCore: Seq[Setting[_]] = Seq(
name := thisProject.value.id,
logManager := LogManager.defaults(extraLoggers.value, StandardMain.console),
onLoadMessage <<= onLoadMessage or (name, thisProjectRef)("Set current project to " + _ + " (in build " + _.build +")"),
runnerTask
onLoadMessage <<= onLoadMessage or (name, thisProjectRef)("Set current project to " + _ + " (in build " + _.build +")")
)
def paths = Seq(
baseDirectory := thisProject.value.base,
@ -852,6 +865,7 @@ object Defaults extends BuildCommon
lazy val disableAggregation = Defaults.globalDefaults( noAggregation map disableAggregate )
def disableAggregate(k: Scoped) = aggregate in k :== false
lazy val runnerSettings: Seq[Setting[_]] = Seq(runnerTask)
lazy val baseTasks: Seq[Setting[_]] = projectTasks ++ packageBase
lazy val baseClasspaths: Seq[Setting[_]] = Classpaths.publishSettings ++ Classpaths.baseSettings
@ -865,7 +879,12 @@ object Defaults extends BuildCommon
// settings that are not specific to a configuration
lazy val projectBaseSettings: Seq[Setting[_]] = projectCore ++ paths ++ baseClasspaths ++ baseTasks ++ compileBase ++ disableAggregation
@deprecated("0.13.2", "Settings now split into AutoPlugins.")
lazy val projectBaseSettings: Seq[Setting[_]] = projectCore ++ runnerSettings ++ paths ++ baseClasspaths ++ baseTasks ++ compileBase ++ disableAggregation
// These are project level settings that MUST be on every project.
lazy val coreDefaultSettings: Seq[Setting[_]] = projectCore ++ disableAggregation
@deprecated("0.13.2", "Default settings split into `coreDefaultSettings` and IvyModule/JvmModule plugins.")
lazy val defaultSettings: Seq[Setting[_]] = projectBaseSettings ++ defaultConfigs
}
object Classpaths
@ -935,9 +954,14 @@ object Classpaths
publishArtifact in Test:== false
))
val publishSettings: Seq[Setting[_]] = publishGlobalDefaults ++ Seq(
artifacts <<= artifactDefs(defaultArtifactTasks),
packagedArtifacts <<= packaged(defaultArtifactTasks),
val jvmPublishSettings: Seq[Setting[_]] = Seq(
artifacts <<= artifactDefs(defaultArtifactTasks),
packagedArtifacts <<= packaged(defaultArtifactTasks)
)
val ivyPublishSettings: Seq[Setting[_]] = publishGlobalDefaults ++ Seq(
artifacts :== Nil,
packagedArtifacts :== Map.empty,
makePom := { val config = makePomConfiguration.value; IvyActions.makePom(ivyModule.value, config, streams.value.log); config.file },
packagedArtifact in makePom := (artifact in makePom value, makePom value),
deliver <<= deliverTask(deliverConfiguration),
@ -946,6 +970,8 @@ object Classpaths
publishLocal <<= publishTask(publishLocalConfiguration, deliverLocal),
publishM2 <<= publishTask(publishM2Configuration, deliverLocal)
)
@deprecated("0.13.2", "This has been split into jvmIvySettings and ivyPublishSettings.")
val publishSettings: Seq[Setting[_]] = jvmPublishSettings ++ ivyPublishSettings
private[this] def baseGlobalDefaults = Defaults.globalDefaults(Seq(
conflictWarning :== ConflictWarning.default("global"),
@ -976,7 +1002,7 @@ object Classpaths
}
))
val baseSettings: Seq[Setting[_]] = baseGlobalDefaults ++ sbtClassifiersTasks ++ Seq(
val ivyBaseSettings: Seq[Setting[_]] = baseGlobalDefaults ++ sbtClassifiersTasks ++ Seq(
conflictWarning := conflictWarning.value.copy(label = Reference.display(thisProjectRef.value)),
unmanagedBase := baseDirectory.value / "lib",
normalizedName := Project.normalizeModuleID(name.value),
@ -1007,14 +1033,11 @@ object Classpaths
otherResolvers := Resolver.publishMavenLocal :: publishTo.value.toList,
projectResolver <<= projectResolverTask,
projectDependencies <<= projectDependenciesTask,
libraryDependencies ++= autoLibraryDependency(autoScalaLibrary.value && !scalaHome.value.isDefined && managedScalaInstance.value, sbtPlugin.value, scalaOrganization.value, scalaVersion.value),
// TODO - Is this the appropriate split? Ivy defines this simply as
// just project + library, while the JVM plugin will define it as
// having the additional sbtPlugin + autoScala magikz.
allDependencies := {
val base = projectDependencies.value ++ libraryDependencies.value
val pluginAdjust = if(sbtPlugin.value) sbtDependency.value.copy(configurations = Some(Provided.name)) +: base else base
if(scalaHome.value.isDefined || ivyScala.value.isEmpty || !managedScalaInstance.value)
pluginAdjust
else
ScalaArtifacts.toolDependencies(scalaOrganization.value, scalaVersion.value) ++ pluginAdjust
projectDependencies.value ++ libraryDependencies.value
},
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 = false, scalaOrganization = so))
@ -1054,6 +1077,22 @@ object Classpaths
}
} tag(Tags.Update, Tags.Network)
)
val jvmBaseSettings: Seq[Setting[_]] = Seq(
libraryDependencies ++= autoLibraryDependency(autoScalaLibrary.value && !scalaHome.value.isDefined && managedScalaInstance.value, sbtPlugin.value, scalaOrganization.value, scalaVersion.value),
// Override the default to handle mixing in the sbtPlugin + scala dependencies.
allDependencies := {
val base = projectDependencies.value ++ libraryDependencies.value
val pluginAdjust = if(sbtPlugin.value) sbtDependency.value.copy(configurations = Some(Provided.name)) +: base else base
if(scalaHome.value.isDefined || ivyScala.value.isEmpty || !managedScalaInstance.value)
pluginAdjust
else
ScalaArtifacts.toolDependencies(scalaOrganization.value, scalaVersion.value) ++ pluginAdjust
}
)
@deprecated("0.13.2", "Split into ivyBaseSettings and jvmBaseSettings.")
val baseSettings: Seq[Setting[_]] = ivyBaseSettings ++ jvmBaseSettings
def warnResolversConflict(ress: Seq[Resolver], log: Logger) {
val resset = ress.toSet
for ((name, r) <- resset groupBy (_.name) if r.size > 1) {

View File

@ -28,7 +28,15 @@ object PluginDiscovery
def discover[T](resource: String)(implicit mf: reflect.ClassManifest[T]) =
binarySourceModules[T](data, loader, resource)
import Paths._
new DetectedPlugins(discover[Plugin](Plugins), discover[AutoImport](AutoImports), discover[AutoPlugin](AutoPlugins), discover[Build](Builds))
// TODO - Fix this once we can autodetect AutoPlugins defined by sbt itself.
val defaultAutoPlugins = Seq(
"sbt.plugins.IvyModule" -> sbt.plugins.IvyModule,
"sbt.plugins.JvmModule" -> sbt.plugins.JvmModule,
"sbt.plugins.GlobalModule" -> sbt.plugins.GlobalModule
)
val detectedAutoPugins = discover[AutoPlugin](AutoPlugins)
val allAutoPlugins = new DetectedModules(defaultAutoPlugins ++ detectedAutoPugins.modules)
new DetectedPlugins(discover[Plugin](Plugins), discover[AutoImport](AutoImports), allAutoPlugins, discover[Build](Builds))
}
/** Discovers the sbt-plugin-related top-level modules from the provided source `analysis`. */

View File

@ -203,10 +203,11 @@ object Project extends ProjectExtra
}
// TODO: add parameter for plugins in 0.14.0
// TODO: Modify default settings to be the core settings, and automatically add the IvyModule + JvmPlugins.
def apply(id: String, base: File, aggregate: => Seq[ProjectReference] = Nil, dependencies: => Seq[ClasspathDep[ProjectReference]] = Nil,
delegates: => Seq[ProjectReference] = Nil, settings: => Seq[Def.Setting[_]] = defaultSettings, configurations: Seq[Configuration] = Configurations.default,
delegates: => Seq[ProjectReference] = Nil, settings: => Seq[Def.Setting[_]] = Nil, configurations: Seq[Configuration] = Nil,
auto: AddSettings = AddSettings.allDefaults): Project =
unresolved(id, base, aggregate, dependencies, delegates, settings, configurations, auto, Plugins.empty, Nil)
unresolved(id, base, aggregate, dependencies, delegates, settings, configurations, auto, Plugins.empty, Nil) // Note: JvmModule/IvyModule auto included...
/** Returns None if `id` is a valid Project ID or Some containing the parser error message if it is not.*/
def validProjectID(id: String): Option[String] = DefaultParsers.parse(id, DefaultParsers.ID).left.toOption
@ -243,6 +244,7 @@ object Project extends ProjectExtra
new ProjectDef[ProjectReference](id, base, aggregate, dependencies, delegates, settings, configurations, auto, plugins, autoPlugins) with Project
}
@deprecated("0.13.2", "Use Defaults.coreDefaultSettings instead, combined with AutoPlugins.")
def defaultSettings: Seq[Def.Setting[_]] = Defaults.defaultSettings
final class Constructor(p: ProjectReference) {

View File

@ -0,0 +1,19 @@
package sbt
package plugins
import Def.Setting
/**
* Plugin for core sbt-isms.
*
* Can control task-level paralleism, logging, etc.
*/
object GlobalModule extends AutoPlugin {
// We must be explicitly enabled
def select = Plugins.empty
override lazy val projectSettings: Seq[Setting[_]] =
Defaults.coreDefaultSettings
override lazy val globalSettings: Seq[Setting[_]] =
Defaults.globalSbtCore
}

View File

@ -0,0 +1,24 @@
package sbt
package plugins
import Def.Setting
/**
* Plugin that enables resolving artifacts via ivy.
*
* Core Tasks
* - `update`
* - `makePom`
* - `publish`
* - `artifacts`
* - `publishedArtifacts`
*/
object IvyModule extends AutoPlugin {
// We must be explicitly enabled
def select = GlobalModule
override lazy val projectSettings: Seq[Setting[_]] =
Classpaths.ivyPublishSettings ++ Classpaths.ivyBaseSettings
override lazy val globalSettings: Seq[Setting[_]] =
Defaults.globalIvyCore
}

View File

@ -0,0 +1,35 @@
package sbt
package plugins
import Def.Setting
/** A plugin representing the ability to build a JVM project.
*
* Core tasks/keys:
* - `run`
* - `test`
* - `compile`
* - `fullClasspath`
* Core configurations
* - `Test`
* - `Compile`
*/
object JvmModule extends AutoPlugin {
// We must be explicitly enabled
def select = IvyModule
override lazy val projectSettings: Seq[Setting[_]] =
Defaults.runnerSettings ++
Defaults.paths ++
Classpaths.jvmPublishSettings ++
Classpaths.jvmBaseSettings ++
Defaults.projectTasks ++
Defaults.packageBase ++
Defaults.compileBase ++
Defaults.defaultConfigs
override lazy val globalSettings: Seq[Setting[_]] =
Defaults.globalJvmCore
override def projectConfigurations: Seq[Configuration] =
Configurations.default
}