sbt/project/Sbt.scala

298 lines
19 KiB
Scala
Raw Normal View History

// TODO(low): proper generated API sources caching: doesn't detect output directory change
import sbt._
import Keys._
import Project.Initialize
import Util._
import Common._
import Licensed._
import Scope.ThisScope
import LaunchProguard.{proguard, Proguard}
object Sbt extends Build
{
override lazy val settings = super.settings ++ buildSettings ++ Status.settings ++ nightlySettings
2011-06-26 18:27:07 +02:00
def buildSettings = Seq(
organization := "org.scala-sbt",
2013-12-10 14:51:24 +01:00
version := "0.13.2-SNAPSHOT",
publishArtifact in packageDoc := false,
2013-10-03 01:39:17 +02:00
scalaVersion := "2.10.3",
publishMavenStyle := false,
componentID := None,
2012-02-05 03:10:30 +01:00
crossPaths := false,
2012-12-31 20:06:28 +01:00
resolvers += Resolver.typesafeIvyRepo("releases"),
2012-07-01 21:16:42 +02:00
concurrentRestrictions in Global += Util.testExclusiveRestriction,
2011-11-20 05:56:30 +01:00
testOptions += Tests.Argument(TestFrameworks.ScalaCheck, "-w", "1"),
javacOptions in compile ++= Seq("-target", "6", "-source", "6", "-Xlint", "-Xlint:-serial")
)
lazy val myProvided = config("provided") intransitive;
override def projects = super.projects.map(p => p.copy(configurations = (p.configurations.filter(_ != Provided)) :+ myProvided))
lazy val root: Project = Project("root", file("."), aggregate = nonRoots ) settings( rootSettings : _*) configs( Sxr.sxrConf, Proguard )
lazy val nonRoots = projects.filter(_ != root).map(p => LocalProject(p.id))
/* ** Subproject declarations ** */
// defines the Java interfaces through which the launcher and the launched application communicate
lazy val launchInterfaceSub = minProject(launchPath / "interface", "Launcher Interface") settings(javaOnly : _*)
// the launcher. Retrieves, loads, and runs applications based on a configuration file.
lazy val launchSub = testedBaseProject(launchPath, "Launcher") dependsOn(ioSub % "test->test", interfaceSub % "test", launchInterfaceSub) settings(launchSettings : _*)
// used to test the retrieving and loading of an application: sample app is packaged and published to the local repository
2012-02-05 03:10:30 +01:00
lazy val testSamples = noPublish( baseProject(launchPath / "test-sample", "Launch Test") ) dependsOn(interfaceSub, launchInterfaceSub) settings(scalaCompiler)
// defines Java structures used across Scala versions, such as the API structures and relationships extracted by
2013-12-10 14:51:24 +01:00
// the analysis compiler phases and passed back to sbt. The API structures are defined in a simple
// format from which Java sources are generated by the datatype generator subproject
lazy val interfaceSub = minProject(file("interface"), "Interface") settings(interfaceSettings : _*)
// defines operations on the API of a source, including determining whether it has changed and converting it to a string
// and discovery of subclasses and annotations
lazy val apiSub = testedBaseProject(compilePath / "api", "API") dependsOn(interfaceSub)
/* **** Utilities **** */
lazy val controlSub = baseProject(utilPath / "control", "Control")
lazy val collectionSub = testedBaseProject(utilPath / "collection", "Collections") settings( Util.keywordsSettings: _* )
lazy val applyMacroSub = testedBaseProject(utilPath / "appmacro", "Apply Macro") dependsOn(collectionSub) settings(scalaCompiler)
// The API for forking, combining, and doing I/O with system processes
2013-07-09 20:55:30 +02:00
lazy val processSub = baseProject(utilPath / "process", "Process") dependsOn(ioSub % "test->test") settings(scalaXml)
// Path, IO (formerly FileUtilities), NameFilter and other I/O utility classes
lazy val ioSub = testedBaseProject(utilPath / "io", "IO") dependsOn(controlSub) settings(ioSettings : _ *)
// Utilities related to reflection, managing Scala versions, and custom class loaders
Synchronize ClassLoaderCache and the Scala provider cache. Construction of Scala providers was already properly synchronized jvm and machine-wide. The cache on top of construction was not and neither was the newer ClassLoaderCache. This could cause the same Scala version to be loaded in multiple class loaders, taking up more permgen space and possibly decreasing performance due to less effective jit. The issue is very rare in practice for 0.13 because of the low probability of contention on ClassLoaderCache. This is because the work for a cache miss is mainly the construction of a URLClassLoader. In 0.12, however, the work potentially involved network access and class loading (not just class loader construction), thus greatly increasing the probability of contention and thus duplicate work (i.e. class loader construction). When there is contention, multiple class loaders are constructed and then preserved by the scalaInstance task in each project throughout the first task execution. Only when multiple scalaInstance tasks execute simultaneously and only during the first execution does this occur. (Technically, it could still happen later, but it doesn't in practice.) This means that the number of duplicate class loaders should quickly saturate instead of growing linearly with the number of projects. It also means that the impact depends on the exact tree structure of projects. A linear chain of dependencies will be unaffected, but a build with independent leaves may be limited by the number of cores. The number of cores affects the number of threads typically used by the task engine, which limits the number of concurrently executing scalaInstance tasks. In summary, this might affect the first, cold compilation of a multi-module project with independent leaves on a multi-core machine with Scala version different from the version used for sbt. It might increase the maximum permgen requirements as well as slow the jit compilation by up to one task execution. Subsequent compilations should be unaffected and the permgen utilization return to be as expected.
2013-06-20 01:20:37 +02:00
lazy val classpathSub = testedBaseProject(utilPath / "classpath", "Classpath") dependsOn(launchInterfaceSub, interfaceSub, ioSub) settings(scalaCompiler)
// Command line-related utilities.
lazy val completeSub = testedBaseProject(utilPath / "complete", "Completion") dependsOn(collectionSub, controlSub, ioSub) settings(jline)
// logging
lazy val logSub = testedBaseProject(utilPath / "log", "Logging") dependsOn(interfaceSub, processSub) settings(jline)
// Relation
lazy val relationSub = testedBaseProject(utilPath / "relation", "Relation") dependsOn(interfaceSub, processSub)
// class file reader and analyzer
lazy val classfileSub = testedBaseProject(utilPath / "classfile", "Classfile") dependsOn(ioSub, interfaceSub, logSub)
// generates immutable or mutable Java data types according to a simple input format
lazy val datatypeSub = baseProject(utilPath /"datatype", "Datatype Generator") dependsOn(ioSub)
2013-01-27 02:13:25 +01:00
// cross versioning
lazy val crossSub = baseProject(utilPath / "cross", "Cross") settings(inConfig(Compile)(Transform.crossGenSettings): _*)
// A monotonic logic that includes restricted negation as failure
lazy val logicSub = baseProject(utilPath / "logic", "Logic").dependsOn(collectionSub, relationSub)
/* **** Intermediate-level Modules **** */
// Apache Ivy integration
lazy val ivySub = baseProject(file("ivy"), "Ivy") dependsOn(interfaceSub, launchInterfaceSub, crossSub, logSub % "compile;test->test", ioSub % "compile;test->test", launchSub % "test->test") settings(ivy, jsch, testExclusive)
// Runner for uniform test interface
lazy val testingSub = baseProject(file("testing"), "Testing") dependsOn(ioSub, classpathSub, logSub, launchInterfaceSub, testAgentSub) settings(testInterface)
// Testing agent for running tests in a separate process.
lazy val testAgentSub = minProject(file("testing/agent"), "Test Agent") settings(testInterface)
// Basic task engine
lazy val taskSub = testedBaseProject(tasksPath, "Tasks") dependsOn(controlSub, collectionSub)
// Standard task system. This provides map, flatMap, join, and more on top of the basic task model.
2012-07-01 21:16:42 +02:00
lazy val stdTaskSub = testedBaseProject(tasksPath / "standard", "Task System") dependsOn(taskSub % "compile;test->test", collectionSub, logSub, ioSub, processSub) settings( testExclusive )
// Persisted caching based on SBinary
2013-07-09 20:55:30 +02:00
lazy val cacheSub = baseProject(cachePath, "Cache") dependsOn(ioSub, collectionSub) settings(sbinary, scalaXml)
// Builds on cache to provide caching for filesystem-related operations
lazy val trackingSub = baseProject(cachePath / "tracking", "Tracking") dependsOn(cacheSub, ioSub)
// Embedded Scala code runner
lazy val runSub = testedBaseProject(file("run"), "Run") dependsOn(ioSub, logSub % "compile;test->test", classpathSub, processSub % "compile;test->test")
// Compiler-side interface to compiler that is compiled against the compiler being used either in advance or on the fly.
// Includes API and Analyzer phases that extract source API and relationships.
Fix unstable existential type names bug. Fix the problem with unstable names synthesized for existential types (declared with underscore syntax) by renaming type variables to a scheme that is guaranteed to be stable no matter where given the existential type appears. The sheme we use are De Bruijn-like indices that capture both position of type variable declarion within single existential type and nesting level of nested existential type. This way we properly support nested existential types by avoiding name clashes. In general, we can perform renamings like that because type variables declared in existential types are scoped to those types so the renaming operation is local. There's a specs2 unit test covering instability of existential types. The test is included in compiler-interface project and the build definition has been modified to enable building and executing tests in compiler-interface project. Some dependencies has been modified: * compiler-interface project depends on api project for testing (test makes us of SameAPI) * dependency on junit has been introduced because it's needed for `@RunWith` annotation which declares that specs2 unit test should be ran with JUnitRunner SameAPI has been modified to expose a method that allows us to compare two definitions. This commit also adds `ScalaCompilerForUnitTesting` class that allows to compile a piece of Scala code and inspect information recorded callbacks defined in `AnalysisCallback` interface. That class uses existing ConsoleLogger for logging. I considered doing the same for ConsoleReporter. There's LoggingReporter defined which would fit our usecase but it's defined in compile subproject that compiler-interface doesn't depend on so we roll our own. ScalaCompilerForUnit testing uses TestCallback from compiler-interface subproject for recording information passed to callbacks. In order to be able to access TestCallback from compiler-interface subproject I had to tweak dependencies between interface and compiler-interface so test classes from the former are visible in the latter. I also modified the TestCallback itself to accumulate apis in a HashMap instead of a buffer of tuples for easier lookup. An integration test has been added which tests scenario mentioned in #823. This commit fixes #823.
2013-08-03 01:27:47 +02:00
lazy val compileInterfaceSub = baseProject(compilePath / "interface", "Compiler Interface") dependsOn(interfaceSub % "compile;test->test", ioSub % "test->test", logSub % "test->test", launchSub % "test->test", apiSub % "test->test") settings( compileInterfaceSettings : _*)
2012-04-13 23:47:12 +02:00
lazy val precompiled282 = precompiled("2.8.2")
lazy val precompiled292 = precompiled("2.9.2")
2013-03-18 15:06:24 +01:00
lazy val precompiled293 = precompiled("2.9.3")
// Implements the core functionality of detecting and propagating changes incrementally.
// Defines the data structures for representing file fingerprints and relationships and the overall source analysis
lazy val compileIncrementalSub = testedBaseProject(compilePath / "inc", "Incremental Compiler") dependsOn(apiSub, ioSub, logSub, classpathSub, relationSub)
// Persists the incremental data structures using SBinary
2012-12-31 20:06:28 +01:00
lazy val compilePersistSub = baseProject(compilePath / "persist", "Persist") dependsOn(compileIncrementalSub, apiSub) settings(sbinary)
// sbt-side interface to compiler. Calls compiler-side interface reflectively
2013-12-10 14:51:24 +01:00
lazy val compilerSub = testedBaseProject(compilePath, "Compile") dependsOn(launchInterfaceSub, interfaceSub % "compile;test->test", logSub, ioSub, classpathSub,
logSub % "test->test", launchSub % "test->test", apiSub % "test") settings( compilerSettings : _*)
lazy val compilerIntegrationSub = baseProject(compilePath / "integration", "Compiler Integration") dependsOn(
compileIncrementalSub, compilerSub, compilePersistSub, apiSub, classfileSub)
2012-04-18 14:07:53 +02:00
lazy val compilerIvySub = baseProject(compilePath / "ivy", "Compiler Ivy Integration") dependsOn(ivySub, compilerSub )
2013-07-09 20:55:30 +02:00
lazy val scriptedBaseSub = baseProject(scriptedPath / "base", "Scripted Framework") dependsOn(ioSub, processSub) settings(scalaParsers)
lazy val scriptedSbtSub = baseProject(scriptedPath / "sbt", "Scripted sbt") dependsOn(ioSub, logSub, processSub, scriptedBaseSub, launchInterfaceSub % "provided")
lazy val scriptedPluginSub = baseProject(scriptedPath / "plugin", "Scripted Plugin") dependsOn(sbtSub, classpathSub)
// Implementation and support code for defining actions.
2012-12-19 16:17:56 +01:00
lazy val actionsSub = testedBaseProject(mainPath / "actions", "Actions") dependsOn(
2012-04-18 14:07:53 +02:00
classpathSub, completeSub, apiSub, compilerIntegrationSub, compilerIvySub,
interfaceSub, ioSub, ivySub, logSub, processSub, runSub, relationSub, stdTaskSub, taskSub, trackingSub, testingSub)
// General command support and core commands not specific to a build system
2013-01-27 02:13:25 +01:00
lazy val commandSub = testedBaseProject(mainPath / "command", "Command") dependsOn(interfaceSub, ioSub, launchInterfaceSub, logSub, completeSub, classpathSub, crossSub)
// Fixes scope=Scope for Setting (core defined in collectionSub) to define the settings system used in build definitions
lazy val mainSettingsSub = testedBaseProject(mainPath / "settings", "Main Settings") dependsOn(applyMacroSub, interfaceSub, ivySub, relationSub, logSub, ioSub, commandSub,
2012-12-31 20:06:28 +01:00
completeSub, classpathSub, stdTaskSub, processSub) settings( sbinary )
2012-01-29 20:36:27 +01:00
// The main integration project for sbt. It brings all of the subsystems together, configures them, and provides for overriding conventions.
lazy val mainSub = testedBaseProject(mainPath, "Main") dependsOn(actionsSub, mainSettingsSub, interfaceSub, ioSub, ivySub, launchInterfaceSub, logSub, logicSub, processSub, runSub, commandSub) settings(scalaXml)
2012-01-29 20:36:27 +01:00
// Strictly for bringing implicits and aliases from subsystems into the top-level sbt namespace through a single package object
// technically, we need a dependency on all of mainSub's dependencies, but we don't do that since this is strictly an integration project
// with the sole purpose of providing certain identifiers without qualification (with a package object)
lazy val sbtSub = baseProject(sbtPath, "sbt") dependsOn(mainSub, compileInterfaceSub, precompiled282, precompiled292, precompiled293, scriptedSbtSub % "test->test") settings(sbtSettings : _*)
/* Nested subproject paths */
def sbtPath = file("sbt")
def cachePath = file("cache")
def tasksPath = file("tasks")
def launchPath = file("launch")
def utilPath = file("util")
def compilePath = file("compile")
def mainPath = file("main")
def scriptedPath = file("scripted")
def sbtSettings = Seq(
normalizedName := "sbt"
)
private def doScripted(launcher : File, scriptedSbtClasspath : Seq[Attributed[File]], scriptedSbtInstance: ScalaInstance, sourcePath : File, args : Seq[String]) {
val noJLine = new classpath.FilteredLoader(scriptedSbtInstance.loader, "jline." :: Nil)
val loader = classpath.ClasspathUtilities.toLoader(scriptedSbtClasspath.files, noJLine)
val m = ModuleUtilities.getObject("sbt.test.ScriptedTests", loader)
val r = m.getClass.getMethod("run", classOf[File], classOf[Boolean], classOf[Array[String]], classOf[File], classOf[Array[String]])
val launcherVmOptions = Array("-XX:MaxPermSize=256M") // increased after a failure in scripted source-dependencies/macro
try { r.invoke(m, sourcePath, true: java.lang.Boolean, args.toArray[String], launcher, launcherVmOptions) }
2011-07-24 05:07:54 +02:00
catch { case ite: java.lang.reflect.InvocationTargetException => throw ite.getCause }
}
def scriptedTask: Initialize[InputTask[Unit]] = InputTask(scriptedSource(dir => (s: State) => scriptedParser(dir))) { result =>
(proguard in Proguard, fullClasspath in scriptedSbtSub in Test, scalaInstance in scriptedSbtSub, publishAll, scriptedSource, result) map {
(launcher, scriptedSbtClasspath, scriptedSbtInstance, _, sourcePath, args) =>
doScripted(launcher, scriptedSbtClasspath, scriptedSbtInstance, sourcePath, args)
}
}
def scriptedUnpublishedTask: Initialize[InputTask[Unit]] = InputTask(scriptedSource(dir => (s: State) => scriptedParser(dir))) { result =>
(proguard in Proguard, fullClasspath in scriptedSbtSub in Test, scalaInstance in scriptedSbtSub, scriptedSource, result) map doScripted
}
2012-05-20 00:20:20 +02:00
import sbt.complete._
import DefaultParsers._
def scriptedParser(scriptedBase: File): Parser[Seq[String]] =
{
val pairs = (scriptedBase * AllPassFilter * AllPassFilter * "test").get map { (f: File) =>
val p = f.getParentFile
(p.getParentFile.getName, p.getName)
};
val pairMap = pairs.groupBy(_._1).mapValues(_.map(_._2).toSet) ;
val id = charClass(c => !c.isWhitespace && c != '/').+.string
val groupP = token(id.examples(pairMap.keySet.toSet)) <~ token('/')
def nameP(group: String) = token("*".id | id.examples(pairMap(group)))
2012-05-20 00:20:20 +02:00
val testID = for( group <- groupP; name <- nameP(group) ) yield (group, name)
(token(Space) ~> matched(testID)).*
}
lazy val scripted = InputKey[Unit]("scripted")
lazy val scriptedUnpublished = InputKey[Unit]("scripted-unpublished", "Execute scripted without publishing SBT first. Saves you some time when only your test has changed.")
lazy val scriptedSource = SettingKey[File]("scripted-source")
lazy val publishAll = TaskKey[Unit]("publish-all")
lazy val publishLauncher = TaskKey[Unit]("publish-launcher")
def deepTasks[T](scoped: TaskKey[Seq[T]]): Initialize[Task[Seq[T]]] = deep(scoped.task) { _.join.map(_.flatten.distinct) }
def deep[T](scoped: SettingKey[T]): Initialize[Seq[T]] =
2011-09-26 14:20:07 +02:00
Util.inAllProjects(projects filterNot Set(root, sbtSub, scriptedBaseSub, scriptedSbtSub, scriptedPluginSub) map { p => LocalProject(p.id) }, scoped)
2013-01-27 02:13:25 +01:00
def launchSettings =
2013-07-19 04:36:40 +02:00
Seq(ivy,
2013-01-27 02:13:25 +01:00
compile in Test <<= compile in Test dependsOn(publishLocal in interfaceSub, publishLocal in testSamples, publishLocal in launchInterfaceSub)
) ++
inConfig(Compile)(Transform.configSettings) ++
inConfig(Compile)(Transform.transSourceSettings ++ Seq(
Transform.inputSourceDirectory <<= (sourceDirectory in crossSub) / "input_sources",
Transform.sourceProperties := Map("cross.package0" -> "xsbt", "cross.package1" -> "boot")
))
2011-06-26 18:27:07 +02:00
import Sxr.sxr
2011-06-26 18:27:07 +02:00
def releaseSettings = Release.settings(nonRoots, proguard in Proguard)
2013-12-10 14:51:24 +01:00
def rootSettings = releaseSettings ++ fullDocSettings ++ LaunchProguard.settings ++ LaunchProguard.specific(launchSub) ++
Util.publishPomSettings ++ otherRootSettings ++ proguardedLauncherSettings ++
Transform.conscriptSettings(launchSub)
def otherRootSettings = Seq(
scripted <<= scriptedTask,
scriptedUnpublished <<= scriptedUnpublishedTask,
scriptedSource <<= (sourceDirectory in sbtSub) / "sbt-test",
2011-06-26 18:27:07 +02:00
publishAll <<= inAll(nonRoots, publishLocal.task),
publishAll <<= (publishAll, publishLocal).map((x,y)=> ()) // publish all normal deps as well as the sbt-launch jar
)
def fullDocSettings = Util.baseScalacOptions ++ Docs.settings ++ Sxr.settings ++ Seq(
scalacOptions += "-Ymacro-no-expand", // for both sxr and doc
sources in sxr <<= deepTasks(sources in Compile), //sxr
sources in (Compile,doc) <<= sources in sxr, // doc
Sxr.sourceDirectories <<= deep(sourceDirectories in Compile).map(_.flatten), // to properly relativize the source paths
fullClasspath in sxr <<= (externalDependencyClasspath in Compile in sbtSub),
dependencyClasspath in (Compile,doc) <<= fullClasspath in sxr
)
// the launcher is published with metadata so that the scripted plugin can pull it in
// being proguarded, it shouldn't ever be on a classpath with other jars, however
def proguardedLauncherSettings = Seq(
publishArtifact in packageSrc := false,
moduleName := "sbt-launch",
autoScalaLibrary := false,
description := "sbt application launcher",
publishLauncher <<= publish,
packageBin in Compile <<= (proguard in Proguard, Transform.conscriptConfigs).map( (x,y) => x)
)
def interfaceSettings = javaOnly ++ Seq(
projectComponent,
exportJars := true,
componentID := Some("xsbti"),
2011-11-10 11:11:16 +01:00
watchSources <++= apiDefinitions,
resourceGenerators in Compile <+= (version, resourceManaged, streams, compile in Compile) map generateVersionFile,
apiDefinitions <<= baseDirectory map { base => (base / "definition") :: (base / "other") :: (base / "type") :: Nil },
sourceGenerators in Compile <+= (cacheDirectory, apiDefinitions, fullClasspath in Compile in datatypeSub, sourceManaged in Compile, mainClass in datatypeSub in Compile, runner, streams) map generateAPICached
)
def precompiledSettings = Seq(
2011-09-26 14:20:07 +02:00
artifact in packageBin <<= (appConfiguration, scalaVersion) { (app, sv) =>
val launcher = app.provider.scalaProvider.launcher
val bincID = binID + "_" + ScalaInstance(sv, launcher).actualVersion
Artifact(binID) extra("e:component" -> bincID)
},
target <<= (target, scalaVersion) { (base, sv) => base / ("precompiled_" + sv) },
scalacOptions := Nil,
2012-02-22 04:47:07 +01:00
ivyScala ~= { _.map(_.copy(checkExplicit = false, overrideScalaVersion = false)) },
exportedProducts in Compile := Nil,
libraryDependencies <+= scalaVersion( "org.scala-lang" % "scala-compiler" % _ % "provided")
)
2011-06-12 02:09:15 +02:00
//
2013-07-19 04:36:40 +02:00
def compileInterfaceSettings: Seq[Setting[_]] = precompiledSettings ++ Seq[Setting[_]](
exportJars := true,
Fix unstable existential type names bug. Fix the problem with unstable names synthesized for existential types (declared with underscore syntax) by renaming type variables to a scheme that is guaranteed to be stable no matter where given the existential type appears. The sheme we use are De Bruijn-like indices that capture both position of type variable declarion within single existential type and nesting level of nested existential type. This way we properly support nested existential types by avoiding name clashes. In general, we can perform renamings like that because type variables declared in existential types are scoped to those types so the renaming operation is local. There's a specs2 unit test covering instability of existential types. The test is included in compiler-interface project and the build definition has been modified to enable building and executing tests in compiler-interface project. Some dependencies has been modified: * compiler-interface project depends on api project for testing (test makes us of SameAPI) * dependency on junit has been introduced because it's needed for `@RunWith` annotation which declares that specs2 unit test should be ran with JUnitRunner SameAPI has been modified to expose a method that allows us to compare two definitions. This commit also adds `ScalaCompilerForUnitTesting` class that allows to compile a piece of Scala code and inspect information recorded callbacks defined in `AnalysisCallback` interface. That class uses existing ConsoleLogger for logging. I considered doing the same for ConsoleReporter. There's LoggingReporter defined which would fit our usecase but it's defined in compile subproject that compiler-interface doesn't depend on so we roll our own. ScalaCompilerForUnit testing uses TestCallback from compiler-interface subproject for recording information passed to callbacks. In order to be able to access TestCallback from compiler-interface subproject I had to tweak dependencies between interface and compiler-interface so test classes from the former are visible in the latter. I also modified the TestCallback itself to accumulate apis in a HashMap instead of a buffer of tuples for easier lookup. An integration test has been added which tests scenario mentioned in #823. This commit fixes #823.
2013-08-03 01:27:47 +02:00
// we need to fork because in unit tests we set usejavacp = true which means
// we are expecting all of our dependencies to be on classpath so Scala compiler
// can use them while constructing its own classpath for compilation
fork in Test := true,
// needed because we fork tests and tests are ran in parallel so we have multiple Scala
// compiler instances that are memory hungry
javaOptions in Test += "-Xmx1G",
artifact in (Compile, packageSrc) := Artifact(srcID).copy(configurations = Compile :: Nil).extra("e:component" -> srcID)
)
def compilerSettings = Seq(
libraryDependencies <+= scalaVersion( "org.scala-lang" % "scala-compiler" % _ % "test" excludeAll(ExclusionRule(organization = "org.scala-lang.modules"))),
unmanagedJars in Test <<= (packageSrc in compileInterfaceSub in Compile).map(x => Seq(x).classpath)
)
def precompiled(scalav: String): Project = baseProject(compilePath / "interface", "Precompiled " + scalav.replace('.', '_')) dependsOn(interfaceSub) settings(precompiledSettings : _*) settings(
scalaHome := None,
scalaVersion <<= (scalaVersion in ThisBuild) { sbtScalaV =>
assert(sbtScalaV != scalav, "Precompiled compiler interface cannot have the same Scala version (" + scalav + ") as sbt.")
scalav
Fix unstable existential type names bug. Fix the problem with unstable names synthesized for existential types (declared with underscore syntax) by renaming type variables to a scheme that is guaranteed to be stable no matter where given the existential type appears. The sheme we use are De Bruijn-like indices that capture both position of type variable declarion within single existential type and nesting level of nested existential type. This way we properly support nested existential types by avoiding name clashes. In general, we can perform renamings like that because type variables declared in existential types are scoped to those types so the renaming operation is local. There's a specs2 unit test covering instability of existential types. The test is included in compiler-interface project and the build definition has been modified to enable building and executing tests in compiler-interface project. Some dependencies has been modified: * compiler-interface project depends on api project for testing (test makes us of SameAPI) * dependency on junit has been introduced because it's needed for `@RunWith` annotation which declares that specs2 unit test should be ran with JUnitRunner SameAPI has been modified to expose a method that allows us to compare two definitions. This commit also adds `ScalaCompilerForUnitTesting` class that allows to compile a piece of Scala code and inspect information recorded callbacks defined in `AnalysisCallback` interface. That class uses existing ConsoleLogger for logging. I considered doing the same for ConsoleReporter. There's LoggingReporter defined which would fit our usecase but it's defined in compile subproject that compiler-interface doesn't depend on so we roll our own. ScalaCompilerForUnit testing uses TestCallback from compiler-interface subproject for recording information passed to callbacks. In order to be able to access TestCallback from compiler-interface subproject I had to tweak dependencies between interface and compiler-interface so test classes from the former are visible in the latter. I also modified the TestCallback itself to accumulate apis in a HashMap instead of a buffer of tuples for easier lookup. An integration test has been added which tests scenario mentioned in #823. This commit fixes #823.
2013-08-03 01:27:47 +02:00
},
// we disable compiling and running tests in precompiled subprojects of compiler interface
// so we do not need to worry about cross-versioning testing dependencies
sources in Test := Nil
)
def ioSettings: Seq[Setting[_]] = Seq(
libraryDependencies <+= scalaVersion("org.scala-lang" % "scala-compiler" % _ % "test" excludeAll(ExclusionRule(organization = "org.scala-lang.modules")))
)
}