sbt/main/Defaults.scala

926 lines
46 KiB
Scala
Raw Normal View History

2011-02-06 03:40:10 +01:00
/* sbt -- Simple Build Tool
* Copyright 2011 Mark Harrah
*/
package sbt
import Build.data
import Scope.{fillTaskAxis, GlobalScope, ThisScope}
2011-03-02 12:46:28 +01:00
import compiler.Discovery
import Project.{inConfig, Initialize, inScope, inTask, ScopedKey, Setting, SettingsDefinition}
import Configurations.{Compile, CompilerPlugin, IntegrationTest, Runtime, Test}
import complete._
import std.TaskExtra._
import org.scalatools.testing.{AnnotatedFingerprint, SubclassFingerprint}
2011-03-14 02:34:17 +01:00
import scala.xml.{Node => XNode,NodeSeq}
import org.apache.ivy.core.module.{descriptor, id}
import descriptor.ModuleDescriptor, id.ModuleRevisionId
2011-03-14 02:34:17 +01:00
import java.io.File
import java.net.URL
2011-04-23 02:13:24 +02:00
import sbinary.DefaultProtocol.StringFormat
import Cache.seqFormat
2011-03-14 02:34:17 +01:00
import Types._
import Path._
import Keys._
2011-03-14 02:34:17 +01:00
object Defaults extends BuildCommon
2011-03-14 02:34:17 +01:00
{
def configSrcSub(key: ScopedSetting[File]): Initialize[File] = (key in ThisScope.copy(config = Global), configuration) { (src, conf) => src / nameForSrc(conf.name) }
def nameForSrc(config: String) = if(config == "compile") "main" else config
def prefix(config: String) = if(config == "compile") "" else config + "-"
def lock(app: xsbti.AppConfiguration): xsbti.GlobalLock = app.provider.scalaProvider.launcher.globalLock
2011-02-27 05:56:30 +01:00
def extractAnalysis[T](a: Attributed[T]): (T, inc.Analysis) =
2011-03-02 12:46:28 +01:00
(a.data, a.metadata get Keys.analysis getOrElse inc.Analysis.Empty)
2011-02-27 05:56:30 +01:00
def analysisMap[T](cp: Seq[Attributed[T]]): Map[T, inc.Analysis] =
(cp map extractAnalysis).toMap
def buildCore: Seq[Setting[_]] = thisBuildCore ++ globalCore
def thisBuildCore: Seq[Setting[_]] = inScope(GlobalScope.copy(project = Select(ThisBuild)))(Seq(
managedDirectory <<= baseDirectory(_ / "lib_managed")
))
def globalCore: Seq[Setting[_]] = inScope(GlobalScope)(Seq(
parallelExecution :== true,
2011-05-21 19:51:13 +02:00
sbtVersion in GlobalScope <<= appConfiguration { _.provider.id.version },
pollInterval :== 500,
logBuffered :== false,
trapExit :== false,
trapExit in run :== true,
logBuffered in testOnly :== true,
logBuffered in test :== true,
traceLevel in console :== Int.MaxValue,
traceLevel in consoleProject :== Int.MaxValue,
traceLevel in consoleQuick :== Int.MaxValue,
2011-04-12 04:12:03 +02:00
autoCompilerPlugins :== true,
internalConfigurationMap :== Configurations.internalMap _,
2011-04-05 00:23:51 +02:00
initialize :== (),
2011-04-06 00:44:47 +02:00
credentials :== Nil,
scalaHome :== None,
2011-03-02 12:46:28 +01:00
javaHome :== None,
version :== "0.1",
2011-03-02 12:46:28 +01:00
outputStrategy :== None,
fork :== false,
javaOptions :== Nil,
2011-03-14 02:34:17 +01:00
sbtPlugin :== false,
2011-03-02 12:46:28 +01:00
crossPaths :== true,
classpathTypes := Set("jar", "bundle"),
2011-03-02 12:46:28 +01:00
aggregate :== Aggregation.Enabled,
maxErrors :== 100,
showTiming :== true,
timingFormat :== Aggregation.defaultFormat,
showSuccess :== true,
2011-03-02 12:46:28 +01:00
commands :== Nil,
retrieveManaged :== false,
buildStructure <<= state map Project.structure,
settings <<= buildStructure map ( _.data ),
artifactClassifier :== None,
artifactClassifier in packageSrc :== Some(SourceClassifier),
artifactClassifier in packageDoc :== Some(DocClassifier),
checksums :== IvySbt.DefaultChecksums,
pomExtra := NodeSeq.Empty,
pomPostProcess := idFun,
pomIncludeRepository := Classpaths.defaultRepositoryFilter
2011-02-27 22:28:00 +01:00
))
def projectCore: Seq[Setting[_]] = Seq(
2011-03-02 12:46:28 +01:00
name <<= thisProject(_.id),
runnerSetting
)
def paths = Seq(
2011-03-02 12:46:28 +01:00
baseDirectory <<= thisProject(_.base),
target <<= baseDirectory / "target",
defaultExcludes in GlobalScope :== (".*" - ".") || HiddenFileFilter,
historyPath <<= target(t => Some(t / ".history")),
sourceDirectory <<= baseDirectory / "src",
sourceFilter in GlobalScope :== ("*.java" | "*.scala"),
sourceManaged <<= crossTarget / "src_managed",
resourceManaged <<= crossTarget / "resource_managed",
cacheDirectory <<= target / "cache"
)
lazy val configPaths = sourceConfigPaths ++ resourceConfigPaths ++ outputConfigPaths
lazy val sourceConfigPaths = Seq(
sourceDirectory <<= configSrcSub( sourceDirectory),
2011-03-02 12:46:28 +01:00
sourceManaged <<= configSrcSub(sourceManaged),
scalaSource <<= sourceDirectory / "scala",
javaSource <<= sourceDirectory / "java",
unmanagedSourceDirectories <<= Seq(scalaSource, javaSource).join,
unmanagedSources <<= collectFiles(unmanagedSourceDirectories, sourceFilter, defaultExcludes in unmanagedSources),
managedSourceDirectories <<= Seq(sourceManaged).join,
managedSources <<= generate(sourceGenerators),
sourceGenerators :== Nil,
sourceDirectories <<= Classpaths.concatSettings(unmanagedSourceDirectories, managedSourceDirectories),
sources <<= Classpaths.concat(unmanagedSources, managedSources)
)
lazy val resourceConfigPaths = Seq(
2011-03-02 12:46:28 +01:00
resourceDirectory <<= sourceDirectory / "resources",
resourceManaged <<= configSrcSub(resourceManaged),
unmanagedResourceDirectories <<= Seq(resourceDirectory).join,
managedResourceDirectories <<= Seq(resourceManaged).join,
resourceDirectories <<= Classpaths.concatSettings(unmanagedResourceDirectories, managedResourceDirectories),
unmanagedResources <<= (unmanagedResourceDirectories, defaultExcludes in unmanagedResources) map unmanagedResourcesTask,
resourceGenerators :== Nil,
resourceGenerators <+= (definedSbtPlugins, resourceManaged) map writePluginsDescriptor,
managedResources <<= generate(resourceGenerators),
resources <<= Classpaths.concat(managedResources, unmanagedResources)
)
lazy val outputConfigPaths = Seq(
cacheDirectory <<= (cacheDirectory, configuration) { _ / _.name },
classDirectory <<= (crossTarget, configuration) { (outDir, conf) => outDir / (prefix(conf.name) + "classes") },
docDirectory <<= (crossTarget, configuration) { (outDir, conf) => outDir / (prefix(conf.name) + "api") }
)
def addBaseSources = Seq(
unmanagedSources <<= (unmanagedSources, baseDirectory, sourceFilter, defaultExcludes in unmanagedSources) map {
2011-05-15 00:21:41 +02:00
(srcs,b,f,excl) => (srcs +++ b * (f -- excl)).get
}
)
def compileBase = Seq(
2011-03-08 23:50:19 +01:00
classpathOptions in GlobalScope :== ClasspathOptions.auto,
2011-04-04 03:15:35 +02:00
compileOrder in GlobalScope :== CompileOrder.Mixed,
compilers <<= (scalaInstance, appConfiguration, streams, classpathOptions, javaHome) map { (si, app, s, co, jh) => Compiler.compilers(si, co, jh)(app, s.log) },
2011-03-02 12:46:28 +01:00
javacOptions in GlobalScope :== Nil,
scalacOptions in GlobalScope :== Nil,
scalaInstance <<= scalaInstanceSetting,
scalaVersion in GlobalScope <<= appConfiguration( _.provider.scalaProvider.version),
2011-05-17 04:56:07 +02:00
crossScalaVersions in GlobalScope <<= Seq(scalaVersion).join,
crossTarget <<= (target, scalaInstance, crossPaths)( (t,si,cross) => if(cross) t / ("scala-" + si.actualVersion) else t ),
cacheDirectory <<= crossTarget / "cache"
2011-02-06 03:40:10 +01:00
)
2011-02-26 00:35:52 +01:00
lazy val configTasks = Seq(
2011-03-02 12:46:28 +01:00
initialCommands in GlobalScope :== "",
compile <<= compileTask,
compileInputs <<= compileInputsTask,
console <<= consoleTask,
consoleQuick <<= consoleQuickTask,
discoveredMainClasses <<= TaskData.write(compile map discoverMainClasses) triggeredBy compile,
2011-03-14 02:34:17 +01:00
definedSbtPlugins <<= discoverPlugins,
2011-03-02 12:46:28 +01:00
inTask(run)(runnerSetting :: Nil).head,
selectMainClass <<= discoveredMainClasses map selectRunMain,
mainClass in run <<= (selectMainClass in run).identity,
2011-03-02 12:46:28 +01:00
mainClass <<= discoveredMainClasses map selectPackageMain,
run <<= runTask(fullClasspath, mainClass in run, runner in run),
runMain <<= runMainTask(fullClasspath, runner in run),
scaladocOptions <<= scalacOptions.identity,
2011-03-02 12:46:28 +01:00
doc <<= docTask,
copyResources <<= copyResourcesTask
)
2011-02-26 00:35:52 +01:00
lazy val projectTasks: Seq[Setting[_]] = Seq(
cleanFiles <<= Seq(managedDirectory, target).join,
cleanKeepFiles <<= historyPath(_.toList),
clean <<= (cleanFiles, cleanKeepFiles) map doClean,
2011-03-02 12:46:28 +01:00
consoleProject <<= consoleProjectTask,
watchSources <<= watchSourcesTask,
watchTransitiveSources <<= watchTransitiveSourcesTask,
watch <<= watchSetting
2011-02-06 17:33:29 +01:00
)
def generate(generators: ScopedSetting[Seq[Task[Seq[File]]]]): Initialize[Task[Seq[File]]] = generators {_.join.map(_.flatten) }
2011-04-07 03:00:48 +02:00
def inAllConfigurations[T](key: ScopedTask[T]): Initialize[Task[Seq[T]]] = (state, thisProjectRef) flatMap { (state, ref) =>
2011-03-01 14:54:06 +01:00
val structure = Project structure state
val configurations = Project.getProject(ref, structure).toList.flatMap(_.configurations)
configurations.flatMap { conf =>
key in (ref, conf) get structure.data
} join
}
2011-03-02 12:46:28 +01:00
def watchTransitiveSourcesTask: Initialize[Task[Seq[File]]] =
2011-04-07 03:00:48 +02:00
(state, thisProjectRef) flatMap { (s, base) =>
2011-04-12 04:12:03 +02:00
inAllDependencies(base, watchSources.task, Project structure s).join.map(_.flatten)
2011-03-01 14:54:06 +01:00
}
def watchSourcesTask: Initialize[Task[Seq[File]]] =
Seq(unmanagedSources, unmanagedResources).map(inAllConfigurations).join { _.join.map(_.flatten.flatten.distinct) }
2011-03-01 14:54:06 +01:00
2011-03-02 12:46:28 +01:00
def watchSetting: Initialize[Watched] = (pollInterval, thisProjectRef) { (interval, base) =>
2011-03-01 14:54:06 +01:00
new Watched {
2011-03-02 12:46:28 +01:00
val scoped = watchTransitiveSources in base
2011-03-01 14:54:06 +01:00
val key = ScopedKey(scoped.scope, scoped.key)
override def pollInterval = interval
override def watchPaths(s: State) = EvaluateTask.evaluateTask(Project structure s, key, s, base) match {
case Some(Value(ps)) => ps
case Some(Inc(i)) => throw i
case None => error("key not found: " + Project.display(key))
}
2011-03-01 14:54:06 +01:00
}
}
def scalaInstanceSetting = (appConfiguration, scalaVersion, scalaHome){ (app, version, home) =>
val launcher = app.provider.scalaProvider.launcher
home match {
case None => ScalaInstance(version, launcher)
case Some(h) => ScalaInstance(h, launcher)
}
}
def unmanagedResourcesTask(dirs: Seq[File], excl: FileFilter) =
2011-05-15 00:21:41 +02:00
dirs.descendentsExcept("*",excl).get
2011-03-01 14:54:06 +01:00
lazy val testTasks = testTaskOptions(test) ++ testTaskOptions(testOnly) ++ Seq(
2011-03-02 12:46:28 +01:00
testLoader <<= (fullClasspath, scalaInstance) map { (cp, si) => TestFramework.createTestLoader(data(cp), si) },
testFrameworks in GlobalScope :== {
2011-02-06 17:33:29 +01:00
import sbt.TestFrameworks._
Seq(ScalaCheck, Specs, ScalaTest, ScalaCheckCompat, ScalaTestCompat, SpecsCompat, JUnit)
},
2011-03-02 12:46:28 +01:00
loadedTestFrameworks <<= (testFrameworks, streams, testLoader) map { (frameworks, s, loader) =>
2011-02-06 17:33:29 +01:00
frameworks.flatMap(f => f.create(loader, s.log).map( x => (f,x)).toIterable).toMap
},
definedTests <<= TaskData.writeRelated(detectTests)(_.map(_.name).distinct) triggeredBy compile,
testListeners in GlobalScope :== Nil,
testOptions in GlobalScope :== Nil,
executeTests <<= (streams in test, loadedTestFrameworks, parallelExecution in test, testOptions in test, testLoader, definedTests) flatMap {
(s, frameworkMap, par, options, loader, discovered) => Tests(frameworkMap, loader, discovered, options, par, s.log)
2011-02-06 17:33:29 +01:00
},
test <<= (executeTests, streams) map { (results, s) => Tests.showResults(s.log, results) },
2011-03-02 12:46:28 +01:00
testOnly <<= testOnlyTask
2011-02-06 03:40:10 +01:00
)
def testTaskOptions(key: Scoped): Seq[Setting[_]] = inTask(key)( Seq(
testListeners <<= (streams, resolvedScoped, streamsManager, logBuffered in key, testListeners) map { (s, sco, sm, buff, ls) =>
TestLogger(s.log, testLogger(sm, test in sco.scope), buff) +: ls
},
testOptions <<= (testOptions, testListeners) map { (options, ls) => Tests.Listeners(ls) +: options }
) )
def testLogger(manager: Streams, baseKey: Scoped)(tdef: TestDefinition): Logger =
{
val scope = baseKey.scope
val extra = scope.extra match { case Select(x) => x; case _ => AttributeMap.empty }
val key = ScopedKey(scope.copy(extra = Select(testExtra(extra, tdef))), baseKey.key)
manager(key).log
}
def buffered(log: Logger): Logger = new BufferedLogger(FullLogger(log))
def testExtra(extra: AttributeMap, tdef: TestDefinition): AttributeMap =
{
val mod = tdef.fingerprint match { case f: SubclassFingerprint => f.isModule; case f: AnnotatedFingerprint => f.isModule; case _ => false }
extra.put(name.key, tdef.name).put(isModule, mod)
}
2011-03-02 12:46:28 +01:00
def testOnlyTask =
2011-04-23 02:13:24 +02:00
InputTask( TaskData(definedTests)(testOnlyParser)(Nil) ) { result =>
(streams, loadedTestFrameworks, parallelExecution in testOnly, testOptions in testOnly, testLoader, definedTests, result) flatMap {
case (s, frameworks, par, opts, loader, discovered, (tests, frameworkOptions)) =>
val modifiedOpts = Tests.Filter(if(tests.isEmpty) _ => true else tests.toSet ) +: Tests.Argument(frameworkOptions : _*) +: opts
Tests(frameworks, loader, discovered, modifiedOpts, par, s.log) map { results =>
Tests.showResults(s.log, results)
}
}
2011-04-23 02:13:24 +02:00
}
def detectTests: Initialize[Task[Seq[TestDefinition]]] = (loadedTestFrameworks, compile, streams) map { (frameworkMap, analysis, s) =>
Tests.discover(frameworkMap.values.toSeq, analysis, s.log)._1
}
2011-03-14 02:34:17 +01:00
2011-02-10 14:16:07 +01:00
lazy val packageBase = Seq(
2011-05-08 04:02:05 +02:00
artifact <<= normalizedName(n => Artifact(n)),
2011-03-02 12:46:28 +01:00
packageOptions in GlobalScope :== Nil,
artifactName in GlobalScope :== ( Artifact.artifactName _ )
2011-02-10 14:16:07 +01:00
)
lazy val packageConfig = Seq(
2011-03-02 12:46:28 +01:00
packageOptions in packageBin <<= (packageOptions, mainClass in packageBin) map { _ ++ _.map(Package.MainClass.apply).toList }
2011-02-10 14:16:07 +01:00
) ++
packageTasks(packageBin, packageBinTask) ++
packageTasks(packageSrc, packageSrcTask) ++
packageTasks(packageDoc, packageDocTask)
final val SourceClassifier = "sources"
final val DocClassifier = "javadoc"
2011-02-10 14:16:07 +01:00
private[this] val allSubpaths = (dir: File) => (dir.*** --- dir) x (relativeTo(dir)|flat)
2011-02-10 14:16:07 +01:00
def packageBinTask = classMappings
2011-03-02 12:46:28 +01:00
def packageDocTask = doc map allSubpaths
def packageSrcTask = concatMappings(resourceMappings, sourceMappings)
private type Mappings = Initialize[Task[Seq[(File, String)]]]
def concatMappings(as: Mappings, bs: Mappings) = (as zipWith bs)( (a,b) => (a :^: b :^: KNil) map { case a :+: b :+: HNil => a ++ b } )
def classMappings = (compileInputs, products) map { (in, _) => allSubpaths(in.config.classesDirectory) }
// drop base directories, since there are no valid mappings for these
def sourceMappings = (unmanagedSources, unmanagedSourceDirectories, baseDirectory) map { (srcs, sdirs, base) =>
( (srcs --- sdirs --- base) x (relativeTo(sdirs)|relativeTo(base)|flat)) toSeq
}
def resourceMappings = (unmanagedResources, unmanagedResourceDirectories) map { (rs, rdirs) =>
(rs --- rdirs) x (relativeTo(rdirs)|flat) toSeq
2011-02-10 14:16:07 +01:00
}
def collectFiles(dirs: ScopedTaskable[Seq[File]], filter: ScopedTaskable[FileFilter], excludes: ScopedTaskable[FileFilter]): Initialize[Task[Seq[File]]] =
2011-05-15 00:21:41 +02:00
(dirs, filter, excludes) map { (d,f,excl) => d.descendentsExcept(f,excl).get }
def artifactPathSetting(art: ScopedSetting[Artifact]) = (crossTarget, projectID, art, scalaVersion, artifactName) { (t, module, a, sv, toString) => t / toString(sv, module, a) asFile }
2011-02-10 14:16:07 +01:00
def pairID[A,B] = (a: A, b: B) => (a,b)
def packageTasks(key: TaskKey[File], mappingsTask: Initialize[Task[Seq[(File,String)]]]) =
2011-02-10 14:16:07 +01:00
inTask(key)( Seq(
key in ThisScope.copy(task = Global) <<= packageTask,
packageConfiguration <<= packageConfigurationTask,
2011-03-02 12:46:28 +01:00
mappings <<= mappingsTask,
packagedArtifact <<= (artifact, key) map pairID,
artifact <<= (artifact, artifactClassifier, configuration) { (a,classifier,c) =>
val cPart = if(c == Compile) Nil else c.name :: Nil
val combined = cPart ++ classifier.toList
a.copy(classifier = if(combined.isEmpty) None else Some(combined mkString "-"))
},
2011-03-02 12:46:28 +01:00
cacheDirectory <<= cacheDirectory / key.key.label,
artifactPath <<= artifactPathSetting(artifact)
2011-02-10 14:16:07 +01:00
))
def packageTask: Initialize[Task[File]] =
(packageConfiguration, cacheDirectory, streams) map { (config, cacheDir, s) =>
2011-03-02 12:46:28 +01:00
Package(config, cacheDir, s.log)
config.jar
}
def packageConfigurationTask: Initialize[Task[Package.Configuration]] =
(mappings, artifactPath, packageOptions) map { (srcs, path, options) =>
new Package.Configuration(srcs, path, options)
2011-02-10 14:16:07 +01:00
}
2011-02-06 03:40:10 +01:00
def selectRunMain(classes: Seq[String]): Option[String] =
sbt.SelectMainClass(Some(SimpleReader readLine _), classes)
def selectPackageMain(classes: Seq[String]): Option[String] =
sbt.SelectMainClass(None, classes)
def doClean(clean: Seq[File], preserve: Seq[File]): Unit =
IO.withTemporaryDirectory { temp =>
2011-04-13 05:10:36 +02:00
val mappings = preserve.filter(_.exists).zipWithIndex map { case (f, i) => (f, new File(temp, i.toHexString)) }
IO.move(mappings)
IO.delete(clean)
IO.move(mappings.map(_.swap))
}
def runMainTask(classpath: ScopedTask[Classpath], scalaRun: ScopedSetting[ScalaRun]): Initialize[InputTask[Unit]] =
{
import DefaultParsers._
InputTask( TaskData(discoveredMainClasses)(runMainParser)(Nil) ) { result =>
(classpath, scalaRun, streams, result) map { case (cp, runner, s, (mainClass, args)) =>
toError(runner.run(mainClass, data(cp), args, s.log))
}
}
}
2011-03-02 12:46:28 +01:00
def runTask(classpath: ScopedTask[Classpath], mainClassTask: ScopedTask[Option[String]], scalaRun: ScopedSetting[ScalaRun]): Initialize[InputTask[Unit]] =
inputTask { result =>
2011-03-02 12:46:28 +01:00
(classpath, mainClassTask, scalaRun, streams, result) map { (cp, main, runner, s, args) =>
val mainClass = main getOrElse error("No main class detected.")
toError(runner.run(mainClass, data(cp), args, s.log))
2011-02-06 03:40:10 +01:00
}
}
def runnerSetting = runner <<= runnerInit
def runnerInit: Initialize[ScalaRun] = (scalaInstance, baseDirectory, javaOptions, outputStrategy, fork, javaHome, trapExit) { (si, base, options, strategy, forkRun, javaHomeDir, trap) =>
2011-03-02 12:46:28 +01:00
if(forkRun) {
new ForkRun( ForkOptions(scalaJars = si.jars, javaHome = javaHomeDir, outputStrategy = strategy,
2011-02-26 00:35:52 +01:00
runJVMOptions = options, workingDirectory = Some(base)) )
} else
new Run(si, trap)
2011-02-26 00:35:52 +01:00
}
def docTask: Initialize[Task[File]] =
2011-04-21 00:31:10 +02:00
(cacheDirectory, compileInputs, streams, docDirectory, configuration, scaladocOptions) map { (cache, in, s, target, config, options) =>
2011-02-06 17:33:29 +01:00
val d = new Scaladoc(in.config.maxErrors, in.compilers.scalac)
2011-04-21 00:31:10 +02:00
val cp = in.config.classpath.toList - in.config.classesDirectory
d.cached(cache / "doc", nameForSrc(config.name), in.config.sources, cp, target, options, s.log)
2011-02-10 14:16:07 +01:00
target
2011-02-06 17:33:29 +01:00
}
def mainRunTask = run <<= runTask(fullClasspath in Runtime, mainClass in run, runner in run)
def mainRunMainTask = runMain <<= runMainTask(fullClasspath in Runtime, runner in run)
2011-02-06 03:40:10 +01:00
2011-02-27 05:56:30 +01:00
def discoverMainClasses(analysis: inc.Analysis): Seq[String] =
Discovery.applications(Tests.allDefs(analysis)) collect { case (definition, discovered) if(discovered.hasMain) => definition.name }
2011-03-02 12:46:28 +01:00
2011-04-09 01:15:13 +02:00
def consoleProjectTask = (state, streams, initialCommands in consoleProject) map { (state, s, extra) => ConsoleProject(state, extra)(s.log); println() }
2011-03-02 12:46:28 +01:00
def consoleTask: Initialize[Task[Unit]] = consoleTask(fullClasspath, console)
def consoleQuickTask = consoleTask(externalDependencyClasspath, consoleQuick)
def consoleTask(classpath: TaskKey[Classpath], task: TaskKey[_]): Initialize[Task[Unit]] = (compilers, classpath, scalacOptions in task, initialCommands in task, streams) map {
(cs, cp, options, initCommands, s) =>
(new Console(cs.scalac))(data(cp), options, initCommands, s.log).foreach(msg => error(msg))
2011-02-06 03:40:10 +01:00
println()
}
def compileTask = (compileInputs, streams) map { (i,s) => Compiler(i,s.log) }
def compileInputsTask =
2011-04-04 03:15:35 +02:00
(dependencyClasspath, sources, compilers, javacOptions, scalacOptions, cacheDirectory, classDirectory, compileOrder, streams) map {
(cp, srcs, cs, javacOpts, scalacOpts, cacheDir, classes, order, s) =>
val classpath = classes +: data(cp)
val analysis = analysisMap(cp)
2011-03-02 12:46:28 +01:00
val cache = cacheDir / "compile"
2011-04-04 03:15:35 +02:00
Compiler.inputs(classpath, srcs, classes, scalacOpts, javacOpts, analysis, cache, 100, order)(cs, s.log)
}
2011-03-14 02:34:17 +01:00
def writePluginsDescriptor(plugins: Set[String], dir: File): List[File] =
{
val descriptor: File = dir / "sbt" / "sbt.plugins"
if(plugins.isEmpty)
{
IO.delete(descriptor)
Nil
}
else
{
2011-03-17 03:21:02 +01:00
IO.writeLines(descriptor, plugins.toSeq.sorted)
2011-03-14 02:34:17 +01:00
descriptor :: Nil
}
}
def discoverPlugins: Initialize[Task[Set[String]]] = (compile, sbtPlugin, streams) map { (analysis, isPlugin, s) => if(isPlugin) discoverSbtPlugins(analysis, s.log) else Set.empty }
def discoverSbtPlugins(analysis: inc.Analysis, log: Logger): Set[String] =
{
val pluginClass = classOf[Plugin].getName
val discovery = Discovery(Set(pluginClass), Set.empty)( Tests allDefs analysis )
discovery collect { case (df, disc) if (disc.baseClasses contains pluginClass) && disc.isModule => df.name } toSet;
}
2011-03-02 12:46:28 +01:00
def copyResourcesTask =
(classDirectory, cacheDirectory, resources, resourceDirectories, streams) map { (target, cache, resrcs, dirs, s) =>
2011-02-06 19:01:50 +01:00
val cacheFile = cache / "copy-resources"
val mappings = (resrcs --- dirs) x (rebase(dirs, target) | flat(target))
2011-02-06 19:01:50 +01:00
s.log.debug("Copy resource mappings: " + mappings.mkString("\n\t","\n\t",""))
Sync(cacheFile)( mappings )
mappings
}
def runMainParser: (State, Seq[String]) => Parser[(String, Seq[String])] =
{
import DefaultParsers._
(state, mainClasses) => Space ~> token(NotSpace examples mainClasses.toSet) ~ spaceDelimited("<arg>")
}
2011-04-23 02:13:24 +02:00
def testOnlyParser: (State, Seq[String]) => Parser[(Seq[String],Seq[String])] =
{ (state, tests) =>
import DefaultParsers._
2011-05-25 05:54:49 +02:00
val selectTests = distinctParser(tests.toSet)
val options = (token(Space) ~> token("--") ~> spaceDelimited("<option>")) ?? Nil
selectTests ~ options
}
2011-05-25 05:54:49 +02:00
def distinctParser(exs: Set[String]): Parser[Seq[String]] =
{
import DefaultParsers._
val base = token(Space) ~> token(NotSpace - "--" examples exs)
val recurse = base flatMap { ex =>
val (matching, notMatching) = exs.partition( GlobFilter(ex).accept _ )
distinctParser(notMatching).map(matching.toSeq ++ _)
}
recurse ?? Nil
}
2011-03-01 14:54:06 +01:00
def inAllDependencies[T](base: ProjectRef, key: ScopedSetting[T], structure: Load.BuildStructure): Seq[T] =
{
def deps(ref: ProjectRef): Seq[ProjectRef] =
Project.getProject(ref, structure).toList.flatMap { p =>
p.dependencies.map(_.project) ++ p.aggregate
}
inAllDeps(base, deps, key, structure.data)
}
def inAllDeps[T](base: ProjectRef, deps: ProjectRef => Seq[ProjectRef], key: ScopedSetting[T], data: Settings[Scope]): Seq[T] =
inAllProjects(Dag.topologicalSort(base)(deps), key, data)
def inAllProjects[T](allProjects: Seq[Reference], key: ScopedSetting[T], data: Settings[Scope]): Seq[T] =
2011-03-01 14:54:06 +01:00
allProjects.flatMap { p => key in p get data }
val CompletionsID = "completions"
def noAggregation = Seq(run, console, consoleQuick, consoleProject)
lazy val disableAggregation = noAggregation map disableAggregate
def disableAggregate(k: Scoped) =
2011-03-02 12:46:28 +01:00
aggregate in Scope.GlobalScope.copy(task = Select(k.key)) :== false
2011-02-26 00:35:52 +01:00
lazy val baseTasks: Seq[Setting[_]] = projectTasks ++ packageBase
2011-02-06 03:40:10 +01:00
2011-02-26 00:35:52 +01:00
lazy val baseClasspaths = Classpaths.publishSettings ++ Classpaths.baseSettings
2011-04-12 04:12:03 +02:00
lazy val configSettings = Classpaths.configSettings ++ configTasks ++ configPaths ++ packageConfig ++ Classpaths.compilerPluginConfig
2011-02-26 00:35:52 +01:00
lazy val compileSettings = configSettings ++ (mainRunMainTask +: mainRunTask +: addBaseSources)
2011-02-26 00:35:52 +01:00
lazy val testSettings = configSettings ++ testTasks
lazy val itSettings = inConfig(IntegrationTest)(testSettings)
2011-05-03 02:41:36 +02:00
lazy val defaultConfigs = inConfig(Compile)(compileSettings) ++ inConfig(Test)(testSettings) ++ inConfig(Runtime)(Classpaths.configSettings)
2011-04-09 01:15:13 +02:00
// settings that are not specific to a configuration
lazy val projectBaseSettings: Seq[Setting[_]] = projectCore ++ paths ++ baseClasspaths ++ baseTasks ++ compileBase ++ disableAggregation
lazy val defaultSettings: Seq[Setting[_]] = projectBaseSettings ++ defaultConfigs
}
object Classpaths
{
import Path._
import Keys._
import Scope.ThisScope
import Defaults._
import Attributed.{blank, blankSeq}
def concat[T](a: ScopedTaskable[Seq[T]], b: ScopedTaskable[Seq[T]]): Initialize[Task[Seq[T]]] = (a,b) map (_ ++ _)
def concatSettings[T](a: ScopedSetting[Seq[T]], b: ScopedSetting[Seq[T]]): Initialize[Seq[T]] = (a,b)(_ ++ _)
2011-02-27 05:56:30 +01:00
lazy val configSettings: Seq[Setting[_]] = Seq(
2011-03-02 12:46:28 +01:00
externalDependencyClasspath <<= concat(unmanagedClasspath, managedClasspath),
dependencyClasspath <<= concat(internalDependencyClasspath, externalDependencyClasspath),
fullClasspath <<= concat(products, dependencyClasspath),
internalDependencyClasspath <<= internalDependencies,
unmanagedClasspath <<= unmanagedDependencies,
products <<= makeProducts,
classpathConfiguration <<= (internalConfigurationMap, configuration)( _ apply _ ),
managedClasspath <<= (classpathConfiguration, classpathTypes, update) map managedJars,
unmanagedJars <<= (configuration, unmanagedBase, classpathFilter, defaultExcludes in unmanagedJars) map { (config, base, filter, excl) =>
2011-05-15 00:21:41 +02:00
(base * (filter -- excl) +++ (base / config.name).descendentsExcept(filter, excl)).get
}
)
def defaultPackageKeys = Seq(packageBin, packageSrc, packageDoc)
lazy val defaultPackages: Seq[ScopedTask[File]] =
for(task <- defaultPackageKeys; conf <- Seq(Compile, Test)) yield (task in conf)
lazy val defaultArtifactTasks: Seq[ScopedTask[File]] = makePom +: defaultPackages
def packaged(pkgTasks: Seq[ScopedTask[File]]): Initialize[Task[Map[Artifact, File]]] =
enabledOnly(packagedArtifact.task, pkgTasks).map(_.join.map(_.toMap))
def artifactDefs(pkgTasks: Seq[ScopedTask[File]]): Initialize[Seq[Artifact]] =
enabledOnly(artifact, pkgTasks)
def enabledOnly[T](key: ScopedSetting[T], pkgTasks: Seq[ScopedTask[File]]): Initialize[Seq[T]] =
( forallIn(key, pkgTasks) zipWith forallIn(publishArtifact, pkgTasks) ) ( _ zip _ collect { case (a, true) => a } )
def forallIn[T](key: ScopedSetting[T], pkgTasks: Seq[ScopedTask[_]]): Initialize[Seq[T]] =
pkgTasks.map( pkg => key in pkg.scope in pkg ).join
2011-02-27 05:56:30 +01:00
val publishSettings: Seq[Setting[_]] = Seq(
2011-03-02 12:46:28 +01:00
publishMavenStyle in GlobalScope :== true,
publishArtifact in GlobalScope in Compile :== true,
publishArtifact in GlobalScope in Test:== false,
artifacts <<= artifactDefs(defaultArtifactTasks),
packagedArtifacts <<= packaged(defaultArtifactTasks),
makePom <<= (ivyModule, makePomConfiguration, streams) map { (module, config, s) => IvyActions.makePom(module, config, s.log); config.file },
packagedArtifact in makePom <<= (artifact in makePom, makePom) map pairID,
deliver <<= deliverTask(deliverConfiguration),
deliverLocal <<= deliverTask(deliverLocalConfiguration),
2011-03-02 12:46:28 +01:00
publish <<= publishTask(publishConfiguration, deliver),
publishLocal <<= publishTask(publishLocalConfiguration, deliverLocal)
)
2011-02-27 05:56:30 +01:00
val baseSettings: Seq[Setting[_]] = Seq(
2011-03-02 12:46:28 +01:00
unmanagedBase <<= baseDirectory / "lib",
normalizedName <<= name(StringUtilities.normalize),
organization <<= organization or normalizedName.identity,
2011-03-02 12:46:28 +01:00
classpathFilter in GlobalScope :== "*.jar",
externalResolvers <<= externalResolvers or (resolvers map Resolver.withDefaultResolvers),
fullResolvers <<= (projectResolver,externalResolvers,sbtPlugin,sbtResolver) map { (pr,rs,isPlugin,sr) =>
val base = pr +: rs
if(isPlugin) sr +: base else base
},
2011-03-02 12:46:28 +01:00
offline in GlobalScope :== false,
moduleID <<= normalizedName.identity,
2011-03-02 12:46:28 +01:00
defaultConfiguration in GlobalScope :== Some(Configurations.Compile),
defaultConfigurationMapping in GlobalScope <<= defaultConfiguration{ case Some(d) => "*->" + d.name; case None => "*->*" },
2011-04-23 21:58:59 +02:00
ivyPaths <<= (baseDirectory, appConfiguration) { (base, app) => new IvyPaths(base, bootIvyHome(app)) },
otherResolvers <<= publishTo(_.toList),
2011-03-02 12:46:28 +01:00
projectResolver <<= projectResolverTask,
projectDependencies <<= projectDependenciesTask,
libraryDependencies in GlobalScope :== Nil,
allDependencies <<= (projectDependencies,libraryDependencies,sbtPlugin,sbtDependency) map { (projDeps, libDeps, isPlugin, sbtDep) =>
val base = projDeps ++ libDeps
if(isPlugin) sbtDep +: base else base
},
2011-03-02 12:46:28 +01:00
ivyLoggingLevel in GlobalScope :== UpdateLogging.Quiet,
ivyXML in GlobalScope :== NodeSeq.Empty,
ivyValidate in GlobalScope :== false,
ivyScala in GlobalScope <<= (scalaHome, scalaVersion)((sh,v) => Some(new IvyScala(v, Nil, filterImplicit = true, checkExplicit = true, overrideScalaVersion = sh.isEmpty))),
2011-03-02 12:46:28 +01:00
moduleConfigurations in GlobalScope :== Nil,
publishTo in GlobalScope :== None,
artifactPath in makePom <<= artifactPathSetting(artifact in makePom),
publishArtifact in makePom <<= publishMavenStyle.identity,
artifact in makePom <<= moduleID( name => Artifact(name, "pom", "pom") ),
2011-05-08 04:02:05 +02:00
projectID <<= (organization,moduleID,version,artifacts,crossPaths){ (org,module,version,as,crossEnabled) =>
ModuleID(org, module, version).cross(crossEnabled).artifacts(as : _*)
},
resolvers in GlobalScope :== Nil,
2011-03-02 12:46:28 +01:00
projectDescriptors <<= depMap,
retrievePattern in GlobalScope :== "[type]/[organisation]/[module]/[artifact](-[revision])(-[classifier]).[ext]",
updateConfiguration <<= (retrieveConfiguration, ivyLoggingLevel)((conf,level) => new UpdateConfiguration(conf, false, level) ),
retrieveConfiguration <<= (managedDirectory, retrievePattern, retrieveManaged) { (libm, pattern, enabled) => if(enabled) Some(new RetrieveConfiguration(libm, pattern)) else None },
ivyConfiguration <<= ivyConfiguration or mkIvyConfiguration,
ivyConfigurations <<= (autoCompilerPlugins, internalConfigurationMap, thisProject) { (auto, internalMap, project) =>
(project.configurations ++ project.configurations.map(internalMap) ++ (if(auto) CompilerPlugin :: Nil else Nil)).distinct
2011-04-12 04:12:03 +02:00
},
moduleSettings <<= moduleSettings0,
makePomConfiguration <<= (artifactPath in makePom, pomExtra, pomPostProcess, pomIncludeRepository) {
(file, extra, process, include) => new MakePomConfiguration(file, None, extra, process, include)
},
deliverLocalConfiguration <<= (crossTarget, ivyLoggingLevel) map { (outDir, level) => deliverConfig( outDir, logging = level ) },
deliverConfiguration <<= deliverLocalConfiguration.identity,
publishConfiguration <<= (packagedArtifacts, publishTo, publishMavenStyle, deliver, ivyLoggingLevel) map { (arts, publishTo, mavenStyle, ivyFile, level) =>
publishConfig(arts, if(mavenStyle) None else Some(ivyFile), resolverName = getPublishTo(publishTo).name, logging = level)
},
publishLocalConfiguration <<= (packagedArtifacts, deliverLocal, ivyLoggingLevel) map {
(arts, ivyFile, level) => publishConfig(arts, Some(ivyFile), logging = level )
},
ivySbt <<= (ivyConfiguration, credentials, streams) map { (conf, creds, s) =>
Credentials.register(creds, s.log)
new IvySbt(conf)
},
2011-03-02 12:46:28 +01:00
ivyModule <<= (ivySbt, moduleSettings) map { (ivySbt, settings) => new ivySbt.Module(settings) },
update <<= (ivyModule, updateConfiguration, cacheDirectory, scalaInstance, streams) map { (module, config, cacheDirectory, si, s) =>
cachedUpdate(cacheDirectory / "update", module, config, Some(si), s.log)
},
transitiveClassifiers in GlobalScope :== Seq("sources", "javadoc"),
2011-03-22 23:19:48 +01:00
updateClassifiers <<= (ivySbt, projectID, update, transitiveClassifiers, updateConfiguration, ivyScala, streams) map { (is, pid, up, classifiers, c, ivyScala, s) =>
IvyActions.transitive(is, pid, up, classifiers, c, ivyScala, s.log)
},
updateSbtClassifiers <<= (ivySbt, projectID, transitiveClassifiers, updateConfiguration, sbtDependency, ivyScala, streams) map { (is, pid, classifiers, c, sbtDep, ivyScala, s) =>
IvyActions.transitiveScratch(is, pid, "sbt", sbtDep :: Nil, classifiers, c, ivyScala, s.log)
},
2011-05-17 04:56:07 +02:00
sbtResolver in GlobalScope :== typesafeResolver,
sbtDependency in GlobalScope <<= appConfiguration { app =>
val id = app.provider.id
ModuleID(id.groupID, id.name, id.version, crossVersion = id.crossVersioned)
}
)
def moduleSettings0: Initialize[Task[ModuleSettings]] =
(projectID, allDependencies, ivyXML, ivyConfigurations, defaultConfiguration, ivyScala, ivyValidate) map {
(pid, deps, ivyXML, confs, defaultConf, ivyS, validate) => new InlineConfiguration(pid, deps, ivyXML, confs, defaultConf, ivyS, validate)
}
def deliverTask(config: TaskKey[DeliverConfiguration]): Initialize[Task[File]] =
(ivyModule, config, update, streams) map { (module, config, _, s) => IvyActions.deliver(module, config, s.log) }
2011-03-02 12:46:28 +01:00
def publishTask(config: TaskKey[PublishConfiguration], deliverKey: TaskKey[_]): Initialize[Task[Unit]] =
(ivyModule, config, streams) map { (module, config, s) =>
2011-04-06 00:44:47 +02:00
IvyActions.publish(module, config, s.log)
}
import Cache._
import CacheIvy.{classpathFormat, /*publishIC,*/ updateIC, updateReportF}
def cachedUpdate(cacheFile: File, module: IvySbt#Module, config: UpdateConfiguration, scalaInstance: Option[ScalaInstance], log: Logger): UpdateReport =
{
implicit val updateCache = updateIC
implicit val updateReport = updateReportF
type In = IvyConfiguration :+: ModuleSettings :+: UpdateConfiguration :+: HNil
def work = (_: In) match { case conf :+: settings :+: config :+: HNil =>
log.info("Updating...")
2011-03-22 23:19:48 +01:00
val r = IvyActions.update(module, config, log)
log.info("Done updating.")
scalaInstance match { case Some(si) => substituteScalaFiles(si, r); case None => r }
}
val f =
Tracked.inputChanged(cacheFile / "inputs") { (inChanged: Boolean, in: In) =>
val outCache = Tracked.lastOutput[In, UpdateReport](cacheFile / "output") {
case (_, Some(out)) if !inChanged && out.allFiles.forall(_.exists) && out.cachedDescriptor.exists => out
case _ => work(in)
}
outCache(in)
}
f(module.owner.configuration :+: module.moduleSettings :+: config :+: HNil)
}
/*
// can't cache deliver/publish easily since files involved are hidden behind patterns. publish will be difficult to verify target-side anyway
def cachedPublish(cacheFile: File)(g: (IvySbt#Module, PublishConfiguration) => Unit, module: IvySbt#Module, config: PublishConfiguration) => Unit =
{ case module :+: config :+: HNil =>
/* implicit val publishCache = publishIC
val f = cached(cacheFile) { (conf: IvyConfiguration, settings: ModuleSettings, config: PublishConfiguration) =>*/
g(module, config)
/*}
f(module.owner.configuration :+: module.moduleSettings :+: config :+: HNil)*/
}*/
2011-04-16 20:40:13 +02:00
def defaultRepositoryFilter = (repo: MavenRepository) => !repo.root.startsWith("file:")
def getPublishTo(repo: Option[Resolver]): Resolver = repo getOrElse error("Repository for publishing is not specified.")
def deliverConfig(outputDirectory: File, status: String = "release", logging: UpdateLogging.Value = UpdateLogging.DownloadOnly) =
new DeliverConfiguration(deliverPattern(outputDirectory), status, None, logging)
def publishConfig(artifacts: Map[Artifact, File], ivyFile: Option[File], resolverName: String = "local", logging: UpdateLogging.Value = UpdateLogging.DownloadOnly) =
new PublishConfiguration(ivyFile, resolverName, artifacts, logging)
2011-05-15 00:21:41 +02:00
def deliverPattern(outputPath: File): String = (outputPath / "[artifact]-[revision](-[classifier]).[ext]").absolutePath
2011-03-02 12:46:28 +01:00
def projectDependenciesTask =
(thisProject, settings) map { (p, data) =>
p.dependencies flatMap { dep => (projectID in dep.project) get data map { _.copy(configurations = dep.configuration) } }
}
def depMap: Initialize[Task[Map[ModuleRevisionId, ModuleDescriptor]]] =
2011-03-22 23:19:48 +01:00
(thisProject, thisProjectRef, settings, streams) flatMap { (root, rootRef, data, s) =>
val dependencies = (p: (ProjectRef, ResolvedProject)) => p._2.dependencies.flatMap(pr => thisProject in pr.project get data map { (pr.project, _) })
2011-03-22 23:19:48 +01:00
depMap(Dag.topologicalSort((rootRef,root))(dependencies).dropRight(1), data, s.log)
}
2011-03-22 23:19:48 +01:00
def depMap(projects: Seq[(ProjectRef,ResolvedProject)], data: Settings[Scope], log: Logger): Task[Map[ModuleRevisionId, ModuleDescriptor]] =
2011-03-02 12:46:28 +01:00
projects.flatMap { case (p,_) => ivyModule in p get data }.join.map { mods =>
(mods.map{ mod =>
2011-03-22 23:19:48 +01:00
val md = mod.moduleDescriptor(log)
(md.getModuleRevisionId, md)
}).toMap
}
2011-03-02 12:46:28 +01:00
def projectResolverTask: Initialize[Task[Resolver]] =
projectDescriptors map { m =>
new RawRepository(new ProjectResolver("inter-project", m))
}
2011-03-02 12:46:28 +01:00
def analyzed[T](data: T, analysis: inc.Analysis) = Attributed.blank(data).put(Keys.analysis, analysis)
def makeProducts: Initialize[Task[Classpath]] =
2011-03-02 12:46:28 +01:00
(compile, compileInputs, copyResources) map { (analysis, i, _) => analyzed(i.config.classesDirectory, analysis) :: Nil }
def internalDependencies: Initialize[Task[Classpath]] =
2011-03-02 12:46:28 +01:00
(thisProjectRef, thisProject, configuration, settings) flatMap internalDependencies0
def unmanagedDependencies: Initialize[Task[Classpath]] =
2011-03-02 12:46:28 +01:00
(thisProjectRef, thisProject, configuration, settings) flatMap unmanagedDependencies0
def mkIvyConfiguration: Initialize[Task[IvyConfiguration]] =
(fullResolvers, ivyPaths, otherResolvers, moduleConfigurations, offline, checksums, appConfiguration, streams) map { (rs, paths, other, moduleConfs, off, check, app, s) =>
new InlineIvyConfiguration(paths, rs, other, moduleConfs, off, Some(lock(app)), check, s.log)
}
import java.util.LinkedHashSet
import collection.JavaConversions.asScalaSet
def interSort(projectRef: ProjectRef, project: ResolvedProject, conf: Configuration, data: Settings[Scope]): Seq[(ProjectRef,String)] =
{
val visited = asScalaSet(new LinkedHashSet[(ProjectRef,String)])
def visit(p: ProjectRef, project: ResolvedProject, c: Configuration)
{
val applicableConfigs = allConfigs(c)
for(ac <- applicableConfigs) // add all configurations in this project
visited add (p, ac.name)
val masterConfs = configurationNames(project)
for( ResolvedClasspathDependency(dep, confMapping) <- project.dependencies)
{
2011-03-02 12:46:28 +01:00
val depProject = thisProject in dep get data getOrElse error("Invalid project: " + dep)
val mapping = mapped(confMapping, masterConfs, configurationNames(depProject), "compile", "*->compile")
// map master configuration 'c' and all extended configurations to the appropriate dependency configuration
for(ac <- applicableConfigs; depConfName <- mapping(ac.name))
{
2011-03-02 12:46:28 +01:00
val depConf = getConfiguration(dep, depProject, depConfName)
if( ! visited( (dep, depConfName) ) )
visit(dep, depProject, depConf)
}
}
}
visit(projectRef, project, conf)
visited.toSeq
}
def unmanagedDependencies0(projectRef: ProjectRef, project: ResolvedProject, conf: Configuration, data: Settings[Scope]): Task[Classpath] =
interDependencies(projectRef, project, conf, data, true, unmanagedLibs)
def internalDependencies0(projectRef: ProjectRef, project: ResolvedProject, conf: Configuration, data: Settings[Scope]): Task[Classpath] =
2011-03-02 12:46:28 +01:00
interDependencies(projectRef, project, conf, data, false, productsTask)
def interDependencies(projectRef: ProjectRef, project: ResolvedProject, conf: Configuration, data: Settings[Scope], includeSelf: Boolean,
f: (ProjectRef, String, Settings[Scope]) => Task[Classpath]): Task[Classpath] =
{
val visited = interSort(projectRef, project, conf, data)
val tasks = asScalaSet(new LinkedHashSet[Task[Classpath]])
for( (dep, c) <- visited )
if(includeSelf || (dep != projectRef) || conf.name != c )
tasks += f(dep, c, data)
(tasks.toSeq.join).map(_.flatten.distinct)
}
def mapped(confString: Option[String], masterConfs: Seq[String], depConfs: Seq[String], default: String, defaultMapping: String): String => Seq[String] =
{
lazy val defaultMap = parseMapping(defaultMapping, masterConfs, depConfs, _ :: Nil)
parseMapping(confString getOrElse default, masterConfs, depConfs, defaultMap)
}
def parseMapping(confString: String, masterConfs: Seq[String], depConfs: Seq[String], default: String => Seq[String]): String => Seq[String] =
union(confString.split(";") map parseSingleMapping(masterConfs, depConfs, default))
def parseSingleMapping( masterConfs: Seq[String], depConfs: Seq[String], default: String => Seq[String])(confString: String): String => Seq[String] =
{
val ms: Seq[(String,Seq[String])] =
trim(confString.split("->",2)) match {
case x :: Nil => for(a <- parseList(x, masterConfs)) yield (a,default(a))
case x :: y :: Nil => val target = parseList(y, depConfs); for(a <- parseList(x, masterConfs)) yield (a,target)
case _ => error("Invalid configuration '" + confString + "'") // shouldn't get here
}
val m = ms.toMap
s => m.getOrElse(s, Nil)
}
def union[A,B](maps: Seq[A => Seq[B]]): A => Seq[B] =
a => (Seq[B]() /: maps) { _ ++ _(a) } distinct;
def configurationNames(p: ResolvedProject): Seq[String] = p.configurations.map( _.name)
def parseList(s: String, allConfs: Seq[String]): Seq[String] = (trim(s split ",") flatMap replaceWildcard(allConfs)).distinct
def replaceWildcard(allConfs: Seq[String])(conf: String): Seq[String] =
if(conf == "") Nil else if(conf == "*") allConfs else conf :: Nil
private def trim(a: Array[String]): List[String] = a.toList.map(_.trim)
def missingConfiguration(in: String, conf: String) =
error("Configuration '" + conf + "' not defined in '" + in + "'")
def allConfigs(conf: Configuration): Seq[Configuration] =
Dag.topologicalSort(conf)(_.extendsConfigs)
def getConfiguration(ref: ProjectRef, dep: ResolvedProject, conf: String): Configuration =
dep.configurations.find(_.name == conf) getOrElse missingConfiguration(Project display ref, conf)
def productsTask(dep: ResolvedReference, conf: String, data: Settings[Scope]): Task[Classpath] =
2011-03-02 12:46:28 +01:00
getClasspath(products, dep, conf, data)
def unmanagedLibs(dep: ResolvedReference, conf: String, data: Settings[Scope]): Task[Classpath] =
2011-03-02 12:46:28 +01:00
getClasspath(unmanagedJars, dep, conf, data)
def getClasspath(key: TaskKey[Classpath], dep: ResolvedReference, conf: String, data: Settings[Scope]): Task[Classpath] =
( key in (dep, ConfigKey(conf)) ) get data getOrElse const(Nil)
def defaultConfigurationTask(p: ResolvedReference, data: Settings[Scope]): Configuration =
2011-03-02 12:46:28 +01:00
flatten(defaultConfiguration in p get data) getOrElse Configurations.Default
def flatten[T](o: Option[Option[T]]): Option[T] = o flatMap idFun
2011-05-17 04:56:07 +02:00
lazy val typesafeResolver = Resolver.url("typesafe-ivy-releases", new URL("http://repo.typesafe.com/typesafe/ivy-releases/"))(Resolver.ivyStylePatterns)
import DependencyFilter._
def managedJars(config: Configuration, jarTypes: Set[String], up: UpdateReport): Classpath = up.select( configuration = configurationFilter(config.name), artifact = artifactFilter(`type` = jarTypes) )
2011-04-12 04:12:03 +02:00
def autoPlugins(report: UpdateReport): Seq[String] =
{
val pluginClasspath = report matching configurationFilter(CompilerPlugin.name)
classpath.ClasspathUtilities.compilerPlugins(pluginClasspath).map("-Xplugin:" + _.getAbsolutePath).toSeq
}
lazy val compilerPluginConfig = Seq(
scalacOptions <<= (scalacOptions, autoCompilerPlugins, update) map { (options, auto, report) =>
if(auto) options ++ autoPlugins(report) else options
2011-04-12 04:12:03 +02:00
}
)
def substituteScalaFiles(scalaInstance: ScalaInstance, report: UpdateReport): UpdateReport =
report.substitute { (configuration, module, arts) =>
import ScalaArtifacts._
(module.organization, module.name) match
{
case (Organization, LibraryID) => (Artifact(LibraryID), scalaInstance.libraryJar) :: Nil
case (Organization, CompilerID) => (Artifact(CompilerID), scalaInstance.compilerJar) :: Nil
case _ => arts
}
}
2011-04-23 21:58:59 +02:00
// try/catch for supporting earlier launchers
2011-04-23 21:58:59 +02:00
def bootIvyHome(app: xsbti.AppConfiguration): Option[File] =
try { Option(app.provider.scalaProvider.launcher.ivyHome) }
catch { case _: NoSuchMethodError => None }
}
2011-04-12 04:12:03 +02:00
trait BuildExtra extends BuildCommon
2011-04-12 04:12:03 +02:00
{
import Defaults._
2011-04-12 04:12:03 +02:00
def compilerPlugin(dependency: ModuleID): ModuleID =
dependency.copy(configurations = Some("plugin->default(compile)"))
def addCompilerPlugin(dependency: ModuleID): Setting[Seq[ModuleID]] =
libraryDependencies += compilerPlugin(dependency)
def addArtifact(a: Artifact, taskDef: ScopedTask[File]): SettingsDefinition =
{
val pkgd = packagedArtifacts <<= (packagedArtifacts, taskDef) map ( (pas,file) => pas updated (a, file) )
seq( artifacts += a, pkgd )
}
def addArtifact(artifact: ScopedSetting[Artifact], taskDef: ScopedTask[File]): SettingsDefinition =
{
val art = artifacts <<= (artifact, artifacts)( _ +: _ )
val pkgd = packagedArtifacts <<= (packagedArtifacts, artifact, taskDef) map ( (pas,a,file) => pas updated (a, file))
seq( art, pkgd )
}
def seq(settings: Setting[_]*): SettingsDefinition = new Project.SettingList(settings)
implicit def settingsDefinitionToSeq(sd: SettingsDefinition): Seq[Setting[_]] = sd.settings
def externalIvySettings(file: Initialize[File] = baseDirectory / "ivysettings.xml"): Setting[Task[IvyConfiguration]] =
{
val other = (baseDirectory, appConfiguration, streams).identityMap
ivyConfiguration <<= (file zipWith other) { case (f, otherTask) =>
otherTask map { case (base, app, s) => new ExternalIvyConfiguration(base, f, Some(lock(app)), s.log) }
}
}
def externalIvyFile(file: Initialize[File] = baseDirectory / "ivy.xml", iScala: Initialize[Option[IvyScala]] = ivyScala.identity): Setting[Task[ModuleSettings]] =
external(file, iScala)( (f, is, v) => new IvyFileConfiguration(f, is, v) )
def externalPom(file: Initialize[File] = baseDirectory / "pom.xml", iScala: Initialize[Option[IvyScala]] = ivyScala.identity): Setting[Task[ModuleSettings]] =
external(file, iScala)( (f, is, v) => new PomConfiguration(f, is, v) )
private[this] def external(file: Initialize[File], iScala: Initialize[Option[IvyScala]])(make: (File, Option[IvyScala], Boolean) => ModuleSettings): Setting[Task[ModuleSettings]] =
moduleSettings <<= ((file zip iScala) zipWith ivyValidate.identity) { case ((f, is), v) => task { make(f, is, v) } }
def runInputTask(config: Configuration, mainClass: String, baseArguments: String*): Initialize[InputTask[Unit]] =
inputTask { result =>
(fullClasspath in config, runner in (config, run), streams, result) map { (cp, r, s, args) =>
toError(r.run(mainClass, data(cp), baseArguments ++ args, s.log))
}
}
def runTask(config: Configuration, mainClass: String, arguments: String*): Initialize[Task[Unit]] =
(fullClasspath in config, runner in (config, run), streams) map { (cp, r, s) =>
toError(r.run(mainClass, data(cp), arguments, s.log))
}
def fullRunInputTask(scoped: ScopedInput[Unit], config: Configuration, mainClass: String, baseArguments: String*): Setting[InputTask[Unit]] =
scoped <<= inputTask { result =>
( inScoped(scoped.scoped, runnerInit) zipWith (fullClasspath in config, streams, result).identityMap) { (r, t) =>
t map { case (cp, s, args) =>
toError(r.run(mainClass, data(cp), baseArguments ++ args, s.log))
}
}
}
def fullRunTask(scoped: ScopedTask[Unit], config: Configuration, mainClass: String, arguments: String*): Setting[Task[Unit]] =
scoped <<= ( inScoped(scoped.scoped, runnerInit) zipWith (fullClasspath in config, streams).identityMap ) { case (r, t) =>
t map { case (cp, s) =>
toError(r.run(mainClass, data(cp), arguments, s.log))
}
}
private[this] def inScoped[T](sk: ScopedKey[_], i: Initialize[T]): Initialize[T] = inScope(fillTaskAxis(sk.scope, sk.key), i)
private[this] def inScope[T](s: Scope, i: Initialize[T]): Initialize[T] = i mapReferenced Project.mapScope(Scope.replaceThis(s))
}
trait BuildCommon
{
def inputTask[T](f: TaskKey[Seq[String]] => Initialize[Task[T]]): Initialize[InputTask[T]] = InputTask(_ => complete.Parsers.spaceDelimited("<arg>"))(f)
implicit def globFilter(expression: String): NameFilter = GlobFilter(expression)
implicit def richAttributed(s: Seq[Attributed[File]]): RichAttributed = new RichAttributed(s)
final class RichAttributed private[sbt](s: Seq[Attributed[File]])
{
def files: Seq[File] = Build data s
}
def toError(o: Option[String]): Unit = o foreach error
2011-04-12 04:12:03 +02:00
}