diff options
Diffstat (limited to 'project')
-rw-r--r-- | project/Build.scala | 280 | ||||
-rw-r--r-- | project/Packaging.scala | 129 | ||||
-rw-r--r-- | project/Release.scala | 27 | ||||
-rw-r--r-- | project/RemoteDependencies.scala | 53 | ||||
-rw-r--r-- | project/Sametest.scala | 3 | ||||
-rw-r--r-- | project/ScalaBuildKeys.scala | 35 | ||||
-rw-r--r-- | project/ScalaToolRunner.scala | 21 | ||||
-rw-r--r-- | project/ShaResolve.scala | 70 | ||||
-rw-r--r-- | project/Testing.scala | 41 |
9 files changed, 373 insertions, 286 deletions
diff --git a/project/Build.scala b/project/Build.scala index e2658e3405..58d322108b 100644 --- a/project/Build.scala +++ b/project/Build.scala @@ -1,12 +1,11 @@ import sbt._ import Keys._ import partest._ -import SameTest._ import ScalaBuildKeys._ +import Release._ - -object ScalaBuild extends Build with Layers { +object ScalaBuild extends Build with Layers with Packaging with Testing { // Build wide settings: override lazy val settings = super.settings ++ Versions.settings ++ Seq( @@ -21,36 +20,13 @@ object ScalaBuild extends Build with Layers { ), organization := "org.scala-lang", version <<= Versions.mavenVersion, - pomExtra := epflPomExtra, - commands += Command.command("fix-uri-projects") { (state: State) => - if(state.get(buildFixed) getOrElse false) state - else { - // TODO -fix up scalacheck's dependencies! - val extracted = Project.extract(state) - import extracted._ - def fix(s: Setting[_]): Setting[_] = s match { - case ScopedExternalSetting(`scalacheck`, scalaInstance.key, setting) => fullQuickScalaReference mapKey Project.mapScope(_ => s.key.scope) - case s => s - } - val transformed = session.mergeSettings map ( s => fix(s) ) - val scopes = transformed collect { case ScopedExternalSetting(`scalacheck`, _, s) => s.key.scope } toSet - // Create some fixers so we don't download scala or rely on it. - val fixers = for { scope <- scopes - setting <- Seq(autoScalaLibrary := false, crossPaths := false) - } yield setting mapKey Project.mapScope(_ => scope) - val newStructure = Load.reapply(transformed ++ fixers, structure) - Project.setProject(session, newStructure, state).put(buildFixed, true) - } - }, - onLoad in Global <<= (onLoad in Global) apply (_ andThen { (state: State) => - "fix-uri-projects" :: state - }) - ) + pomExtra := epflPomExtra + ) // Collections of projects to run 'compile' on. - lazy val compiledProjects = Seq(quickLib, quickComp, continuationsLibrary, actors, swing, forkjoin, fjbg) + lazy val compiledProjects = Seq(quickLib, quickComp, continuationsLibrary, actors, actorsMigration, swing, forkjoin, fjbg) // Collection of projects to 'package' and 'publish' together. - lazy val packagedBinaryProjects = Seq(scalaLibrary, scalaCompiler, swing, continuationsPlugin, jline, scalap) + lazy val packagedBinaryProjects = Seq(scalaLibrary, scalaCompiler, swing, actors, actorsMigration, continuationsPlugin, jline, scalap) lazy val partestRunProjects = Seq(testsuite, continuationsTestsuite) private def epflPomExtra = ( @@ -110,7 +86,6 @@ object ScalaBuild extends Build with Layers { }, // TODO - Make exported products == makeDist so we can use this when creating a *real* distribution. commands += Release.pushStarr - //commands += Release.setStarrHome ) // Note: Root project is determined by lowest-alphabetical project that has baseDirectory as file("."). we use aaa_ to 'win'. lazy val aaa_root = Project("scala", file(".")) settings(projectSettings: _*) settings(ShaResolve.settings: _*) @@ -123,6 +98,11 @@ object ScalaBuild extends Build with Layers { ) ) + def fixArtifactSrc(dir: File, name: String) = name match { + case x if x startsWith "scala-" => dir / "src" / (name drop 6) + case x => dir / "src" / name + } + // These are setting overrides for most artifacts in the Scala build file. def settingOverrides: Seq[Setting[_]] = publishSettings ++ Seq( crossPaths := false, @@ -134,9 +114,8 @@ object ScalaBuild extends Build with Layers { target <<= (baseDirectory, name) apply (_ / "target" / _), (classDirectory in Compile) <<= target(_ / "classes"), javacOptions ++= Seq("-target", "1.5", "-source", "1.5"), - scalaSource in Compile <<= (baseDirectory, name) apply (_ / "src" / _), - javaSource in Compile <<= (baseDirectory, name) apply (_ / "src" / _), - autoScalaLibrary := false, + scalaSource in Compile <<= (baseDirectory, name) apply fixArtifactSrc, + javaSource in Compile <<= (baseDirectory, name) apply fixArtifactSrc, unmanagedJars in Compile := Seq(), // Most libs in the compiler use this order to build. compileOrder in Compile := CompileOrder.JavaThenScala, @@ -187,6 +166,7 @@ object ScalaBuild extends Build with Layers { // Reference to quick scala instance. lazy val quickScalaInstance = makeScalaReference("quick", quickLib, quickReflect, quickComp) def quickScalaLibraryDependency = unmanagedClasspath in Compile <++= (exportedProducts in quickLib in Compile).identity + def quickScalaReflectDependency = unmanagedClasspath in Compile <++= (exportedProducts in quickReflect in Compile).identity def quickScalaCompilerDependency = unmanagedClasspath in Compile <++= (exportedProducts in quickComp in Compile).identity // Strapp is used to test binary 'sameness' between things built with locker and things built with quick. @@ -222,17 +202,18 @@ object ScalaBuild extends Build with Layers { } // TODO - in sabbus, these all use locker to build... I think tihs way is better, but let's farm this idea around. - // TODO - Actors + swing separate jars... lazy val dependentProjectSettings = settingOverrides ++ Seq(quickScalaInstance, quickScalaLibraryDependency, addCheaterDependency("scala-library")) - lazy val actors = Project("actors", file(".")) settings(dependentProjectSettings:_*) dependsOn(forkjoin % "provided") - // TODO - Remove actors dependency from pom... - lazy val swing = Project("swing", file(".")) settings(dependentProjectSettings:_*) dependsOn(actors % "provided") + lazy val actors = Project("scala-actors", file(".")) settings(dependentProjectSettings:_*) dependsOn(forkjoin % "provided") + lazy val swing = Project("scala-swing", file(".")) settings(dependentProjectSettings:_*) dependsOn(actors % "provided") + lazy val actorsMigration = Project("scala-actors-migration", file(".")) settings(dependentProjectSettings:_*) dependsOn(actors % "provided") // This project will generate man pages (in man1 and html) for scala. lazy val manmakerSettings: Seq[Setting[_]] = dependentProjectSettings :+ externalDeps lazy val manmaker = Project("manual", file(".")) settings(manmakerSettings:_*) // Things that compile against the compiler. - lazy val compilerDependentProjectSettings = dependentProjectSettings ++ Seq(quickScalaCompilerDependency, addCheaterDependency("scala-compiler")) + lazy val compilerDependentProjectSettings = dependentProjectSettings ++ Seq(quickScalaReflectDependency, quickScalaCompilerDependency, addCheaterDependency("scala-compiler")) + + lazy val scalacheck = Project("scalacheck", file(".")) settings(compilerDependentProjectSettings:_*) dependsOn(actors % "provided") lazy val partestSettings = compilerDependentProjectSettings :+ externalDeps lazy val partest = Project("partest", file(".")) settings(partestSettings:_*) dependsOn(actors,forkjoin,scalap) lazy val scalapSettings = compilerDependentProjectSettings ++ Seq( @@ -267,7 +248,7 @@ object ScalaBuild extends Build with Layers { // -------------------------------------------------------------- val allSubpathsCopy = (dir: File) => (dir.*** --- dir) x (relativeTo(dir)|flat) def productTaskToMapping(products : Seq[File]) = products flatMap { p => allSubpathsCopy(p) } - lazy val packageScalaLibBinTask = Seq(quickLib, continuationsLibrary, forkjoin, actors).map(p => products in p in Compile).join.map(_.flatten).map(productTaskToMapping) + lazy val packageScalaLibBinTask = Seq(quickLib, continuationsLibrary, forkjoin).map(p => products in p in Compile).join.map(_.flatten).map(productTaskToMapping) lazy val scalaLibArtifactSettings: Seq[Setting[_]] = inConfig(Compile)(Defaults.packageTasks(packageBin, packageScalaLibBinTask)) ++ Seq( name := "scala-library", crossPaths := false, @@ -282,14 +263,13 @@ object ScalaBuild extends Build with Layers { ) lazy val scalaLibrary = Project("scala-library", file(".")) settings(publishSettings:_*) settings(scalaLibArtifactSettings:_*) - // TODO - Real Reflect instance - // -------------------------------------------------------------- - // Real Compiler Artifact + // Real Reflect Artifact // -------------------------------------------------------------- - lazy val packageScalaBinTask = Seq(quickComp, fjbg, asm).map(p => products in p in Compile).join.map(_.flatten).map(productTaskToMapping) - lazy val scalaBinArtifactSettings : Seq[Setting[_]] = inConfig(Compile)(Defaults.packageTasks(packageBin, packageScalaBinTask)) ++ Seq( - name := "scala-compiler", + + lazy val packageScalaReflect = Seq(quickReflect).map(p => products in p in Compile).join.map(_.flatten).map(productTaskToMapping) + lazy val scalaReflectArtifactSettings : Seq[Setting[_]] = inConfig(Compile)(Defaults.packageTasks(packageBin, packageScalaReflect)) ++ Seq( + name := "scala-reflect", crossPaths := false, exportJars := true, autoScalaLibrary := false, @@ -298,52 +278,33 @@ object ScalaBuild extends Build with Layers { quickScalaInstance, target <<= (baseDirectory, name) apply (_ / "target" / _) ) - lazy val scalaCompiler = Project("scala-compiler", file(".")) settings(publishSettings:_*) settings(scalaBinArtifactSettings:_*) dependsOn(scalaLibrary) - lazy val fullQuickScalaReference = makeScalaReference("pack", scalaLibrary, quickReflect, scalaCompiler) + lazy val scalaReflect = Project("scala-reflect", file(".")) settings(publishSettings:_*) settings(scalaReflectArtifactSettings:_*) dependsOn(scalaLibrary) + // -------------------------------------------------------------- - // Testing + // Real Compiler Artifact // -------------------------------------------------------------- - /* lazy val scalacheckSettings: Seq[Setting[_]] = Seq(fullQuickScalaReference, crossPaths := false)*/ - lazy val scalacheck = uri("git://github.com/jsuereth/scalacheck.git#scala-build") - - lazy val testsuiteSettings: Seq[Setting[_]] = compilerDependentProjectSettings ++ partestTaskSettings ++ VerifyClassLoad.settings ++ Seq( - unmanagedBase <<= baseDirectory / "test/files/lib", - fullClasspath in VerifyClassLoad.checkClassLoad <<= (fullClasspath in scalaLibrary in Runtime).identity, + lazy val packageScalaBinTask = Seq(quickComp, fjbg, asm).map(p => products in p in Compile).join.map(_.flatten).map(productTaskToMapping) + lazy val scalaBinArtifactSettings : Seq[Setting[_]] = inConfig(Compile)(Defaults.packageTasks(packageBin, packageScalaBinTask)) ++ Seq( + name := "scala-compiler", + crossPaths := false, + exportJars := true, autoScalaLibrary := false, - checkSameLibrary <<= checkSameBinaryProjects(quickLib, strappLib), - checkSameCompiler <<= checkSameBinaryProjects(quickComp, strappComp), - checkSame <<= (checkSameLibrary, checkSameCompiler) map ((a,b) => ()), - autoScalaLibrary := false - ) - lazy val continuationsTestsuiteSettings: Seq[Setting[_]] = testsuiteSettings ++ Seq( - scalacOptions in Test <++= (exportedProducts in Compile in continuationsPlugin) map { - case Seq(cpDir) => Seq("-Xplugin-require:continuations", "-P:continuations:enable", "-Xplugin:"+cpDir.data.getAbsolutePath) - }, - partestDirs <<= baseDirectory apply { bd => - def mkFile(name: String) = bd / "test" / "files" / name - def mkTestType(name: String) = name.drop("continuations-".length).toString - Seq("continuations-neg", "continuations-run") map (t => mkTestType(t) -> mkFile(t)) toMap - } - ) - val testsuite = ( - Project("testsuite", file(".")) - settings (testsuiteSettings:_*) - dependsOn (swing, scalaLibrary, scalaCompiler, fjbg, partest, scalacheck) - ) - val continuationsTestsuite = ( - Project("continuations-testsuite", file(".")) - settings (continuationsTestsuiteSettings:_*) - dependsOn (partest, swing, scalaLibrary, scalaCompiler, fjbg) + unmanagedJars in Compile := Seq(), + fullClasspath in Runtime <<= (exportedProducts in Compile).identity, + quickScalaInstance, + target <<= (baseDirectory, name) apply (_ / "target" / _) ) + lazy val scalaCompiler = Project("scala-compiler", file(".")) settings(publishSettings:_*) settings(scalaBinArtifactSettings:_*) dependsOn(scalaReflect) + lazy val fullQuickScalaReference = makeScalaReference("pack", scalaLibrary, scalaReflect, scalaCompiler) + // -------------------------------------------------------------- // Generating Documentation. // -------------------------------------------------------------- // TODO - Migrate this into the dist project. // Scaladocs - def distScalaInstance = makeScalaReference("dist", scalaLibrary, quickReflect, scalaCompiler) lazy val documentationSettings: Seq[Setting[_]] = dependentProjectSettings ++ Seq( // TODO - Make these work for realz. defaultExcludes in unmanagedSources in Compile := ((".*" - ".") || HiddenFileFilter || @@ -373,163 +334,4 @@ object ScalaBuild extends Build with Layers { settings (documentationSettings: _*) dependsOn(quickLib, quickComp, actors, fjbg, forkjoin, swing, continuationsLibrary) ) - - // -------------------------------------------------------------- - // Packaging a distro - // -------------------------------------------------------------- - - class ScalaToolRunner(classpath: Classpath) { - // TODO - Don't use the ant task directly... - lazy val classLoader = new java.net.URLClassLoader(classpath.map(_.data.toURI.toURL).toArray, null) - lazy val mainClass = classLoader.loadClass("scala.tools.ant.ScalaTool") - lazy val executeMethod = mainClass.getMethod("execute") - lazy val setFileMethod = mainClass.getMethod("setFile", classOf[java.io.File]) - lazy val setClassMethod = mainClass.getMethod("setClass", classOf[String]) - lazy val setClasspathMethod = mainClass.getMethod("setClassPath", classOf[String]) - lazy val instance = mainClass.newInstance() - - def setClass(cls: String): Unit = setClassMethod.invoke(instance, cls) - def setFile(file: File): Unit = setFileMethod.invoke(instance, file) - def setClasspath(cp: String): Unit = setClasspathMethod.invoke(instance, cp) - def execute(): Unit = executeMethod.invoke(instance) - } - - def genBinTask( - runner: ScopedTask[ScalaToolRunner], - outputDir: ScopedSetting[File], - classpath: ScopedTask[Classpath], - useClasspath: Boolean - ): Project.Initialize[sbt.Task[Map[File,String]]] = { - (runner, outputDir, classpath, streams) map { (runner, outDir, cp, s) => - IO.createDirectory(outDir) - val classToFilename = Map( - "scala.tools.nsc.MainGenericRunner" -> "scala", - "scala.tools.nsc.Main" -> "scalac", - "scala.tools.nsc.ScalaDoc" -> "scaladoc", - "scala.tools.nsc.CompileClient" -> "fsc", - "scala.tools.scalap.Main" -> "scalap" - ) - if (useClasspath) { - val classpath = Build.data(cp).map(_.getCanonicalPath).distinct.mkString(",") - s.log.debug("Setting classpath = " + classpath) - runner setClasspath classpath - } - def genBinFiles(cls: String, dest: File) = { - runner.setClass(cls) - runner.setFile(dest) - runner.execute() - // TODO - Mark generated files as executable (755 or a+x) that is *not* JDK6 specific... - dest.setExecutable(true) - } - def makeBinMappings(cls: String, binName: String): Map[File,String] = { - val file = outDir / binName - val winBinName = binName + ".bat" - genBinFiles(cls, file) - Map( file -> ("bin/"+binName), outDir / winBinName -> ("bin/"+winBinName) ) - } - classToFilename.flatMap((makeBinMappings _).tupled).toMap - } - } - def runManmakerTask(classpath: ScopedTask[Classpath], scalaRun: ScopedTask[ScalaRun], mainClass: String, dir: String, ext: String): Project.Initialize[Task[Map[File,String]]] = - (classpath, scalaRun, streams, target) map { (cp, runner, s, target) => - val binaries = Seq("fsc", "scala", "scalac", "scaladoc", "scalap") - binaries map { bin => - val file = target / "man" / dir / (bin + ext) - val classname = "scala.man1." + bin - IO.createDirectory(file.getParentFile) - toError(runner.run(mainClass, Build.data(cp), Seq(classname, file.getAbsolutePath), s.log)) - file -> ("man/" + dir + "/" + bin + ext) - } toMap - } - - val genBinRunner = TaskKey[ScalaToolRunner]("gen-bin-runner", - "Creates a utility to generate script files for Scala.") - val genBin = TaskKey[Map[File,String]]("gen-bin", - "Creates script files for Scala distribution.") - val binDir = SettingKey[File]("binaries-directory", - "Directory where binary scripts will be located.") - val genBinQuick = TaskKey[Map[File,String]]("gen-quick-bin", - "Creates script files for testing against current Scala build classfiles (not local dist).") - val runManmakerMan = TaskKey[Map[File,String]]("make-man", - "Runs the man maker project to generate man pages") - val runManmakerHtml = TaskKey[Map[File,String]]("make-html", - "Runs the man maker project to generate html pages") - - lazy val scalaDistSettings: Seq[Setting[_]] = Seq( - crossPaths := false, - target <<= (baseDirectory, name) apply (_ / "target" / _), - scalaSource in Compile <<= (baseDirectory, name) apply (_ / "src" / _), - autoScalaLibrary := false, - unmanagedJars in Compile := Seq(), - genBinRunner <<= (fullClasspath in quickComp in Runtime) map (new ScalaToolRunner(_)), - binDir <<= target(_/"bin"), - genBin <<= genBinTask(genBinRunner, binDir, fullClasspath in Runtime, false), - binDir in genBinQuick <<= baseDirectory apply (_ / "target" / "bin"), - // Configure the classpath this way to avoid having .jar files and previous layers on the classpath. - fullClasspath in Runtime in genBinQuick <<= Seq(quickComp,quickLib,scalap,actors,swing,fjbg,jline,forkjoin).map(classDirectory in Compile in _).join.map(Attributed.blankSeq), - fullClasspath in Runtime in genBinQuick <++= (fullClasspath in Compile in jline), - genBinQuick <<= genBinTask(genBinRunner, binDir in genBinQuick, fullClasspath in Runtime in genBinQuick, true), - runManmakerMan <<= runManmakerTask(fullClasspath in Runtime in manmaker, runner in manmaker, "scala.tools.docutil.EmitManPage", "man1", ".1"), - runManmakerHtml <<= runManmakerTask(fullClasspath in Runtime in manmaker, runner in manmaker, "scala.tools.docutil.EmitHtml", "doc", ".html"), - // TODO - We could *really* clean this up in many ways. Let's look into making a a Seq of "direct jars" (scalaLibrary, scalaCompiler, jline, scalap) - // a seq of "plugin jars" (continuationsPlugin) and "binaries" (genBin) and "documentation" mappings (genBin) that this can aggregate. - // really need to figure out a better way to pull jline + jansi. - makeDistMappings <<= (genBin, - runManmakerMan, - runManmakerHtml, - packageBin in scalaLibrary in Compile, - packageBin in scalaCompiler in Compile, - packageBin in jline in Compile, - packageBin in continuationsPlugin in Compile, - managedClasspath in jline in Compile, - packageBin in scalap in Compile) map { - (binaries, man, html, lib, comp, jline, continuations, jlineDeps, scalap) => - val jlineDepMap: Seq[(File, String)] = jlineDeps.map(_.data).flatMap(_ x Path.flat) map { case(a,b) => a -> ("lib/"+b) } - binaries ++ man ++ html ++ jlineDepMap ++ Seq( - lib -> "lib/scala-library.jar", - comp -> "lib/scala-compiler.jar", - jline -> "lib/jline.jar", - continuations -> "misc/scala-devel/plugins/continuations.jar", - scalap -> "lib/scalap.jar" - ) toMap - }, - // Add in some more dependencies - makeDistMappings <<= (makeDistMappings, - packageBin in swing in Compile) map { - (dist, s) => - dist ++ Seq(s -> "lib/scala-swing.jar") - }, - makeDist <<= (makeDistMappings, baseDirectory, streams) map { (maps, dir, s) => - s.log.debug("Map = " + maps.mkString("\n")) - val file = dir / "target" / "scala-dist.zip" - IO.zip(maps, file) - s.log.info("Created " + file.getAbsolutePath) - file - }, - makeExplodedDist <<= (makeDistMappings, target, streams) map { (maps, dir, s) => - def sameFile(f: File, f2: File) = f.getCanonicalPath == f2.getCanonicalPath - IO.createDirectory(dir) - IO.copy(for { - (file, name) <- maps - val file2 = dir / name - if !sameFile(file,file2) - } yield (file, file2)) - // Hack to make binaries be executable. TODO - Fix for JDK 5 and below... - maps.values filter (_ startsWith "bin/") foreach (dir / _ setExecutable true) - dir - } - ) - lazy val scaladist = ( - Project("dist", file(".")) - settings (scalaDistSettings: _*) - ) -} - -/** Matcher to make updated remote project references easier. */ -object ScopedExternalSetting { - def unapply[T](s: Setting[_]): Option[(URI, AttributeKey[_], Setting[_])] = - s.key.scope.project match { - case Select(p @ ProjectRef(uri, _)) => Some((uri, s.key.key, s)) - case _ => None - } } diff --git a/project/Packaging.scala b/project/Packaging.scala new file mode 100644 index 0000000000..eb4e69f99e --- /dev/null +++ b/project/Packaging.scala @@ -0,0 +1,129 @@ +import sbt._ +import Keys._ +import ScalaBuildKeys._ + +/** All the settings related to *packaging* the built scala software. */ +trait Packaging { self: ScalaBuild.type => + + // -------------------------------------------------------------- + // Packaging a distro + // -------------------------------------------------------------- + lazy val scalaDistSettings: Seq[Setting[_]] = Seq( + crossPaths := false, + target <<= (baseDirectory, name) apply (_ / "target" / _), + scalaSource in Compile <<= (baseDirectory, name) apply (_ / "src" / _), + autoScalaLibrary := false, + unmanagedJars in Compile := Seq(), + genBinRunner <<= (fullClasspath in quickComp in Runtime) map (new ScalaToolRunner(_)), + binDir <<= target(_/"bin"), + genBin <<= genBinTask(genBinRunner, binDir, fullClasspath in Runtime, false), + binDir in genBinQuick <<= baseDirectory apply (_ / "target" / "bin"), + // Configure the classpath this way to avoid having .jar files and previous layers on the classpath. + fullClasspath in Runtime in genBinQuick <<= Seq(quickComp,quickLib,scalap,actors,swing,fjbg,jline,forkjoin).map(classDirectory in Compile in _).join.map(Attributed.blankSeq), + fullClasspath in Runtime in genBinQuick <++= (fullClasspath in Compile in jline), + genBinQuick <<= genBinTask(genBinRunner, binDir in genBinQuick, fullClasspath in Runtime in genBinQuick, true), + runManmakerMan <<= runManmakerTask(fullClasspath in Runtime in manmaker, runner in manmaker, "scala.tools.docutil.EmitManPage", "man1", ".1"), + runManmakerHtml <<= runManmakerTask(fullClasspath in Runtime in manmaker, runner in manmaker, "scala.tools.docutil.EmitHtml", "doc", ".html"), + // TODO - We could *really* clean this up in many ways. Let's look into making a a Seq of "direct jars" (scalaLibrary, scalaCompiler, jline, scalap) + // a seq of "plugin jars" (continuationsPlugin) and "binaries" (genBin) and "documentation" mappings (genBin) that this can aggregate. + // really need to figure out a better way to pull jline + jansi. + makeDistMappings <<= (genBin, + runManmakerMan, + runManmakerHtml, + packageBin in scalaLibrary in Compile, + packageBin in scalaCompiler in Compile, + packageBin in jline in Compile, + packageBin in continuationsPlugin in Compile, + managedClasspath in jline in Compile, + packageBin in scalap in Compile) map { + (binaries, man, html, lib, comp, jline, continuations, jlineDeps, scalap) => + val jlineDepMap: Seq[(File, String)] = jlineDeps.map(_.data).flatMap(_ x Path.flat) map { case(a,b) => a -> ("lib/"+b) } + binaries ++ man ++ html ++ jlineDepMap ++ Seq( + lib -> "lib/scala-library.jar", + comp -> "lib/scala-compiler.jar", + jline -> "lib/jline.jar", + continuations -> "misc/scala-devel/plugins/continuations.jar", + scalap -> "lib/scalap.jar" + ) + }, + // Add in some more dependencies + makeDistMappings <+= (packageBin in swing in Compile) map (s => s -> "lib/scala-swing.jar"), + makeDistMappings <+= (packageBin in scalaReflect in Compile) map (s => s -> "lib/scala-reflect.jar"), + makeDist <<= (makeDistMappings, baseDirectory, streams) map { (maps, dir, s) => + s.log.debug("Map = " + maps.mkString("\n")) + val file = dir / "target" / "scala-dist.zip" + IO.zip(maps, file) + s.log.info("Created " + file.getAbsolutePath) + file + }, + makeExplodedDist <<= (makeDistMappings, target, streams) map { (maps, dir, s) => + def sameFile(f: File, f2: File) = f.getCanonicalPath == f2.getCanonicalPath + IO.createDirectory(dir) + IO.copy(for { + (file, name) <- maps + val file2 = dir / name + if !sameFile(file,file2) + } yield (file, file2)) + // Hack to make binaries be executable. TODO - Fix for JDK 5 and below... + maps map (_._2) filter (_ startsWith "bin/") foreach (dir / _ setExecutable true) + dir + } + ) + lazy val scaladist = ( + Project("dist", file(".")) + settings (scalaDistSettings: _*) + ) + + +// Helpers to make a distribution + + /** Generates runner scripts for distribution. */ + def genBinTask( + runner: ScopedTask[ScalaToolRunner], + outputDir: ScopedSetting[File], + classpath: ScopedTask[Classpath], + useClasspath: Boolean + ): Project.Initialize[sbt.Task[Seq[(File,String)]]] = { + (runner, outputDir, classpath, streams) map { (runner, outDir, cp, s) => + IO.createDirectory(outDir) + val classToFilename = Seq( + "scala.tools.nsc.MainGenericRunner" -> "scala", + "scala.tools.nsc.Main" -> "scalac", + "scala.tools.nsc.ScalaDoc" -> "scaladoc", + "scala.tools.nsc.CompileClient" -> "fsc", + "scala.tools.scalap.Main" -> "scalap" + ) + if (useClasspath) { + val classpath = Build.data(cp).map(_.getCanonicalPath).distinct.mkString(",") + s.log.debug("Setting classpath = " + classpath) + runner setClasspath classpath + } + def genBinFiles(cls: String, dest: File) = { + runner.setClass(cls) + runner.setFile(dest) + runner.execute() + // TODO - Mark generated files as executable (755 or a+x) that is *not* JDK6 specific... + dest.setExecutable(true) + } + def makeBinMappings(cls: String, binName: String): Seq[(File,String)] = { + val file = outDir / binName + val winBinName = binName + ".bat" + genBinFiles(cls, file) + Seq( file -> ("bin/"+binName), outDir / winBinName -> ("bin/"+winBinName) ) + } + classToFilename.flatMap((makeBinMappings _).tupled) + } + } + /** Creates man pages for distribution. */ + def runManmakerTask(classpath: ScopedTask[Classpath], scalaRun: ScopedTask[ScalaRun], mainClass: String, dir: String, ext: String): Project.Initialize[Task[Seq[(File,String)]]] = + (classpath, scalaRun, streams, target) map { (cp, runner, s, target) => + val binaries = Seq("fsc", "scala", "scalac", "scaladoc", "scalap") + binaries map { bin => + val file = target / "man" / dir / (bin + ext) + val classname = "scala.man1." + bin + IO.createDirectory(file.getParentFile) + toError(runner.run(mainClass, Build.data(cp), Seq(classname, file.getAbsolutePath), s.log)) + file -> ("man/" + dir + "/" + bin + ext) + } + } +} diff --git a/project/Release.scala b/project/Release.scala index 1a17956c13..feab8bdc8c 100644 --- a/project/Release.scala +++ b/project/Release.scala @@ -5,11 +5,26 @@ object Release { // TODO - Just make the STARR artifacts and dump the sha1 files. + val starrLibs = Seq("scala-library.jar", "scala-reflect.jar", "scala-compiler.jar", "jline.jar") - lazy val pushStarr = Command.command("push-starr") { (state: State) => - // TODO do something - // Revert to previous project state. - state - } - + val pushStarr = Command.command("new-starr") { (state: State) => + /*val extracted = Project.extract(state) + import extracted._ + // First run tests + val (s1, result) = runTask(test in Test, state) + // If successful, package artifacts + val (s2, distDir) = runTask(makeExplodedDist, s1) + // Then copy new libs in place + val bd = extracted get baseDirectory + for { + jarName <- starrLibs + jar = distDir / "lib" / jarName + if jar.exists + } IO.copyFile(jar, bd / "lib" / jarName) + // Invalidate SHA1 files. + ShaResolve.removeInvalidShaFiles(bd) + // Now run tests *again*? + s2*/ + state + } } diff --git a/project/RemoteDependencies.scala b/project/RemoteDependencies.scala new file mode 100644 index 0000000000..705b9dc402 --- /dev/null +++ b/project/RemoteDependencies.scala @@ -0,0 +1,53 @@ +import sbt._ +import Keys._ +import ScalaBuildKeys._ + + +object RemoteDependencies { + def buildSettings(externalProjects: Set[URI], localScala: Setting[_]): Seq[Setting[_]] = Seq( + commands += Command.command("fix-uri-projects") { (state: State) => + if(state.get(buildFixed) getOrElse false) state + else { + // TODO -fix up scalacheck's dependencies! + val extracted = Project.extract(state) + import extracted._ + val scalaVersionString = extracted get version + + def fix(s: Setting[_]): Setting[_] = s match { + case ScopedExternalSetting(p, scalaInstance.key, setting) if externalProjects(p) => localScala mapKey Project.mapScope(_ => s.key.scope) + // TODO - Fix Actors dependency... + //case ScopedExternalSetting(p, libraryDependencies.key, setting) if externalProjects(p) => fixProjectDeps(s) + case s => s + } + val transformed = session.mergeSettings map ( s => fix(s) ) + val scopes = transformed collect { case ScopedExternalSetting(p, _, s) if externalProjects(p) => s.key.scope } toSet + // Create some fixers so we don't download scala or rely on it. + // Also add dependencies that disappear in 2.10 for now... + val fixers = for { scope <- scopes + setting <- Seq(autoScalaLibrary := false, + crossPaths := false, + scalaVersion := scalaVersionString) + } yield setting mapKey Project.mapScope(_ => scope) + val newStructure = Load.reapply(transformed ++ fixers, structure) + Project.setProject(session, newStructure, state).put(buildFixed, true) + } + }, + onLoad in Global <<= (onLoad in Global) apply (_ andThen { (state: State) => + "fix-uri-projects" :: state + }) + ) +} + + + +/** Matcher to make updated remote project references easier. */ +object ScopedExternalSetting { + def unapply[T](s: Setting[_]): Option[(URI, AttributeKey[_], Setting[_])] = + s.key.scope.project match { + case Select(p @ ProjectRef(uri, _)) => Some((uri, s.key.key, s)) + case _ => None + } +} + + + diff --git a/project/Sametest.scala b/project/Sametest.scala index f44fe8ec65..6f12eb24b3 100644 --- a/project/Sametest.scala +++ b/project/Sametest.scala @@ -5,9 +5,6 @@ import Keys._ // This code is adapted from scala.tools.ant.Same by Gilles Dubochet. object SameTest { - lazy val checkSame: TaskKey[Unit] = TaskKey("check-same-binaries", "checks whether or not the class files generated by scala are the same.") - lazy val checkSameLibrary: TaskKey[Unit] = TaskKey("check-same-lib-binaries", "checks whether or not the librayr class files generated by scala are the same.") - lazy val checkSameCompiler: TaskKey[Unit] = TaskKey("check-same-comp-binaries", "checks whether or not the compiler class files generated by scala are the same.") def checkSameBinaryProjects(lhs: Project, rhs: Project): Project.Initialize[Task[Unit]] = (classDirectory in Compile in lhs, classDirectory in Compile in rhs, diff --git a/project/ScalaBuildKeys.scala b/project/ScalaBuildKeys.scala index dbde6bd18c..9e495de19f 100644 --- a/project/ScalaBuildKeys.scala +++ b/project/ScalaBuildKeys.scala @@ -2,21 +2,22 @@ import sbt._ import Keys._ object ScalaBuildKeys { - val lockerLock: TaskKey[Unit] = TaskKey("locker-lock", - "Locks the locker layer of the compiler build such that it won't rebuild on changed source files.") - val lockerUnlock: TaskKey[Unit] = TaskKey("locker-unlock", - "Unlocks the locker layer of the compiler so that it will be recompiled on changed source files.") - val lockFile: SettingKey[File] = SettingKey("lock-file", - "Location of the lock file compiling this project.") - // New tasks/settings specific to the scala build. - val lock: TaskKey[Unit] = TaskKey("lock", "Locks this project so it won't be recompiled.") - val unlock: TaskKey[Unit] = TaskKey("unlock", "Unlocks this project so it will be recompiled.") - val makeDist: TaskKey[File] = TaskKey("make-dist", - "Creates a mini-distribution (scala home directory) for this build in a zip file.") - val makeExplodedDist: TaskKey[File] = TaskKey("make-exploded-dist", - "Creates a mini-distribution (scala home directory) for this build in a directory.") - val makeDistMappings: TaskKey[Map[File, String]] = TaskKey("make-dist-mappings", - "Creates distribution mappings for creating zips,jars,directorys,etc.") - val buildFixed = AttributeKey[Boolean]("build-uri-fixed") - + val lockerLock = TaskKey[Unit]("locker-lock", "Locks the locker layer of the compiler build such that it won't rebuild on changed source files.") + val lockerUnlock = TaskKey[Unit]("locker-unlock", "Unlocks the locker layer of the compiler so that it will be recompiled on changed source files.") + val lockFile = SettingKey[File]("lock-file", "Location of the lock file compiling this project.") + val lock = TaskKey[Unit]("lock", "Locks this project so it won't be recompiled.") + val unlock = TaskKey[Unit]("unlock", "Unlocks this project so it will be recompiled.") + val makeDist = TaskKey[File]("make-dist", "Creates a mini-distribution (scala home directory) for this build in a zip file.") + val makeExplodedDist = TaskKey[File]("make-exploded-dist", "Creates a mini-distribution (scala home directory) for this build in a directory.") + val makeDistMappings = TaskKey[Seq[(File, String)]]("make-dist-mappings", "Creates distribution mappings for creating zips,jars,directorys,etc.") + val buildFixed = AttributeKey[Boolean]("build-uri-fixed") + val genBinRunner = TaskKey[ScalaToolRunner]("gen-bin-runner", "Creates a utility to generate script files for Scala.") + val genBin = TaskKey[Seq[(File,String)]]("gen-bin", "Creates script files for Scala distribution.") + val binDir = SettingKey[File]("binaries-directory", "Directory where binary scripts will be located.") + val genBinQuick = TaskKey[Seq[(File,String)]]("gen-quick-bin", "Creates script files for testing against current Scala build classfiles (not local dist).") + val runManmakerMan = TaskKey[Seq[(File,String)]]("make-man", "Runs the man maker project to generate man pages") + val runManmakerHtml = TaskKey[Seq[(File,String)]]("make-html", "Runs the man maker project to generate html pages") + val checkSame = TaskKey[Unit]("check-same-binaries", "checks whether or not the class files generated by scala are the same.") + val checkSameLibrary = TaskKey[Unit]("check-same-lib-binaries", "checks whether or not the librayr class files generated by scala are the same.") + val checkSameCompiler = TaskKey[Unit]("check-same-comp-binaries", "checks whether or not the compiler class files generated by scala are the same.") } diff --git a/project/ScalaToolRunner.scala b/project/ScalaToolRunner.scala new file mode 100644 index 0000000000..d7338a54b3 --- /dev/null +++ b/project/ScalaToolRunner.scala @@ -0,0 +1,21 @@ +import sbt._ +import Keys._ + +/** Reflection helper that runs ScalaTool. + * TODO - When SBT is on 2.10.x try to use Dynamic + Reflection. COULD BE FUN. + */ +class ScalaToolRunner(classpath: Classpath) { + // TODO - Don't use the ant task directly... + lazy val classLoader = new java.net.URLClassLoader(classpath.map(_.data.toURI.toURL).toArray, null) + lazy val mainClass = classLoader.loadClass("scala.tools.ant.ScalaTool") + lazy val executeMethod = mainClass.getMethod("execute") + lazy val setFileMethod = mainClass.getMethod("setFile", classOf[java.io.File]) + lazy val setClassMethod = mainClass.getMethod("setClass", classOf[String]) + lazy val setClasspathMethod = mainClass.getMethod("setClassPath", classOf[String]) + lazy val instance = mainClass.newInstance() + + def setClass(cls: String): Unit = setClassMethod.invoke(instance, cls) + def setFile(file: File): Unit = setFileMethod.invoke(instance, file) + def setClasspath(cp: String): Unit = setClasspathMethod.invoke(instance, cp) + def execute(): Unit = executeMethod.invoke(instance) +} diff --git a/project/ShaResolve.scala b/project/ShaResolve.scala index e6824ee464..cea2b2d6cc 100644 --- a/project/ShaResolve.scala +++ b/project/ShaResolve.scala @@ -7,6 +7,7 @@ import scala.collection.{ mutable, immutable } import scala.collection.parallel.CompositeThrowable import java.security.MessageDigest +case class Credentials(user: String, pw: String) /** Helpers to resolve SHA artifacts from typesafe repo. */ object ShaResolve { @@ -19,7 +20,8 @@ object ShaResolve { def settings: Seq[Setting[_]] = Seq( binaryLibCache in ThisBuild := file(System.getProperty("user.home")) / ".sbt" / "cache" / "scala", - pullBinaryLibs in ThisBuild <<= (baseDirectory, binaryLibCache, streams) map resolveLibs + pullBinaryLibs in ThisBuild <<= (baseDirectory, binaryLibCache, streams) map resolveLibs, + pushBinaryLibs in ThisBuild <<= (baseDirectory, streams) map getCredentialsAndPushFiles ) def resolveLibs(dir: File, cacheDir: File, s: TaskStreams): Unit = loggingParallelExceptions(s) { @@ -33,6 +35,34 @@ object ShaResolve { } pullFile(jar, sha + "/" + uri, cacheDir, sha, s) } + /** This method removes all SHA1 files that don't match their corresponding JAR. */ + def removeInvalidShaFiles(dir: File): Unit = { + val files = (dir / "test" / "files" ** "*.desired.sha1") +++ (dir / "lib" ** "*.desired.sha1") + for { + (file, name) <- (files x relativeTo(dir)).par + uri = name.dropRight(13).replace('\\', '/') + jar = dir / uri + if !jar.exists || !isValidSha(file) + } IO.delete(jar) + } + def getCredentials: Credentials = System.out.synchronized { + val user = (SimpleReader.readLine("Please enter your STARR username> ") getOrElse error("No username provided.")) + val password = (SimpleReader.readLine("Please enter your STARR password> ", Some('*')) getOrElse error("No password provided.")) + Credentials(user, password) + } + + def getCredentialsAndPushFiles(dir: File, s: TaskStreams): Unit = + pushFiles(dir, getCredentials, s) + + def pushFiles(dir: File, cred: Credentials, s: TaskStreams): Unit = loggingParallelExceptions(s) { + val files = (dir / "test" / "files" ** "*.jar") +++ (dir / "lib" ** "*.jar") + for { + (jar, name) <- (files x relativeTo(dir)).par + shafile = dir / (name + ".desired.sha1") + if !shafile.exists || !isValidSha(shafile) + } pushFile(jar, name, cred, s) + } + @inline final def loggingParallelExceptions[U](s: TaskStreams)(f: => U): U = try f catch { case t: CompositeThrowable => s.log.error("Error during parallel execution, GET READY FOR STACK TRACES!!") @@ -60,24 +90,17 @@ object ShaResolve { sha } - // TODO - Prettier way of doing this... - private def convertToHex(data: Array[Byte]): String = { + def convertToHex(data: Array[Byte]): String = { + def byteToHex(b: Int) = + if ((0 <= b) && (b <= 9)) ('0' + b).toChar + else ('a' + (b-10)).toChar val buf = new StringBuffer - for (i <- 0 until data.length) { - var halfbyte = (data(i) >>> 4) & 0x0F; - var two_halfs = 0; - while(two_halfs < 2) { - if ((0 <= halfbyte) && (halfbyte <= 9)) - buf.append(('0' + halfbyte).toChar) - else - buf.append(('a' + (halfbyte - 10)).toChar); - halfbyte = data(i) & 0x0F; - two_halfs += 1 - } - } - return buf.toString - } - + for (i <- 0 until data.length) { + buf append byteToHex((data(i) >>> 4) & 0x0F) + buf append byteToHex(data(i) & 0x0F) + } + buf.toString + } // Parses a sha file into a file and a sha. def parseShaFile(file: File): (File, String) = IO.read(file).split("\\s") match { @@ -110,10 +133,15 @@ object ShaResolve { IO.copyFile(cachedFile, file) } - def pushFile(file: File, uri: String, user: String, pw: String): Unit = { - val url = remote_urlbase + "/" + uri - val sender = dispatch.url(url).PUT.as(user,pw) <<< (file, "application/java-archive") + // Pushes a file and writes the new .desired.sha1 for git. + def pushFile(file: File, uri: String, cred: Credentials, s: TaskStreams): Unit = { + val sha = calculateSha(file) + val url = remote_urlbase + "/" + sha + "/" + uri + val sender = dispatch.url(url).PUT.as(cred.user,cred.pw) <<< (file, "application/java-archive") // TODO - output to logger. Http(sender >>> System.out) + val shafile = file.getParentFile / (file.getName + ".desired.sha1") + IO.touch(shafile) + IO.write(shafile, sha + " ?" + file.getName) } } diff --git a/project/Testing.scala b/project/Testing.scala new file mode 100644 index 0000000000..cec1d8c60b --- /dev/null +++ b/project/Testing.scala @@ -0,0 +1,41 @@ +import sbt._ +import Keys._ +import partest._ +import SameTest._ +import ScalaBuildKeys._ + +/** All settings/projects relating to testing. */ +trait Testing { self: ScalaBuild.type => + + lazy val testsuiteSettings: Seq[Setting[_]] = compilerDependentProjectSettings ++ partestTaskSettings ++ VerifyClassLoad.settings ++ Seq( + unmanagedBase <<= baseDirectory / "test/files/lib", + fullClasspath in VerifyClassLoad.checkClassLoad <<= (fullClasspath in scalaLibrary in Runtime).identity, + autoScalaLibrary := false, + checkSameLibrary <<= checkSameBinaryProjects(quickLib, strappLib), + checkSameCompiler <<= checkSameBinaryProjects(quickComp, strappComp), + checkSame <<= (checkSameLibrary, checkSameCompiler) map ((a,b) => ()), + autoScalaLibrary := false + ) + lazy val continuationsTestsuiteSettings: Seq[Setting[_]] = testsuiteSettings ++ Seq( + scalacOptions in Test <++= (exportedProducts in Compile in continuationsPlugin) map { + case Seq(cpDir) => Seq("-Xplugin-require:continuations", "-P:continuations:enable", "-Xplugin:"+cpDir.data.getAbsolutePath) + }, + partestDirs <<= baseDirectory apply { bd => + def mkFile(name: String) = bd / "test" / "files" / name + def mkTestType(name: String) = name.drop("continuations-".length).toString + Seq("continuations-neg", "continuations-run") map (t => mkTestType(t) -> mkFile(t)) toMap + } + ) + val testsuite = ( + Project("testsuite", file(".")) + settings (testsuiteSettings:_*) + dependsOn (scalaLibrary, scalaCompiler, fjbg, partest, scalacheck, actorsMigration) + ) + val continuationsTestsuite = ( + Project("continuations-testsuite", file(".")) + settings (continuationsTestsuiteSettings:_*) + dependsOn (partest, scalaLibrary, scalaCompiler, fjbg, actorsMigration) + ) + +} + |