From d928047678624b51c6d240eb63d4df91179354ef Mon Sep 17 00:00:00 2001 From: Mark Harrah Date: Fri, 10 Jun 2011 07:48:53 -0400 Subject: [PATCH] port build to 0.10, fixes #30 use 'publish-all' from the root to publish all projects to local use 'proguard' to package the launcher --- project/Proguard.scala | 137 +++++++++ project/Sbt.scala | 211 +++++++++++++ project/Sxr.scala | 31 ++ project/Util.scala | 93 ++++++ project/build.properties | 5 - project/build/Helpers.scala | 57 ---- project/build/InstallExtractProject.scala | 62 ---- project/build/InstallerProject.scala | 28 -- project/build/LauncherProguard.scala | 72 ----- project/build/ProguardProject.scala | 92 ------ project/build/Sxr.scala | 24 -- project/build/XSbt.scala | 343 ---------------------- project/plugins/Plugins.scala | 6 - util/datatype/DatatypeParser.scala | 2 +- util/datatype/Definition.scala | 2 +- util/datatype/GenerateDatatypes.scala | 2 +- util/datatype/Generator.scala | 2 +- util/datatype/Line.scala | 2 +- 18 files changed, 477 insertions(+), 694 deletions(-) create mode 100644 project/Proguard.scala create mode 100644 project/Sbt.scala create mode 100644 project/Sxr.scala create mode 100644 project/Util.scala delete mode 100644 project/build.properties delete mode 100644 project/build/Helpers.scala delete mode 100644 project/build/InstallExtractProject.scala delete mode 100644 project/build/InstallerProject.scala delete mode 100644 project/build/LauncherProguard.scala delete mode 100644 project/build/ProguardProject.scala delete mode 100644 project/build/Sxr.scala delete mode 100644 project/build/XSbt.scala delete mode 100644 project/plugins/Plugins.scala diff --git a/project/Proguard.scala b/project/Proguard.scala new file mode 100644 index 000000000..1ea30d08b --- /dev/null +++ b/project/Proguard.scala @@ -0,0 +1,137 @@ + import sbt._ + import Keys._ + import Scope.{GlobalScope, ThisScope} + +object LaunchProguard +{ + lazy val Proguard = config("proguard") hide ; + + lazy val configurationFile = SettingKey[File]("configuration-file") + lazy val proguard = TaskKey[File]("proguard", "Produces the final compacted jar that contains only the classes needed using proguard.") + lazy val proguardConfiguration = TaskKey[File]("proguard-configuration", "Creates the configuration file to use with proguard.") + lazy val options = TaskKey[Seq[String]]("options") + lazy val optimizePasses = SettingKey[Int]("optimize-passes") + lazy val keepFullClasses = SettingKey[Seq[String]]("keep-full-classes") + lazy val keepClasses = SettingKey[Seq[String]]("keep-classes") + lazy val inputJars = TaskKey[Seq[File]]("input-jars") + + lazy val settings: Seq[Setting[_]] = + inScope(GlobalScope)(inConfig(Proguard)(globalSettings)) ++ + inConfig(Proguard)( baseSettings ) :+ + (libraryDependencies += "net.sf.proguard" % "proguard" % "4.4" % Proguard.name) + + def globalSettings = Seq( + optimizePasses := 2, + keepFullClasses := Nil, + keepClasses := Nil, + options := basicOptions + ) + def baseSettings = Seq( + options <++= optimizePasses map { passes => if(passes <= 0) Seq("-dontoptimize") else Seq( "-optimizationpasses " + passes.toString, "-optimizations !code/allocation/variable") }, + options <++= keepFullClasses map { _ map ("-keep public class " + _ + " {\n\tpublic protected * ;\n}") }, + options <++= keepClasses map { _ map ("-keep class " + _ + " {}") }, + configurationFile <<= target / "proguard.pro", + proguardConfiguration <<= writeProguardConfiguration, + proguard <<= proguardTask + ) + + def specific(launchSub: Reference): Seq[Setting[_]] = inConfig(Proguard)(Seq( + keepFullClasses ++= "xsbti.**" :: "jline.**" :: Nil, + keepClasses ++= "org.apache.ivy.plugins.resolver.URLResolver" :: "org.apache.ivy.plugins.resolver.IBiblioResolver" :: Nil, + artifactPath <<= (target, version) { (out,v) => out / ("sbt-launch-" + v + ".jar") }, + options <++= (dependencyClasspath in (launchSub, Compile), compile in (launchSub,Compile), streams) map { (cp, analysis, s) => mapJars(cp.files, analysis.relations.allBinaryDeps.toSeq, s.log) }, + options <+= packageBin map { f => "-injars " + mkpath(f) }, + packageBin <<= (packageBin in (launchSub, Compile)).identity, + options <++= mainClass in (launchSub, Compile) map { _.toList map(s => keepMain.format(s)) }, + options <+= artifactPath map { p => "-outjars " + mkpath(p) }, + fullClasspath <<= (configuration, classpathTypes, update) map Classpaths.managedJars + )) + + def mapJars(in: Seq[File], all: Seq[File], log: Logger): Seq[String] = + mapInJars(in, log) ++ mapLibraryJars(all filterNot in.toSet) + def writeProguardConfiguration = (options, configurationFile, streams) map { (opts, conf, s) => + val content = opts.mkString("\n") + if(!conf.exists || IO.read(conf) != content) { + s.log.info("Proguard configuration written to " + conf) + IO.write(conf, content) + } + conf + } + + def basicOptions = + Seq( + "-keep,allowoptimization,allowshrinking class * { *; }", + "-keepattributes SourceFile,LineNumberTable", + "-dontnote", + "-dontwarn", + "-ignorewarnings") + + private val keepMain = + """-keep public class %s { + | public static void main(java.lang.String[]); + |}""".stripMargin + + def mapLibraryJars(libraryJars: Seq[File]): Seq[String] = libraryJars.map(f => "-libraryjars " + mkpath(f)) + def mapOutJar(outJar: File) = "-outjars " + mkpath(outJar) + + def mkpath(f: File) : String = mkpath(f.getAbsolutePath, '\"') + def mkpath(path: String, delimiter : Char) : String = delimiter + path + delimiter + + def proguardTask = (cacheDirectory, artifactPath, proguardConfiguration, fullClasspath, packageBin, streams) map { (cache, outputJar, configFile, cp, inJar, s) => + val f = FileFunction.cached(cache / "proguard", FilesInfo.hash) { _ => + runProguard(outputJar, configFile, cp.files, s.log) + Set(outputJar) + } + f(Set(inJar, configFile)) // make the assumption that if the classpath changed, the outputJar would change + outputJar + } + def runProguard(outputJar: File, configFile: File, cp: Seq[File], log: Logger) + { + IO.delete(outputJar) + val fileString = mkpath(configFile.getAbsolutePath, '\'') + val exitValue = Process("java", List("-Xmx256M", "-cp", Path.makeString(cp), "proguard.ProGuard", "-include " + fileString)) ! log + if(exitValue != 0) error("Proguard failed with nonzero exit code (" + exitValue + ")") + } + + def mapInJars(inJars: Seq[File], log: Logger): Seq[String] = + { + val (jlineJars, notJLine) = inJars partition isJarX("jline") + val (ivyJars, notIvy) = notJLine partition isJarX("ivy") + val (libraryJar, remaining) = notIvy partition isJarX("scala-library") + val (compilerJar, otherJars) = remaining partition isJarX("scala-compiler") + + log.debug("proguard configuration:") + log.debug("\tJLline jar location: " + jlineJars.mkString(", ")) + log.debug("\tIvy jar location: " + ivyJars.mkString(", ")) + log.debug("\tOther jars:\n\t" + otherJars.mkString("\n\t")) + + ((withJar(ivyJars.toSeq, "Ivy") + excludeString(excludeIvyResources)) :: + (withJar(jlineJars, "JLine") + jlineFilter ) :: + (withJar(libraryJar, "Scala library") + libraryFilter) :: + otherJars.map(jar => mkpath(jar) + generalFilter).toList) map { "-injars " + _ } + } + + private def excludeString(s: List[String]) = s.map("!" + _).mkString("(",",",")") + private def excludeIvyResources = + "META-INF/**" :: + "fr/**" :: + "**/antlib.xml" :: + "**/*.png" :: + "org/apache/ivy/core/settings/ivyconf*.xml" :: + "org/apache/ivy/core/settings/ivysettings-*.xml" :: + "org/apache/ivy/plugins/resolver/packager/*" :: + "**/ivy_vfs.xml" :: + "org/apache/ivy/plugins/report/ivy-report-*" :: + Nil + + private def libraryFilter = "(!META-INF/**,!*.properties,!scala/actors/**.!scala/util/parsing/*.class,!scala/xml/**.class,!scala/package$.class,**.class)" + private def jlineFilter = "(!META-INF/**)" + private def generalFilter = "(!META-INF/**,!*.properties)" + + private def withJar[T](files: Seq[File], name: String) = mkpath(files.firstOption getOrElse error(name + " not present") ) + private def isJarX(x: String)(file: File) = + { + val name = file.getName + name.startsWith(x) && name.endsWith(".jar") + } +} diff --git a/project/Sbt.scala b/project/Sbt.scala new file mode 100644 index 000000000..01a6f08ad --- /dev/null +++ b/project/Sbt.scala @@ -0,0 +1,211 @@ +// TODO(high): proper incremental xsbt.version.properties generation +// TODO(low): proper generated API sources caching: doesn't detect output directory change +// TODO: fix discovery/test + + 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 ++ Seq( + organization := "org.scala-tools.sbt", + version := "0.10.1-SNAPSHOT", + publishArtifact in packageDoc := false, + scalaVersion := "2.8.1", + publishMavenStyle := false, + componentID := None, + publishTo := Some( Resolver.url("typesafe-ivy-releases", url("http://repo.typesafe.com/typesafe/ivy-releases/"))(Resolver.ivyStylePatterns) ), + credentials += Credentials(Path.userHome / ".ivy2" / ".typesafe-credentials") + ) + + 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("xsbt", 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 = project(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 : _*) + def launchSettings = Seq(jline, ivy, crossPaths := false, + compile in Test <<= compile in Test dependsOn(publishLocal in interfaceSub, publishLocal in testSamples, publishLocal in launchInterfaceSub) +// mappings in (Compile, packageBin) <++= (mappings in (launchInterfaceSub, Compile, packageBin) ).identity + ) + + // used to test the retrieving and loading of an application: sample app is packaged and published to the local repository + lazy val testSamples = noPublish( baseProject(launchPath / "test-sample", "Launch Test") ) dependsOn(interfaceSub, launchInterfaceSub) settings(scalaCompiler, crossPaths := false) + + // defines Java structures used across Scala versions, such as the API structures and relationships extracted by + // 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 = project(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 + lazy val apiSub = baseProject(compilePath / "api", "API") dependsOn(interfaceSub) + + /***** Utilities *****/ + + lazy val controlSub = baseProject(utilPath / "control", "Control") + lazy val collectionSub = testedBaseProject(utilPath / "collection", "Collections") + // The API for forking, combining, and doing I/O with system processes + lazy val processSub = baseProject(utilPath / "process", "Process") dependsOn(ioSub % "test->test") + // Path, IO (formerly FileUtilities), NameFilter and other I/O utility classes + lazy val ioSub = testedBaseProject(utilPath / "io", "IO") dependsOn(controlSub) + // Utilities related to reflection, managing Scala versions, and custom class loaders + lazy val classpathSub = baseProject(utilPath / "classpath", "Classpath") dependsOn(launchInterfaceSub, 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(libraryDependencies += jlineDep % "optional") + // 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) + + /***** Intermediate-level Modules *****/ + + // Apache Ivy integration + lazy val ivySub = baseProject(file("ivy"), "Ivy") dependsOn(interfaceSub, launchInterfaceSub, logSub % "compile;test->test", ioSub % "compile;test->test", launchSub % "test->test") settings(ivy, jsch) + // Runner for uniform test interface + lazy val testingSub = baseProject(file("testing"), "Testing") dependsOn(ioSub, classpathSub, logSub) settings(libraryDependencies += "org.scala-tools.testing" % "test-interface" % "0.5") + + // 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. + lazy val stdTaskSub = testedBaseProject(tasksPath / "standard", "Task System") dependsOn(taskSub % "compile;test->test", collectionSub, logSub, ioSub, processSub) + // Persisted caching based on SBinary + lazy val cacheSub = baseProject(cachePath, "Cache") dependsOn(ioSub, collectionSub) settings(sbinary) + // 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 = baseProject(file("run"), "Run") dependsOn(ioSub, logSub, classpathSub, processSub) + + // 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. + lazy val compileInterfaceSub = baseProject(compilePath / "interface", "Compiler Interface") dependsOn(interfaceSub, ioSub % "test->test", logSub % "test->test", launchSub % "test->test") settings( compileInterfaceSettings : _*) + lazy val precompiled29 = precompiled("2.9.0-1") +// lazy val precompiled27 = precompiled("2.7.7") + + // 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(collectionSub, apiSub, ioSub, logSub) + // Persists the incremental data structures using SBinary + lazy val compilePersistSub = baseProject(compilePath / "persist", "Persist") dependsOn(compileIncrementalSub, apiSub) settings(sbinary) + // sbt-side interface to compiler. Calls compiler-side interface reflectively + lazy val compilerSub = testedBaseProject(compilePath, "Compile") dependsOn(launchInterfaceSub, interfaceSub % "compile;test->test", ivySub, ioSub, classpathSub, + logSub % "test->test", launchSub % "test->test", apiSub % "test->test") settings( compilerSettings : _*) + + // Searches the source API data structures, currently looks for subclasses and annotations + lazy val discoverySub = testedBaseProject(compilePath / "discover", "Discovery") dependsOn(compileIncrementalSub, apiSub, compilerSub % "test->test") + + lazy val scriptedBaseSub = baseProject(scriptedPath / "base", "Scripted Framework") dependsOn(ioSub, processSub) + 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. + lazy val actionsSub = baseProject(mainPath / "actions", "Actions") dependsOn( + classfileSub, classpathSub, compileIncrementalSub, compilePersistSub, compilerSub, completeSub, discoverySub, + interfaceSub, ioSub, ivySub, logSub, processSub, runSub, stdTaskSub, taskSub, trackingSub, testingSub) + + // 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, interfaceSub, ioSub, ivySub, launchInterfaceSub, logSub, processSub, runSub) + // 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, "Simple Build Tool") dependsOn(mainSub, 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" + ) + + def scriptedTask: Initialize[InputTask[Unit]] = inputTask { result => + (proguard in Proguard, fullClasspath in scriptedSbtSub in Test, scalaInstance in scriptedSbtSub, publishAll, version, scalaVersion, scriptedScalaVersion, scriptedSource, result) map { + (launcher, scriptedSbtClasspath, scriptedSbtInstance, _, v, sv, ssv, sourcePath, args) => + val loader = classpath.ClasspathUtilities.toLoader(scriptedSbtClasspath.files, scriptedSbtInstance.loader) + val m = ModuleUtilities.getObject("sbt.test.ScriptedTests", loader) + val r = m.getClass.getMethod("run", classOf[File], classOf[Boolean], classOf[String], classOf[String], classOf[String], classOf[Array[String]], classOf[File]) + r.invoke(m, sourcePath, true: java.lang.Boolean, v, sv, ssv, args.toArray[String], launcher) + } + } + + lazy val scriptedScalaVersion = SettingKey[String]("scripted-scala-version") + lazy val scripted = InputKey[Unit]("scripted") + lazy val scriptedSource = SettingKey[File]("scripted-source") + lazy val publishAll = TaskKey[Unit]("publish-all") + + def deepTasks[T](scoped: ScopedTask[Seq[T]]): Initialize[Task[Seq[T]]] = deep(scoped.task).map { _.flatMap(_.join.map(_.flatten)) } + def deep[T](scoped: ScopedSetting[T]): Initialize[Task[Seq[T]]] = + state map { s => + val sxrProjects = projects filterNot Set(root, sbtSub, scriptedBaseSub, scriptedSbtSub, scriptedPluginSub) map { p => LocalProject(p.id) } + Defaults.inAllProjects(sxrProjects, scoped, Project.extract(s).structure.data) + } + + import Sxr.sxr + def rootSettings = LaunchProguard.settings ++ LaunchProguard.specific(launchSub) ++ Sxr.settings ++ docSetting ++ Seq( + scriptedScalaVersion := "2.8.1", + scripted <<= scriptedTask, + scriptedSource <<= (sourceDirectory in sbtSub) / "sbt-test", + sources in sxr <<= deepTasks(sources in Compile), + Sxr.sourceDirectories <<= deep(sourceDirectories in Compile).map(_.map(_.flatten)), + fullClasspath in sxr <<= (externalDependencyClasspath in Compile in sbtSub).identity, + compileInputs in (Compile,sxr) <<= (sources in sxr, compileInputs in sbtSub in Compile, fullClasspath in sxr) map { (srcs, in, cp) => + in.copy(config = in.config.copy(sources = srcs, classpath = cp.files)) + }, + publishAll <<= state flatMap { s => nop dependsOn( Defaults.inAllProjects(nonRoots, publishLocal.task, Project.extract(s).structure.data) : _*) }, + TaskKey[Unit]("build-all") <<= (publishAll, sxr, doc) map { (_,_,_) => () } + ) + def docSetting = inConfig(Compile)(inTask(sxr)(doc in ThisScope.copy(task = Global, config = Global) <<= Defaults.docTask)) + + def interfaceSettings = javaOnly ++ Seq( + crossPaths := false, + projectComponent, + exportJars := true, + componentID := Some("xsbti"), + watchSources <++= apiDefinitions.identity, + resourceGenerators in Compile <+= (version, resourceManaged, streams) 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( + artifact in packageBin <<= scalaInstance in Compile apply { si => + val bincID = binID + "_" + si.actualVersion + Artifact(binID) extra("e:component" -> bincID) + }, + target <<= (target, scalaVersion) { (base, sv) => base / ("precompiled_" + sv) }, + scalacOptions := Nil, + crossPaths := false, + exportedProducts in Compile := Nil, + exportedProducts in Test := Nil, + libraryDependencies <+= scalaVersion( "org.scala-lang" % "scala-compiler" % _ % "provided"), + libraryDependencies += jlineDep artifacts(Artifact("jline", Map("e:component" -> srcID))) + ) + def compileInterfaceSettings: Seq[Setting[_]] = precompiledSettings ++ Seq( + exportJars := true, + artifact in packageSrc := Artifact(srcID) extra("e:component" -> srcID) + ) + def compilerSettings = Seq( + libraryDependencies <+= scalaVersion( "org.scala-lang" % "scala-compiler" % _ % "test"), + 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(scalaVersion := scalav) settings(precompiledSettings : _*) +} diff --git a/project/Sxr.scala b/project/Sxr.scala new file mode 100644 index 000000000..adf9f735b --- /dev/null +++ b/project/Sxr.scala @@ -0,0 +1,31 @@ + import sbt._ + import Keys._ + import Scope.ThisScope + +object Sxr +{ + val sxrConf = config("sxr") hide + val sxr = TaskKey[File]("sxr") + val sourceDirectories = TaskKey[Seq[File]]("sxr-source-directories") + + lazy val settings: Seq[Setting[_]] = inTask(sxr)(inSxrSettings) ++ baseSettings + + def baseSettings = Seq( + libraryDependencies += "org.scala-tools.sxr" %% "sxr" % "0.2.7" % sxrConf.name + ) + def inSxrSettings = Seq( + managedClasspath <<= update map { _.matching( configurationFilter(sxrConf.name) ).classpath }, + scalacOptions <+= sourceDirectories map { "-P:sxr:base-directory:" + _.absString }, + scalacOptions <+= managedClasspath map { "-Xplugin:" + _.files.absString }, + target <<= target in taskGlobal apply { _ / "browse" }, + sxr in taskGlobal <<= sxrTask + ) + def taskGlobal = ThisScope.copy(task = Global) + def sxrTask = (sources, target, scalacOptions, classpathOptions, scalaInstance, fullClasspath in sxr, streams) map { (srcs, out, opts, cpOpts, si, cp, s) => + IO.delete(out) + IO.createDirectory(out) + val comp = new compiler.RawCompiler(si, cpOpts, s.log) + comp(srcs, cp.files, out, opts) + out + } +} diff --git a/project/Util.scala b/project/Util.scala new file mode 100644 index 000000000..0be323291 --- /dev/null +++ b/project/Util.scala @@ -0,0 +1,93 @@ + import sbt._ + import Keys._ + import StringUtilities.normalize + +object Util +{ + lazy val componentID = SettingKey[Option[String]]("component-id") + + def noPublish(p: Project) = p.copy(settings = noRemotePublish(p.settings)) + def noRemotePublish(in: Seq[Setting[_]]) = in filterNot { s => s.key == deliver || s.key == publish } + lazy val noExtra = projectDependencies ~= { _.map(_.copy(extraAttributes = Map.empty)) } // not sure why this is needed + + def project(path: File, nameString: String) = Project(normalize(nameString), path) settings( name := nameString, noExtra ) + def baseProject(path: File, nameString: String) = project(path, nameString) settings( base : _*) + def testedBaseProject(path: File, nameString: String) = baseProject(path, nameString) settings( testDependencies : _*) + + lazy val javaOnly = Seq[Setting[_]](/*crossPaths := false, */compileOrder := CompileOrder.JavaThenScala, unmanagedSourceDirectories in Compile <<= Seq(javaSource in Compile).join) + lazy val base: Seq[Setting[_]] = Seq(scalacOptions ++= Seq("-Xelide-below", "0"), projectComponent) ++ Licensed.settings + + def testDependencies = libraryDependencies ++= Seq( + "org.scala-tools.testing" %% "scalacheck" % "1.8" % "test", + "org.scala-tools.testing" %% "specs" % "1.6.8" % "test" + ) + + lazy val minimalSettings: Seq[Setting[_]] = Defaults.paths ++ Seq[Setting[_]](crossTarget <<= target.identity, name <<= thisProject(_.id)) + + def projectComponent = projectID <<= (projectID, componentID) { (pid, cid) => + cid match { case Some(id) => pid extra("e:component" -> id); case None => pid } + } + + lazy val apiDefinitions = TaskKey[Seq[File]]("api-definitions") + + def generateAPICached(cache: File, defs: Seq[File], cp: Classpath, out: File, main: Option[String], run: ScalaRun, s: TaskStreams): Seq[File] = + { + def gen() = generateAPI(defs, cp, out, main, run, s) + val f = FileFunction.cached(cache / "gen-api", FilesInfo.hash) { _ => gen().toSet} // TODO: check if output directory changed + f(defs.toSet).toSeq + } + def generateAPI(defs: Seq[File], cp: Classpath, out: File, main: Option[String], run: ScalaRun, s: TaskStreams): Seq[File] = + { + IO.delete(out) + IO.createDirectory(out) + val args = "immutable" :: "xsbti.api" :: out.getAbsolutePath :: defs.map(_.getAbsolutePath).toList + val mainClass = main getOrElse "No main class defined for datatype generator" + toError(run.run(mainClass, cp.files, args, s.log)) + (out ** "*.java").get + } + def generateVersionFile(version: String, dir: File, s: TaskStreams): Seq[File] = + { + import java.util.{Date, TimeZone} + val formatter = new java.text.SimpleDateFormat("yyyyMMdd'T'HHmmss") + formatter.setTimeZone(TimeZone.getTimeZone("GMT")) + val timestamp = formatter.format(new Date) + val content = "version=" + version + "\ntimestamp=" + timestamp + val f = dir / "xsbt.version.properties" + if(!f.exists) { // TODO: properly handle this + s.log.info("Writing version information to " + f + " :\n" + content) + IO.write(f, content) } + f :: Nil + } + def binID = "compiler-interface-bin" + def srcID = "compiler-interface-src" +} + +object Common +{ + def lib(m: ModuleID) = libraryDependencies += m + lazy val jlineDep = "jline" % "jline" % "0.9.94" intransitive() + lazy val jline = lib(jlineDep) + lazy val ivy = lib("org.apache.ivy" % "ivy" % "2.2.0") + lazy val jsch = lib("com.jcraft" % "jsch" % "0.1.31" intransitive() ) + lazy val sbinary = lib("org.scala-tools.sbinary" %% "sbinary" % "0.4.0" ) + lazy val scalaCompiler = libraryDependencies <+= scalaVersion("org.scala-lang" % "scala-compiler" % _ ) +} +object Licensed +{ + lazy val notice = SettingKey[File]("notice") + lazy val extractLicenses = TaskKey[Seq[File]]("extract-licenses") + + lazy val seeRegex = """\(see (.*?)\)""".r + def licensePath(base: File, str: String): File = { val path = base / str; if(path.exists) path else error("Referenced license '" + str + "' not found at " + path) } + def seePaths(base: File, noticeString: String): Seq[File] = seeRegex.findAllIn(noticeString).matchData.map(d => licensePath(base, d.group(1))).toList + + def settings: Seq[Setting[_]] = Seq( + notice <<= baseDirectory(_ / "NOTICE"), + unmanagedResources in Compile <++= (notice, extractLicenses) map { _ +: _ }, + extractLicenses <<= (baseDirectory in ThisBuild, notice, streams) map extractLicenses0 + ) + def extractLicenses0(base: File, note: File, s: TaskStreams): Seq[File] = + if(!note.exists) Nil else + try { seePaths(base, IO.read(note)) } + catch { case e: Exception => s.log.warn("Could not read NOTICE"); Nil } +} \ No newline at end of file diff --git a/project/build.properties b/project/build.properties deleted file mode 100644 index 8b1dd0451..000000000 --- a/project/build.properties +++ /dev/null @@ -1,5 +0,0 @@ -project.organization=org.scala-tools.sbt -project.name=xsbt -sbt.version=0.7.7 -project.version=0.10.1-SNAPSHOT -build.scala.versions=2.8.1 diff --git a/project/build/Helpers.scala b/project/build/Helpers.scala deleted file mode 100644 index d647e93e7..000000000 --- a/project/build/Helpers.scala +++ /dev/null @@ -1,57 +0,0 @@ -import sbt._ - -trait NoUpdate extends ManagedBase with EmptyTask -{ - override final def updateAction = emptyTask -} -trait NoCrossPaths extends Project -{ - override def disableCrossPaths = true -} -trait JavaProject extends BasicScalaProject with NoCrossPaths -{ - // ensure that interfaces are only Java sources and that they cannot reference Scala classes - override def mainSources = descendents(mainSourceRoots, "*.java") - override def compileOrder = CompileOrder.JavaThenScala -} -trait SourceProject extends BasicScalaProject with NoCrossPaths -{ - override def packagePaths = mainResources +++ mainSources // the default artifact is a jar of the main sources and resources -} -trait ManagedBase extends BasicScalaProject -{ - override def deliverScalaDependencies = Nil - override def managedStyle = ManagedStyle.Ivy - override def useDefaultConfigurations = false - val defaultConf = Configurations.Default - val testConf = Configurations.Test -} -trait Component extends DefaultProject -{ - override def projectID = componentID match { case Some(id) => super.projectID extra("e:component" -> id); case None => super.projectID } - def componentID: Option[String] = None -} -trait PrecompiledInterface extends BasicScalaProject with ManagedBase -{ - override def fullClasspath(config: Configuration) = super.fullClasspath(config) filter(f => !f.asFile.getName.contains("scala-compiler")) - def binID = "compiler-interface-bin" - def bincID = binID + "_" + buildScalaInstance.actualVersion - override def jarPath = mkJarPath(binID) - override def defaultMainArtifact = Artifact(binID) extra("e:component" -> bincID) - def mkJarPath(id: String) = outputPath / (id + "-" + version.toString + ".jar") - override def ivyXML: scala.xml.NodeSeq = // Remove when we build with 0.7.3, which does not unnecessarily add a default artifact -} -trait EmptyTask extends Project { - def emptyTask = task {None} -} -trait NoRemotePublish extends BasicManagedProject with EmptyTask -{ - override def deliverAction = emptyTask - override def publishAction = emptyTask -} -trait NoLocalPublish extends BasicManagedProject with EmptyTask -{ - override def publishLocalAction = emptyTask - override def deliverLocalAction = emptyTask -} -trait NoPublish extends NoLocalPublish with NoRemotePublish \ No newline at end of file diff --git a/project/build/InstallExtractProject.scala b/project/build/InstallExtractProject.scala deleted file mode 100644 index e2202f5ff..000000000 --- a/project/build/InstallExtractProject.scala +++ /dev/null @@ -1,62 +0,0 @@ -/* sbt -- Simple Build Tool - * Copyright 2009, 2010 Mark Harrah - */ - -import sbt._ -import java.io.File - -// TODO: use ProguardProject -protected class InstallExtractProject(info: ProjectInfo, pluginProject: => InstallPluginProject) extends DefaultProject(info) with NoPublish with ProguardProject -{ - override def unmanagedClasspath = super.unmanagedClasspath +++ info.sbtClasspath - override def rawPackage = `package` - override def rawJarPath = jarPath - - private lazy val plugin = pluginProject - val mainClassName = "sbt.extract.Main" - val defaultConfig = Configurations.Default - def outputJar = (plugin.outputPath ##) / defaultJarName - override val proguardConfigurationPath: Path = outputPath / "proguard.pro" - - /******** Proguard *******/ - override lazy val proguard = proguardTask dependsOn(`package`, writeProguardConfiguration, cleanProguard) - override lazy val writeProguardConfiguration = writeProguardConfigurationTask dependsOn `package` - lazy val cleanProguard = cleanTask(outputJar) - - override protected def writeProguardConfigurationTask = - task - { - // the template for the proguard configuration file - val outTemplate = """ - |-dontoptimize - |-dontobfuscate - |-dontnote - |-dontwarn - |-libraryjars "%s" - |%s - |-outjars "%s" - |-ignorewarnings - |-keep public class %s { - | public static void main(java.lang.String[]); - |}""" - - val defaultJar = mkpath(jarPath.absolutePath, '\"') - log.debug("proguard configuration using main jar " + defaultJar) - val externalDependencies = (mainCompileConditional.analysis.allExternals).map(_.getAbsoluteFile).filter(_.getName.endsWith(".jar")) - debugJars("external dependencies", externalDependencies) - // partition jars from the external jar dependencies of this project by whether they are located in the project directory - // if they are, they are specified with -injars, otherwise they are specified with -libraryjars - val (externalJars, libraryJars) = externalDependencies.toList.partition{jar => Path.relativize(rootProjectDirectory, jar).isDefined} - debugJars("library jars", libraryJars) - val externalJarStrings = externalJars.map( mkpath(_) + "(!META-INF/**,!*.properties)") - // exclude properties files and manifests from scala-library jar - val inJars = (defaultJar :: externalJarStrings).map("-injars " + _).mkString("\n") - - val proguardConfiguration = outTemplate.stripMargin.format(libraryJars.mkString(File.pathSeparator), inJars, outputJar.absolutePath, mainClassName) - log.debug("Proguard configuration written to " + proguardConfigurationPath) - FileUtilities.write(proguardConfigurationPath.asFile, proguardConfiguration, log) - } - - private def debugJars[T](label: String, jars: Iterable[T]): Unit = - log.debug("proguard configuration " + label + ": \n\t" + jars.mkString("\n\t")) -} \ No newline at end of file diff --git a/project/build/InstallerProject.scala b/project/build/InstallerProject.scala deleted file mode 100644 index fb67c3f74..000000000 --- a/project/build/InstallerProject.scala +++ /dev/null @@ -1,28 +0,0 @@ -/* sbt -- Simple Build Tool - * Copyright 2009 Mark Harrah - */ -import sbt._ - -abstract class InstallerProject(info: ProjectInfo) extends ParentProject(info) with NoPublish -{ - /** Project for the sbt plugin that a project uses to generate the installer jar. */ - lazy val installPlugin: InstallPluginProject = project("plugin", "Installer Plugin", new InstallPluginProject(_, installExtractor), installExtractor) - /** Project for the code that runs when the generated installer jar is run. */ - lazy val installExtractor: InstallExtractProject = project("extract", "Installer Extractor", new InstallExtractProject(_, installPlugin)) -} - -import java.nio.charset.Charset - -protected class InstallPluginProject(info: ProjectInfo, extract: => InstallExtractProject) extends PluginProject(info) -{ - private lazy val extractProject = extract - override def mainResources = super.mainResources +++ extractProject.outputJar +++ extractLocation - - def extractLocation = (outputPath ##) / "extract.location" - lazy val writeProperties = task { FileUtilities.write(extractLocation.asFile, extractProject.outputJar.relativePath, Charset.forName("UTF-8"), log) } - override def packageAction = super.packageAction dependsOn(extractProject.proguard, writeProperties) - - override def deliverProjectDependencies = Nil - val publishTo = "Scala Tools Nexus" at "http://nexus.scala-tools.org/content/repositories/releases/" - Credentials(Path.fromFile(System.getProperty("user.home")) / ".ivy2" / ".credentials", log) -} \ No newline at end of file diff --git a/project/build/LauncherProguard.scala b/project/build/LauncherProguard.scala deleted file mode 100644 index 432439a6d..000000000 --- a/project/build/LauncherProguard.scala +++ /dev/null @@ -1,72 +0,0 @@ -import sbt._ -import java.io.File - -trait ProguardLaunch extends ProguardProject -{ - override def optimize = 2 - override def basicOptions = super.basicOptions ++ Seq(keepJLine) - def outputJar = rootProject.outputPath / ("sbt-launch-" + version + ".jar") - override def keepFullClasses = - "xsbti.**" :: - "jline.**" :: - Nil - override def keepClasses = - "org.apache.ivy.plugins.resolver.URLResolver" :: - "org.apache.ivy.plugins.resolver.IBiblioResolver" :: - Nil - - override def mapInJars(inJars: Seq[File]) = - { - val inputJar = jarPath.asFile.getAbsolutePath - val jlineJars = runClasspath.getFiles.filter(isJLineJar) - // pull out Ivy in order to exclude resources inside - val (ivyJars, notIvy) = inJars.filter(jar => !isJLineJar(jar)).partition(isIvyJar) - val (libraryJar, remaining) = notIvy.partition(isScalaJar) - - val otherJars = remaining.filter(jar => !isJarX(jar, "scala-compiler")) - - log.debug("proguard configuration:") - log.debug("\tJLline jar location: " + jlineJars.mkString(", ")) - log.debug("\tIvy jar location: " + ivyJars.mkString(", ")) - log.debug("\tOther jars:\n\t" + otherJars.mkString("\n\t")) - val excludeIvyResourcesString = excludeString(excludeIvyResources) - ((withJar(ivyJars.toSeq, "Ivy") + excludeIvyResourcesString) :: - (withJar(jlineJars, "JLine") + jlineFilter ) :: - (withJar(libraryJar, "Scala library") + libraryFilter) :: - otherJars.map(jar => mkpath(jar) + generalFilter).toList) map { "-injars " + _ } - } - - private def excludeString(s: List[String]) = s.map("!" + _).mkString("(",",",")") - private def excludeIvyResources = - "META-INF/**" :: - "fr/**" :: - "**/antlib.xml" :: - "**/*.png" :: - "org/apache/ivy/core/settings/ivyconf*.xml" :: - "org/apache/ivy/core/settings/ivysettings-*.xml" :: - "org/apache/ivy/plugins/resolver/packager/*" :: - "**/ivy_vfs.xml" :: - "org/apache/ivy/plugins/report/ivy-report-*" :: - Nil - - private def libraryFilter = "(!META-INF/**,!*.properties,!scala/actors/**.!scala/util/parsing/*.class,!scala/xml/**.class,!scala/package$.class,**.class)" - private def jlineFilter = "(!META-INF/**)" - private def generalFilter = "(!META-INF/**,!*.properties)" - - private def withJar[T](files: Iterable[File], name: String) = mkpath(files.toSeq.firstOption.getOrElse(error(name + " not present (try running update)"))) - private def isJLineJar(file: File) = isJarX(file, "jline") - private def isIvyJar(file: File) = isJarX(file, "ivy") - private def isScalaJar(file: File) = isJarX(file, "scala-library") - private def isJarX(file: File, x: String) = - { - val name = file.getName - name.startsWith(x) && name.endsWith(".jar") - } - - private val keepJLine = - """ - |-keep public class jline.** { - | public protected *; - |} - |""".stripMargin -} diff --git a/project/build/ProguardProject.scala b/project/build/ProguardProject.scala deleted file mode 100644 index 339116fd2..000000000 --- a/project/build/ProguardProject.scala +++ /dev/null @@ -1,92 +0,0 @@ -package sbt - -import java.io.File - -object ProguardProject -{ - val ProguardDescription = "Produces the final compacted jar that contains only the minimum classes needed using proguard." - val WriteProguardDescription = "Creates the configuration file to use with proguard." -} -import ProguardProject._ -trait ProguardProject extends BasicScalaProject -{ - def rawJarPath: Path - def rawPackage: Task - - def proguardConfigurationPath: Path = outputPath / "proguard.pro" - def outputJar: Path - def rootProjectDirectory = rootProject.info.projectPath - - val toolsConfig = config("tools") hide - val proguardJar = "net.sf.proguard" % "proguard" % "4.4" % "tools" - - lazy val proguard = proguardAction - def proguardAction = proguardTask dependsOn(writeProguardConfiguration) describedAs(ProguardDescription) - lazy val writeProguardConfiguration = writeProguardConfigurationAction - def writeProguardConfigurationAction = writeProguardConfigurationTask dependsOn rawPackage describedAs WriteProguardDescription - - def basicOptions: Seq[String] = - Seq( - "-keep,allowoptimization,allowshrinking class * { *; }", - "-keepattributes SourceFile,LineNumberTable", - "-dontnote", - "-dontwarn", - "-ignorewarnings") ++ - optimizeOptions - - def keepFullClasses: Seq[String] = Nil - def keepClasses: Seq[String] = Nil - def optimize: Int = 0 - def optimizeOptions = if(optimize <= 0) Seq("-dontoptimize") else Seq( "-optimizationpasses 2", "-optimizations !code/allocation/variable") - - def mapInJars(inJars: Seq[File]): Seq[String] = inJars.map(f => "-injars " + mkpath(f)) - def mapLibraryJars(libraryJars: Seq[File]): Seq[String] = libraryJars.map(f => "-libraryjars " + mkpath(f)) - def mapOutJar(outJar: File) = "-outjars " + mkpath(outJar) - - def template(inJars: Seq[File], libraryJars: Seq[File], outJar: File, options: Seq[String], mainClass: Option[String], keepClasses: Seq[String]) = - { - val keepMain = - """-keep public class %s { - | public static void main(java.lang.String[]); - |}""" - - val lines = - options ++ - keepFullClasses.map("-keep public class " + _ + " {\n public protected * ;\n}") ++ - keepClasses.map("-keep class " + _ + " {}") ++ - mapInJars(inJars) ++ - Seq("-injars " + mkpath(rawJarPath.asFile), - mapOutJar(outJar)) ++ - mapLibraryJars(libraryJars) ++ - mainClass.map(main => keepMain.stripMargin.format(main)).toList - lines.mkString("\n") - } - - def mkpath(f: File) : String = mkpath(f.getAbsolutePath, '\"') - def mkpath(path: String, delimiter : Char) : String = delimiter + path + delimiter - protected def proguardTask = - task - { - FileUtilities.clean(outputJar :: Nil, log) - val proguardClasspathString = Path.makeString(managedClasspath(toolsConfig).get) - val configFile = mkpath(proguardConfigurationPath.asFile.getAbsolutePath, '\'') - val exitValue = Process("java", List("-Xmx256M", "-cp", proguardClasspathString, "proguard.ProGuard", "-include " + configFile)) ! log - if(exitValue == 0) None else Some("Proguard failed with nonzero exit code (" + exitValue + ")") - } - protected def writeProguardConfigurationTask = - task - { - val dependencies = mainDependencies.snapshot - log.debug("proguard configuration, all dependencies:\n\t" + dependencies.all.mkString("\n\t")) - val externalJars = dependencies.external - log.debug("proguard configuration external dependencies: \n\t" + externalJars.mkString("\n\t")) - // partition jars from the external jar dependencies of this project by whether they are located in the project directory - // if they are, they are specified with -injars, otherwise they are specified with -libraryjars - val libraryJars = dependencies.libraries ++ dependencies.scalaJars - log.debug("proguard configuration library jars locations:\n\t" + libraryJars.mkString("\n\t")) - - val proguardConfiguration = template(libraryJars, externalJars, outputJar.asFile, basicOptions, getMainClass(false), keepClasses) - log.debug("Proguard configuration written to " + proguardConfigurationPath) - FileUtilities.write(proguardConfigurationPath.asFile, proguardConfiguration, log) - } -} diff --git a/project/build/Sxr.scala b/project/build/Sxr.scala deleted file mode 100644 index ce00223c3..000000000 --- a/project/build/Sxr.scala +++ /dev/null @@ -1,24 +0,0 @@ -import sbt._ - -trait Sxr extends BasicScalaProject -{ - val sxrConf = config("sxr") hide - val sxrDep = "org.scala-tools.sxr" %% "sxr" % "0.2.7" % sxrConf.name jar() - - def deepSources: PathFinder - def deepBaseDirectories: PathFinder - def sxrBaseDirs = "-P:sxr:base-directory:" + deepBaseDirectories.absString - def sxrLocation = "-Xplugin:" + managedClasspath(sxrConf).absString - def sxrDirName = "browse" - def sxrOutput = outputPath / (sxrDirName + ".sxr") - def sxrClassesOutput = outputPath / sxrDirName // isn't actually written to, since compiler stops before writing classes - def sxrOptions = compileOptions.map(_.asString) ++ Seq(sxrBaseDirs, sxrLocation) - - lazy val sxr = task { - xsbt.FileUtilities.delete(sxrOutput +++ sxrClassesOutput getFiles) - xsbt.FileUtilities.createDirectory(sxrClassesOutput asFile) - val compiler = new xsbt.RawCompiler(buildScalaInstance, xsbt.ClasspathOptions.auto, log) - compiler(deepSources.getFiles, compileClasspath.getFiles, sxrClassesOutput asFile, sxrOptions) - None - } -} diff --git a/project/build/XSbt.scala b/project/build/XSbt.scala deleted file mode 100644 index 12f8a2036..000000000 --- a/project/build/XSbt.scala +++ /dev/null @@ -1,343 +0,0 @@ -import sbt._ - -import java.io.File - -class XSbt(info: ProjectInfo) extends ParentProject(info) with NoCrossPaths -{ - /*** Subproject declarations ***/ - - // defines the Java interfaces through which the launcher and the launched application communicate - val launchInterfaceSub = project(launchPath / "interface", "Launcher Interface", new LaunchInterfaceProject(_)) - - // the launcher. Retrieves, loads, and runs applications based on a configuration file. - val launchSub = project(launchPath, "Launcher", new LaunchProject(_), launchInterfaceSub) - - // defines Java structures used across Scala versions, such as the API structures and relationships extracted by - // 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 - val interfaceSub = project("interface", "Interface", new InterfaceProject(_)) - - // defines operations on the API of a source, including determining whether it has changed and converting it to a string - val apiSub = baseProject(compilePath / "api", "API", interfaceSub) - - /***** Utilities *****/ - - val controlSub = baseProject(utilPath / "control", "Control") - val collectionSub = testedBase(utilPath / "collection", "Collections") - // The API for forking, combining, and doing I/O with system processes - val processSub = project(utilPath / "process", "Process", new Base(_) with TestWithIO) - // Path, IO (formerly FileUtilities), NameFilter and other I/O utility classes - val ioSub = testedBase(utilPath / "io", "IO", controlSub) - // Utilities related to reflection, managing Scala versions, and custom class loaders - val classpathSub = baseProject(utilPath / "classpath", "Classpath", launchInterfaceSub, ioSub) - // Command line-related utilities. Currently, history. - val completeSub = project(utilPath / "complete", "Completion", new InputProject(_), collectionSub, controlSub, ioSub) - // logging - val logSub = project(utilPath / "log", "Logging", new LogProject(_), interfaceSub, processSub) - // class file reader and analyzer - val classfileSub = testedBase(utilPath / "classfile", "Classfile", ioSub, interfaceSub, logSub) - // generates immutable or mutable Java data types according to a simple input format - val datatypeSub = baseProject(utilPath /"datatype", "Datatype Generator", ioSub) - - /***** Intermediate-level Modules *****/ - - // Apache Ivy integration - val ivySub = project("ivy", "Ivy", new IvyProject(_), interfaceSub, launchInterfaceSub, logSub, ioSub) - // Runner for uniform test interface - val testingSub = project("testing", "Testing", new TestingProject(_), ioSub, classpathSub, logSub) - // Basic task engine - val taskSub = testedBase(tasksPath, "Tasks", controlSub, collectionSub) - // Persisted caching based on SBinary - val cacheSub = project(cachePath, "Cache", new CacheProject(_), ioSub, collectionSub) - // Builds on cache to provide caching for filesystem-related operations - val trackingSub = baseProject(cachePath / "tracking", "Tracking", cacheSub, ioSub) - // Embedded Scala code runner - val runSub = baseProject("run", "Run", ioSub, logSub, classpathSub, processSub) - - /***** compilation/discovery related modules *****/ - - // 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. - val compileInterfaceSub = project(compilePath / "interface", "Compiler Interface", new CompilerInterfaceProject(_), interfaceSub) - // 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 - val compileIncrementalSub = testedBase(compilePath / "inc", "Incremental Compiler", collectionSub, apiSub, ioSub, logSub) - // Persists the incremental data structures using SBinary - val compilePersistSub = project(compilePath / "persist", "Persist", new PersistProject(_), compileIncrementalSub, apiSub) - // sbt-side interface to compiler. Calls compiler-side interface reflectively - val compilerSub = project(compilePath, "Compile", new CompileProject(_), - launchInterfaceSub, interfaceSub, ivySub, ioSub, classpathSub, compileInterfaceSub, logSub) - // Searches the source API data structures, currently looks for subclasses and annotations - val discoverySub = project(compilePath / "discover", "Discovery", new DiscoveryProject(_), compileIncrementalSub, apiSub) - - val scriptedBaseSub = project("scripted" / "base", "Scripted Framework", new TestProject(_), ioSub, processSub) - val scriptedSbtSub = baseProject("scripted" / "sbt", "Scripted sbt", ioSub, logSub, processSub, scriptedBaseSub, launchInterfaceSub /*should really be a 'provided' dependency*/) - - // Standard task system. This provides map, flatMap, join, and more on top of the basic task model. - val stdTaskSub = testedBase(tasksPath / "standard", "Task System", taskSub, collectionSub, logSub, ioSub, processSub) - // Implementation and support code for defining actions. - val actionsSub = baseProject(mainPath / "actions", "Actions", - classfileSub, classpathSub, compileIncrementalSub, compilePersistSub, compilerSub, completeSub, discoverySub, - interfaceSub, ioSub, ivySub, logSub, processSub, runSub, stdTaskSub, taskSub, trackingSub, testingSub) - - // The main integration project for sbt. It brings all of the subsystems together, configures them, and provides for overriding conventions. - val mainSub = project(mainPath, "Main", new Main(_), actionsSub, interfaceSub, ioSub, ivySub, launchInterfaceSub, logSub, processSub, runSub) - // 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) - val sbtSub = project(sbtPath, "Simple Build Tool", new Sbt(_), mainSub) - val scriptedPluginSub = project("scripted" / "plugin", "Scripted Plugin", new Scripted(_), sbtSub, classpathSub) - - /** following modules are not updated for 2.8 or 0.9 */ - /* - val installerSub = project(sbtPath / "install", "Installer", new InstallerProject(_) {}, sbtSub) - lazy val dist = task { None } dependsOn(launchSub.proguard, sbtSub.publishLocal, installerSub.publishLocal)*/ - - def baseProject(path: Path, name: String, deps: Project*) = project(path, name, new Base(_), deps : _*) - def testedBase(path: Path, name: String, deps: Project*) = project(path, name, new TestedBase(_), deps : _*) - - /* Multi-subproject paths */ - def sbtPath = path("sbt") - def cachePath = path("cache") - def tasksPath = path("tasks") - def launchPath = path("launch") - def utilPath = path("util") - def compilePath = path("compile") - def mainPath = path("main") - - def compilerInterfaceClasspath = compileInterfaceSub.projectClasspath(Configurations.Test) - - //run in parallel - override def parallelExecution = true - - def jlineDep = "jline" % "jline" % "0.9.94" intransitive() - - override def managedStyle = ManagedStyle.Ivy - val publishTo = Resolver.url("typesafe-ivy-releases", new java.net.URL("http://typesafe.artifactoryonline.com/typesafe/ivy-releases/")) - val additional = publishTo - Credentials(Path.userHome / ".ivy2" / ".typesafe-credentials", log) - - /* Subproject configurations*/ - class LaunchProject(info: ProjectInfo) extends Base(info) with TestWithIO with TestDependencies with ProguardLaunch with NoCrossPaths - { - val jline = jlineDep - val ivy = "org.apache.ivy" % "ivy" % "2.2.0" - override def deliverProjectDependencies = Nil - - // defines the package that proguard operates on - def rawJarPath = jarPath - def rawPackage = `package` - override def packagePaths = super.packagePaths +++ launchInterfaceSub.packagePaths - - // configure testing - override def testClasspath = super.testClasspath +++ interfaceSub.compileClasspath +++ interfaceSub.mainResourcesPath - override def testCompileAction = super.testCompileAction dependsOn(interfaceSub.publishLocal, testSamples.publishLocal) - - // used to test the retrieving and loading of an application: sample app is packaged and published to the local repository - lazy val testSamples = project("test-sample", "Launch Test", new TestSamples(_), interfaceSub, launchInterfaceSub) - class TestSamples(info: ProjectInfo) extends Base(info) with NoCrossPaths with NoRemotePublish { - override def deliverProjectDependencies = Nil - } - } - class InputProject(info: ProjectInfo) extends TestedBase(info) - { - val jline = jlineDep - } - trait TestDependencies extends Project - { - val sc = "org.scala-tools.testing" %% "scalacheck" % "1.8" % "test" - val sp = "org.scala-tools.testing" %% "specs" % "1.6.8" % "test" - } - class LogProject(info: ProjectInfo) extends Base(info) with TestDependencies - { - val opt = Configurations.Optional - val jline = jlineDep % "optional" - } - class CacheProject(info: ProjectInfo) extends Base(info) with SBinaryDep - class PersistProject(info: ProjectInfo) extends Base(info) with SBinaryDep - { -// override def compileOptions = super.compileOptions ++ compileOptions("-Xlog-implicits") - } - trait SBinaryDep extends BasicManagedProject - { - // these compilation options are useful for debugging caches and task composition - //override def compileOptions = super.compileOptions ++ List(Unchecked,ExplainTypes, CompileOption("-Xlog-implicits")) - val sbinary = "org.scala-tools.sbinary" %% "sbinary" % "0.4.0" - } - class Base(info: ProjectInfo) extends DefaultProject(info) with ManagedBase with Component with Licensed - { - override def scratch = true - override def consoleClasspath = testClasspath - override def compileOptions = super.compileOptions ++ compileOptions("-Xelide-below", "0") - } - class TestedBase(info: ProjectInfo) extends Base(info) with TestDependencies - trait Licensed extends BasicScalaProject - { - def notice = path("NOTICE") - abstract override def mainResources = super.mainResources +++ notice +++ Path.lazyPathFinder( extractLicenses ) - lazy val seeRegex = """\(see (.*?)\)""".r - def licensePath(str: String): Path = { val path = Path.fromString(XSbt.this.info.projectPath, str); if(path.exists) path else error("Referenced license '" + str + "' not found at " + path) } - def seePaths(noticeString: String): List[Path] = seeRegex.findAllIn(noticeString).matchData.map(d => licensePath(d.group(1))).toList - def extractLicenses = if(!notice.exists) Nil else FileUtilities.readString(notice asFile, log).fold(_ => { log.warn("Could not read NOTICE"); Nil} , seePaths _) - } - class TestingProject(info: ProjectInfo) extends Base(info) - { - val testInterface = "org.scala-tools.testing" % "test-interface" % "0.5" - } - class DiscoveryProject(info: ProjectInfo) extends TestedBase(info) with TestWithCompile - class CompileProject(info: ProjectInfo) extends Base(info) with TestWithLog with TestWithLaunch with TestWithAPI - { - override def testCompileAction = super.testCompileAction dependsOn(compileInterfaceSub.`package`, interfaceSub.`package`) - override def testClasspath = super.testClasspath +++ compileInterfaceSub.packageSrcJar --- compilerInterfaceClasspath --- interfaceSub.mainCompilePath +++ interfaceSub.jarPath +++ buildCompilerJar - } - class IvyProject(info: ProjectInfo) extends Base(info) with TestWithIO with TestWithLog with TestWithLaunch - { - val ivy = "org.apache.ivy" % "ivy" % "2.2.0" - val jsch = "com.jcraft" % "jsch" % "0.1.31" intransitive() - } - abstract class BaseInterfaceProject(info: ProjectInfo) extends DefaultProject(info) with ManagedBase with TestWithLog with Component with JavaProject - class InterfaceProject(info: ProjectInfo) extends BaseInterfaceProject(info) - { - override def componentID: Option[String] = Some("xsbti") - override def packageAction = super.packageAction dependsOn generateVersions - def versionPropertiesPath = mainResourcesPath / "xsbt.version.properties" - lazy val generateVersions = task { - import java.util.{Date, TimeZone} - val formatter = new java.text.SimpleDateFormat("yyyyMMdd'T'HHmmss") - formatter.setTimeZone(TimeZone.getTimeZone("GMT")) - val timestamp = formatter.format(new Date) - val content = "version=" + version + "\ntimestamp=" + timestamp - log.info("Writing version information to " + versionPropertiesPath + " :\n" + content) - FileUtilities.write(versionPropertiesPath.asFile, content, log) - } - - override def watchPaths = super.watchPaths +++ apiDefinitionPaths --- sources(generatedBasePath) - override def mainSourceRoots = super.mainSourceRoots +++ (generatedBasePath ##) - def srcManagedPath = path("src_managed") - def generatedBasePath = srcManagedPath / "main" / "java" - /** Files that define the datatypes.*/ - def apiDefinitionPaths: PathFinder = "definition" - /** Delete up the generated sources*/ - lazy val cleanManagedSrc = cleanTask(srcManagedPath) - override def cleanAction = super.cleanAction dependsOn(cleanManagedSrc) - /** Runs the generator compiled by 'compile', putting the classes in src_managed and processing the definitions 'apiDefinitions'. */ - lazy val generateSource = generateSourceAction dependsOn(cleanManagedSrc, datatypeSub.compile) - def generateSourceTask(immutable: Boolean, pkg: String, apiDefinitions: PathFinder): Task = - { - val m = if(immutable) "immutable" else "mutable" - generateSourceTask(m :: pkg :: generatedBasePath.absolutePath :: apiDefinitions.get.toList.map(_.absolutePath)) - } - def generateSourceTask(args: List[String]): Task = - runTask(datatypeSub.getMainClass(true), datatypeSub.runClasspath, args) - def generateSourceAction = - //generateSourceTask(false, "xsbti.api", "definition" +++ "type") && - generateSourceTask(true, "xsbti.api", "other" +++ "definition" +++ "type") - /** compiles the generated sources */ - override def compileAction = super.compileAction dependsOn(generateSource) - } - class LaunchInterfaceProject(info: ProjectInfo) extends BaseInterfaceProject(info) - { - override def componentID = None - } - class Scripted(info: ProjectInfo) extends Base(info) - { - override def managedStyle = ManagedStyle.Ivy - override def scratch = true - } - class TestProject(info: ProjectInfo) extends Base(info) - { - val process = "org.scala-tools.sbt" % "process" % "0.1" - } - class CompilerInterfaceProject(info: ProjectInfo) extends Base(info) with PrecompiledInterface with NoCrossPaths with TestWithIO with TestWithLog - { cip => - //val jline = jlineDep artifacts(Artifact("jline", Map("e:component" -> srcID))) - // necessary because jline is not distributed with 2.8 and we will get a compile error - // sbt should work with the above inline declaration, but it doesn't, so the inline Ivy version is used for now. - override def ivyXML = - ( - - - - - ) - - def srcID = "compiler-interface-src" - lazy val srcArtifact = Artifact(srcID) extra("e:component" -> srcID) - override def packageSrcJar = mkJarPath(srcID) - lazy val pkgSrc = packageSrc // call it something else because we don't need dependencies to run package-src - override def packageAction = super.packageAction dependsOn(pkgSrc) - - // sub projects for each version of Scala to precompile against other than the one sbt is built against - // each sub project here will add ~100k to the download - lazy val precompiled29 = precompiledSub("2.9.0") - lazy val precompiled27 = precompiledSub("2.7.7") - - def precompiledSub(v: String) = - project(info.projectPath, "Precompiled " + v, new Precompiled(v)(_), cip.info.dependencies.toSeq : _* /*doesn't include subprojects of cip*/ ) - - /** A project that compiles the compiler interface against the Scala version 'sv'. - * This is done for selected Scala versions (generally, popular ones) so that it doesn't need to be done at runtime. */ - class Precompiled(sv: String)(info: ProjectInfo) extends Base(info) with PrecompiledInterface with NoUpdate { - /** force the Scala version in order to precompile the compiler interface for different Scala versions*/ - override def buildScalaVersion = sv - - /** Get compilation classpath from parent. Scala dependencies are added on top of this and this - * subproject does not depend on any Scala subprojects, so mixing versions is not a problem. */ - override def compileClasspath = cip.compileClasspath --- cip.mainUnmanagedClasspath +++ mainUnmanagedClasspath - - override def compileOptions = Nil - // these ensure that the classes compiled against other versions of Scala are not exported (for compilation/testing/...) - override def projectClasspath(config: Configuration) = Path.emptyPathFinder - } - } - trait TestWithAPI extends TestWith { - override def testWithTestClasspath = super.testWithTestClasspath ++ Seq(apiSub) - } - trait TestWithCompile extends TestWith { - override def testWithTestClasspath = super.testWithTestClasspath ++ Seq(compilerSub) - } - trait TestWithIO extends TestWith { - override def testWithTestClasspath = super.testWithTestClasspath ++ Seq(ioSub) - } - trait TestWithLaunch extends TestWith { - override def testWithTestClasspath = super.testWithTestClasspath ++ Seq(launchSub) - } - trait TestWithLog extends TestWith { - override def testWithCompileClasspath = super.testWithCompileClasspath ++ Seq(logSub) - } - trait TestWith extends BasicScalaProject - { - def testWithCompileClasspath: Seq[BasicScalaProject] = Nil - def testWithTestClasspath: Seq[BasicScalaProject] = Nil - override def testCompileAction = super.testCompileAction dependsOn((testWithTestClasspath.map(_.testCompile) ++ testWithCompileClasspath.map(_.compile)) : _*) - override def testClasspath = (super.testClasspath /: (testWithTestClasspath.map(_.testClasspath) ++ testWithCompileClasspath.map(_.compileClasspath) ))(_ +++ _) - } - class Sbt(info: ProjectInfo) extends Base(info) with TestWith with posterous.Publish - { - override def normalizedName = "sbt" - override def testWithCompileClasspath = super.testWithCompileClasspath ++ Seq(scriptedSbtSub) - override def testAction = super.testAction dependsOn(publishLocal) - def scriptedScalaVersions = "2.8.1" - lazy val scripted = task { args => task { - val launcher = launchSub.outputJar.asFile - val loader = ClasspathUtilities.toLoader(scriptedSbtSub.testClasspath, scriptedSbtSub.buildScalaInstance.loader) - val m = ModuleUtilities.getObject("sbt.test.ScriptedTests", loader) - val r = m.getClass.getMethod("run", classOf[File], classOf[Boolean], classOf[String], classOf[String], classOf[String], classOf[Array[String]], classOf[File]) - try { r.invoke(m, sourcePath / "sbt-test" asFile, true: java.lang.Boolean, version.toString, buildScalaVersion, scriptedScalaVersions, args, launcher) } - catch { case e: java.lang.reflect.InvocationTargetException => throw e.getCause } - None - } dependsOn(publishLocal, scriptedSbtSub.compile, testCompile) } - } - class Main(info: ProjectInfo) extends Base(info) with Sxr - { - def concatPaths[T](s: Seq[T])(f: PartialFunction[T, PathFinder]): PathFinder = - { - def finder: T => PathFinder = (f orElse { case _ => Path.emptyPathFinder }) - (Path.emptyPathFinder /: s) { _ +++ finder(_) } - } - def deepBaseDirectories = Path.finder { topologicalSort.flatMap { case p: ScalaPaths => p.mainSourceRoots.getFiles } } - def deepSources = concatPaths(mainSub.topologicalSort){ case p: ScalaPaths => p.mainSources } -// override def documentOptions = CompoundDocOption("-sourcepath", deepBaseDirectories.absString) :: LinkSource :: super.documentOptions.toList - lazy val sbtGenDoc = scaladocTask("sbt", deepSources, docPath, docClasspath, documentOptions) dependsOn(compile) - } -} diff --git a/project/plugins/Plugins.scala b/project/plugins/Plugins.scala deleted file mode 100644 index 89434667f..000000000 --- a/project/plugins/Plugins.scala +++ /dev/null @@ -1,6 +0,0 @@ -import sbt._ - -class Plugins(info: ProjectInfo) extends PluginDefinition(info) -{ - val posterous = "net.databinder" % "posterous-sbt" % "0.1.7" -} \ No newline at end of file diff --git a/util/datatype/DatatypeParser.scala b/util/datatype/DatatypeParser.scala index 1eddb163a..060527af0 100644 --- a/util/datatype/DatatypeParser.scala +++ b/util/datatype/DatatypeParser.scala @@ -2,7 +2,7 @@ * Copyright 2009 Mark Harrah */ package xsbt -package api +package datatype import java.io.File import sbt.IO.readLines diff --git a/util/datatype/Definition.scala b/util/datatype/Definition.scala index b5a2b59c5..ed787ae19 100644 --- a/util/datatype/Definition.scala +++ b/util/datatype/Definition.scala @@ -1,7 +1,7 @@ /* sbt -- Simple Build Tool * Copyright 2009 Mark Harrah */ -package xsbt.api +package xsbt.datatype sealed trait Definition extends NotNull { diff --git a/util/datatype/GenerateDatatypes.scala b/util/datatype/GenerateDatatypes.scala index 0ee9d0bb1..1c5dc100a 100644 --- a/util/datatype/GenerateDatatypes.scala +++ b/util/datatype/GenerateDatatypes.scala @@ -1,7 +1,7 @@ /* sbt -- Simple Build Tool * Copyright 2009, 2010 Mark Harrah */ -package xsbt.api +package xsbt.datatype import java.io.File diff --git a/util/datatype/Generator.scala b/util/datatype/Generator.scala index 3177b7f57..0e63cbbe8 100644 --- a/util/datatype/Generator.scala +++ b/util/datatype/Generator.scala @@ -2,7 +2,7 @@ * Copyright 2009, 2010 Mark Harrah */ package xsbt -package api +package datatype import java.io.File import sbt.Path diff --git a/util/datatype/Line.scala b/util/datatype/Line.scala index 39f5276b9..e4efbc442 100644 --- a/util/datatype/Line.scala +++ b/util/datatype/Line.scala @@ -1,7 +1,7 @@ /* sbt -- Simple Build Tool * Copyright 2009 Mark Harrah */ -package xsbt.api +package xsbt.datatype sealed trait Line extends NotNull { val line: Int } final class ClassLine(val name: String, val level: Int, val line: Int) extends Line