From d4e16acd28f1dec82c213403f78d0e33cca4a791 Mon Sep 17 00:00:00 2001 From: Josh Suereth Date: Thu, 1 Dec 2011 10:18:08 -0500 Subject: Port of SBT 0.11.x build. Things appear to be working well. --- project/Build.scala | 574 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 574 insertions(+) create mode 100644 project/Build.scala (limited to 'project/Build.scala') diff --git a/project/Build.scala b/project/Build.scala new file mode 100644 index 0000000000..dd75b92734 --- /dev/null +++ b/project/Build.scala @@ -0,0 +1,574 @@ +import sbt._ +import Keys._ +import partest._ +import SameTest._ + +object ScalaBuild extends Build with Layers { + // New tasks/settings specific to the scala build. + lazy 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.") + lazy val lockerUnlock: TaskKey[Unit] = TaskKey("locker-unlock", + "Unlocks the locker layer of the compiler so that it will be recompiled on changed source files.") + lazy val lockFile: SettingKey[File] = SettingKey("lock-file", + "Location of the lock file compiling this project.") + lazy val makeDist: TaskKey[File] = TaskKey("make-dist", + "Creates a mini-distribution (scala home directory) for this build in a zip file.") + lazy val makeExplodedDist: TaskKey[File] = TaskKey("make-exploded-dist", + "Creates a mini-distribution (scala home directory) for this build in a directory.") + lazy val makeDistMappings: TaskKey[Map[File, String]] = TaskKey("make-dist-mappings", + "Creates distribution mappings for creating zips,jars,directorys,etc.") + lazy val buildFixed = AttributeKey[Boolean]("build-uri-fixed") + + // Build wide settings: + override lazy val settings = super.settings ++ Seq( + autoScalaLibrary := false, + resolvers += Resolver.url( + "Typesafe nightlies", + url("https://typesafe.artifactoryonline.com/typesafe/ivy-snapshots/") + )(Resolver.ivyStylePatterns), + resolvers ++= Seq( + "junit interface repo" at "https://repository.jboss.org/nexus/content/repositories/scala-tools-releases", + ScalaToolsSnapshots + ), + organization := "org.scala-lang", + version := "2.10.0-SNAPSHOT", + scalaVersion := "2.10.0-SNAPSHOT", + pomExtra := + 2002 + + + BSD-like + http://www.scala-lang.org/downloads/license.html + + + + scm:svn:http://lampsvn.epfl.ch/svn-repos/scala/scala/trunk + + + jira + http://issues.scala-lang.org + + , + 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 + }) + ) + + // Collections of projects to run 'compile' on. + lazy val compiledProjects = Seq(quickLib, quickComp, continuationsLibrary, actors, swing, dbc, forkjoin, fjbg, msil) + // Collection of projects to 'package' and 'publish' together. + lazy val packagedBinaryProjects = Seq(scalaLibrary, scalaCompiler, swing, dbc, continuationsPlugin, jline, scalap) + lazy val partestRunProjects = Seq(testsuite, continuationsTestsuite) + + private def epflPomExtra = ( + + 2002 + + + BSD-like + http://www.scala-lang.org/downloads/license.html + + + + scm:svn:http://lampsvn.epfl.ch/svn-repos/scala/scala/trunk + + + jira + http://issues.scala-lang.org + + + ) + + // maven/ivy settings I pulled from build.sbt to keep it lean and mean + // XXX not sure where they go though, please advise or fix + def publishSettings: Seq[Setting[_]] = Seq( + ivyScala ~= ((is: Option[IvyScala]) => is.map(_.copy(checkExplicit = false))), + pomIncludeRepository := (_ => false), + publishMavenStyle := true, + makePomConfiguration <<= makePomConfiguration apply (_.copy(configurations = Some(Seq(Compile, Default)))), + pomExtra := epflPomExtra + ) + + // Settings for root project. These are aggregate tasks against the rest of the build. + def projectSettings: Seq[Setting[_]] = publishSettings ++ Seq( + doc in Compile <<= (doc in documentation in Compile).identity, + // These next two aggregate commands on several projects and return results that are to be ignored by remaining tasks. + compile in Compile <<= compiledProjects.map(p => compile in p in Compile).join.map(_.head), + // TODO - just clean target? i.e. target map IO.deleteRecursively + clean <<= (compiledProjects ++ partestRunProjects).map(p => clean in p).dependOn, + packageBin in Compile <<= packagedBinaryProjects.map(p => packageBin in p in Compile).join.map(_.head), + // TODO - Make sure scalaLibrary has packageDoc + packageSrc from documentation attached... + publish <<= packagedBinaryProjects.map(p => publish in p).join.map(_.head), + publishLocal <<= packagedBinaryProjects.map(p => publishLocal in p).join.map(_.head), + packageDoc in Compile <<= (packageDoc in documentation in Compile).identity, + packageSrc in Compile <<= (packageSrc in documentation in Compile).identity, + test in Test <<= (runPartest in testsuite, runPartest in continuationsTestsuite, checkSame in testsuite) map { (a,b,c) => () }, + lockerLock <<= (lockFile in lockerLib, lockFile in lockerComp, compile in Compile in lockerLib, compile in Compile in lockerComp) map { (lib, comp, _, _) => + Seq(lib,comp).foreach(f => IO.touch(f)) + }, + lockerUnlock <<= (lockFile in lockerLib, lockFile in lockerComp) map { (lib, comp) => + Seq(lib,comp).foreach(IO.delete) + }, + genBinQuick <<= (genBinQuick in scaladist).identity, + makeDist <<= (makeDist in scaladist).identity, + makeExplodedDist <<= (makeExplodedDist in scaladist).identity, + // Note: We override unmanagedSources so that ~ compile will look at all these sources, then run our aggregated compile... + unmanagedSourceDirectories in Compile <<= baseDirectory apply (_ / "src") apply { dir => + Seq("library/scala","actors","compiler","fjbg","swing","continuations/library","forkjoin") map (dir / _) + }, + // 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: _*) + + // External dependencies used for various projects + lazy val externalDeps: Setting[_] = libraryDependencies <<= (sbtVersion)(v => + Seq( + "org.apache.ant" % "ant" % "1.8.2", + "org.scala-tools.sbt" % "compiler-interface" % v % "provided" + ) + ) + + // These are setting overrides for most artifacts in the Scala build file. + // TODO - what can we move into build.sbt... + // @PP: Ha, and here I'm moving stuff out of it. Clearly I need to + // be educated on the merits of having more stuff in build.sbt. I think + // of it as a good place for items I am frequently changing (logLevel, + // compiler options, etc.) and not so good for anything else. But you + // use this stuff a lot more than I do. + def settingOverrides: Seq[Setting[_]] = Seq( + crossPaths := false, + publishArtifact in packageDoc := false, + publishArtifact in packageSrc := false, + 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, + unmanagedJars in Compile := Seq(), + // Most libs in the compiler use this order to build. + compileOrder in Compile := CompileOrder.JavaThenScala, + lockFile <<= target(_ / "compile.lock"), + skip in Compile <<= lockFile.map(_ exists) + ) + + // -------------------------------------------------------------- + // Libraries used by Scalac that change infrequently + // (or hopefully so). + // -------------------------------------------------------------- + + // Jline nested project. Compile this sucker once and be done. + lazy val jline = Project("jline", file("src/jline")) + // Fast Java Bytecode Generator (nested in every scala-compiler.jar) + lazy val fjbg = Project("fjbg", file(".")) settings(settingOverrides : _*) + // Forkjoin backport + lazy val forkjoin = Project("forkjoin", file(".")) settings(settingOverrides : _*) + + // MSIL code generator + // TODO - This probably needs to compile in the layers, but Sabbus + // had it building against locker, so we'll do worse and build + // build against STARR for now. + lazy val msilSettings = settingOverrides ++ Seq( + defaultExcludes := ("tests"), + javacOptions ++= Seq("-source", "1.4"), + STARR + ) + lazy val msil = Project("msil", file(".")) settings(msilSettings: _*) + + // -------------------------------------------------------------- + // The magic kingdom. + // Layered compilation of Scala. + // Stable Reference -> Locker ('Lockable' dev version) -> Quick -> Strap (Binary compatibility testing) + // -------------------------------------------------------------- + + // Need a report on this... + // TODO - Resolve STARR from a repo.. + lazy val STARR = scalaInstance <<= appConfiguration map { app => + val launcher = app.provider.scalaProvider.launcher + val library = file("lib/scala-library.jar") + val compiler = file("lib/scala-compiler.jar") + val libJars = (file("lib") * "*.jar").get filterNot Set(library, compiler) + + ScalaInstance("starr", library, compiler, launcher, libJars: _*) + } + + // Locker is a lockable Scala compiler that can be built of 'current' source to perform rapid development. + lazy val (lockerLib, lockerComp) = makeLayer("locker", STARR) + lazy val locker = Project("locker", file(".")) aggregate(lockerLib, lockerComp) + + // Quick is the general purpose project layer for the Scala compiler. + lazy val (quickLib, quickComp) = makeLayer("quick", makeScalaReference("locker", lockerLib, lockerComp, fjbg)) + lazy val quick = Project("quick", file(".")) aggregate(quickLib, quickComp) + + // Reference to quick scala instance. + lazy val quickScalaInstance = makeScalaReference("quick", quickLib, quickComp, fjbg) + def quickScalaLibraryDependency = unmanagedClasspath in Compile <++= (exportedProducts in quickLib 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. + lazy val (strappLib, strappComp) = makeLayer("strapp", quickScalaInstance) + + // -------------------------------------------------------------- + // Projects dependent on layered compilation (quick) + // -------------------------------------------------------------- + def addCheaterDependency(projectName: String): Setting[_] = + pomPostProcess <<= (version, organization, pomPostProcess) apply { (v,o,k) => + val dependency: scala.xml.Node = + + {o} + {projectName} + {v} + + def fixDependencies(node: scala.xml.Node): scala.xml.Node = node match { + case {nested@_*} => {dependency}{nested} + case x => x + } + // This is a hack to get around issues where \ and \\ don't work if any of the children are `scala.xml.Group`. + def hasDependencies(root: scala.xml.Node): Boolean = + (root.child collectFirst { + case n: scala.xml.Elem if n.label == "dependencies" => n + } isEmpty) + // TODO - Keep namespace on project... + k andThen { + case n @ { nested@_*} if hasDependencies(n) => + {nested}{dependency} + case { nested@_*} => + { nested map fixDependencies } + } + } + + // 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") + lazy val dbc = Project("dbc", file(".")) settings(dependentProjectSettings:_*) + // TODO - Remove actors dependency from pom... + lazy val swing = Project("swing", 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 partestSettings = compilerDependentProjectSettings :+ externalDeps + lazy val partest = Project("partest", file(".")) settings(partestSettings:_*) dependsOn(actors,forkjoin,scalap) + lazy val scalapSettings = compilerDependentProjectSettings ++ Seq( + name := "scalap", + exportJars := true + ) + lazy val scalap = Project("scalap", file(".")) settings(scalapSettings:_*) + + // -------------------------------------------------------------- + // Continuations plugin + library + // -------------------------------------------------------------- + lazy val continuationsPluginSettings = compilerDependentProjectSettings ++ Seq( + scalaSource in Compile <<= baseDirectory(_ / "src/continuations/plugin/"), + resourceDirectory in Compile <<= baseDirectory(_ / "src/continuations/plugin/"), + exportJars := true, + name := "continuations" // Note: This artifact is directly exported. + + ) + lazy val continuationsPlugin = Project("continuations-plugin", file(".")) settings(continuationsPluginSettings:_*) + lazy val continuationsLibrarySettings = dependentProjectSettings ++ Seq( + scalaSource in Compile <<= baseDirectory(_ / "src/continuations/library/"), + scalacOptions in Compile <++= (exportedProducts in Compile in continuationsPlugin) map { + case Seq(cpDir) => Seq("-Xplugin-require:continuations", "-P:continuations:enable", "-Xplugin:"+cpDir.data.getAbsolutePath) + } + ) + lazy val continuationsLibrary = Project("continuations-library", file(".")) settings(continuationsLibrarySettings:_*) + + // TODO - OSGi Manifest + + // -------------------------------------------------------------- + // Real Library Artifact + // -------------------------------------------------------------- + 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 scalaLibArtifactSettings: Seq[Setting[_]] = inConfig(Compile)(Defaults.packageTasks(packageBin, packageScalaLibBinTask)) ++ Seq( + name := "scala-library", + crossPaths := false, + exportJars := true, + autoScalaLibrary := false, + unmanagedJars in Compile := Seq(), + packageDoc in Compile <<= (packageDoc in documentation in Compile).identity, + packageSrc in Compile <<= (packageSrc in documentation in Compile).identity, + fullClasspath in Runtime <<= (exportedProducts in Compile).identity, + quickScalaInstance, + target <<= (baseDirectory, name) apply (_ / "target" / _) + ) + lazy val scalaLibrary = Project("scala-library", file(".")) settings(scalaLibArtifactSettings:_*) + + // -------------------------------------------------------------- + // Real Compiler Artifact + // -------------------------------------------------------------- + lazy val packageScalaBinTask = Seq(quickComp, fjbg, msil).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, + 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(scalaBinArtifactSettings:_*) dependsOn(scalaLibrary) + lazy val fullQuickScalaReference = makeScalaReference("pack", scalaLibrary, scalaCompiler, fjbg) + + // -------------------------------------------------------------- + // Testing + // -------------------------------------------------------------- + /* lazy val scalacheckSettings: Seq[Setting[_]] = Seq(fullQuickScalaReference, crossPaths := false)*/ + lazy val scalacheck = uri("git://github.com/rickynils/scalacheck.git") + + 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 (swing, scalaLibrary, scalaCompiler, fjbg, partest, scalacheck) + ) + val continuationsTestsuite = ( + Project("continuations-testsuite", file(".")) + settings (continuationsTestsuiteSettings:_*) + dependsOn (partest, swing, scalaLibrary, scalaCompiler, fjbg) + ) + + // -------------------------------------------------------------- + // Generating Documentation. + // -------------------------------------------------------------- + + // TODO - Migrate this into the dist project. + // Scaladocs + def distScalaInstance = makeScalaReference("dist", scalaLibrary, scalaCompiler, fjbg) + lazy val documentationSettings: Seq[Setting[_]] = dependentProjectSettings ++ Seq( + // TODO - Make these work for realz. + defaultExcludes in unmanagedSources in Compile := ((".*" - ".") || HiddenFileFilter || + "reflect/Print.scala" || + "reflect/Symbol.scala" || + "reflect/Tree.scala" || + "reflect/Type.scala" || + "runtime/*$.scala" || + "runtime/ScalaRuntime.scala" || + "runtime/StringAdd.scala" || + "scala/swing/test/*"), + sourceFilter in Compile := ("*.scala"), + unmanagedSourceDirectories in Compile <<= baseDirectory apply { dir => + Seq(dir / "src" / "library" / "scala", dir / "src" / "actors", dir / "src" / "swing", dir / "src" / "continuations" / "library") + }, + compile := inc.Analysis.Empty, + scaladocOptions in Compile in doc <++= (baseDirectory) map (bd => + Seq("-sourcepath", (bd / "src" / "library").getAbsolutePath, + "-doc-no-compile", (bd / "src" / "library-aux").getAbsolutePath, + "-doc-source-url", """https://lampsvn.epfl.ch/trac/scala/browser/scala/trunk/src/€{FILE_PATH}.scala#L1""", + "-doc-root-content", (bd / "compiler/scala/tools/nsc/doc/html/resource/lib/rootdoc.txt").getAbsolutePath + )), + classpathOptions in Compile := ClasspathOptions.manual + ) + lazy val documentation = ( + Project("documentation", file(".")) + 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,dbc,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, + packageBin in dbc in Compile) map { + (dist, s, d) => + dist ++ Seq(s -> "lib/scala-swing.jar", d -> "lib/scala-dbc.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 + } +} -- cgit v1.2.3 From 47fb0d381022bda800b7f8ee234224aa20020e4a Mon Sep 17 00:00:00 2001 From: Josh Suereth Date: Mon, 5 Dec 2011 15:52:10 -0500 Subject: Adding SHA resolve to the SBT build so that we don't need the push/pull binary libs script anymore. Only pull is implemented. --- project/Build.scala | 4 ++-- project/ShaResolve.scala | 57 ++++++++++++++++++++++++++++++++++++++++++++++++ project/plugins.sbt | 2 ++ 3 files changed, 61 insertions(+), 2 deletions(-) create mode 100644 project/ShaResolve.scala (limited to 'project/Build.scala') diff --git a/project/Build.scala b/project/Build.scala index dd75b92734..6ffdffa005 100644 --- a/project/Build.scala +++ b/project/Build.scala @@ -141,7 +141,7 @@ object ScalaBuild extends Build with Layers { //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: _*) + lazy val aaa_root = Project("scala", file(".")) settings(projectSettings: _*) settings(ShaResolve.settings: _*) // External dependencies used for various projects lazy val externalDeps: Setting[_] = libraryDependencies <<= (sbtVersion)(v => @@ -206,7 +206,7 @@ object ScalaBuild extends Build with Layers { // Need a report on this... // TODO - Resolve STARR from a repo.. - lazy val STARR = scalaInstance <<= appConfiguration map { app => + lazy val STARR = scalaInstance <<= (appConfiguration, ShaResolve.pullBinaryLibs in ThisBuild) map { (app, _) => val launcher = app.provider.scalaProvider.launcher val library = file("lib/scala-library.jar") val compiler = file("lib/scala-compiler.jar") diff --git a/project/ShaResolve.scala b/project/ShaResolve.scala new file mode 100644 index 0000000000..2b7fafd576 --- /dev/null +++ b/project/ShaResolve.scala @@ -0,0 +1,57 @@ +import sbt._ + +import Build._ +import Keys._ +import Project.Initialize +import scala.collection.{ mutable, immutable } + + + + +/** Helpers to resolve SHA artifacts from typesafe repo. */ +object ShaResolve { + import dispatch.{Http,url} + val remote_urlbase="http://typesafe.artifactoryonline.com/typesafe/scala-sha-bootstrap/org/scala-lang/bootstrap" + + val pullBinaryLibs = TaskKey[Unit]("pull-binary-libs", "Pulls binary libs by the SHA key.") + val pushBinaryLibs = TaskKey[Unit]("push-binary-libs", "Pushes binary libs whose SHA has changed.") + + + def settings: Seq[Setting[_]] = Seq( + pullBinaryLibs in ThisBuild <<= (baseDirectory, streams) map resolveLibs + ) + + def resolveLibs(dir: File, s: TaskStreams): Unit = { + for { + (file, name) <- dir ** "*.desired.sha1" x relativeTo(dir) + uri = name.dropRight(13) + jar = dir / uri + if !jar.exists || !isValidSha(file) + sha = getShaFromShafile(file) + } pullFile(jar, sha + "/" + uri, s) + } + + def getShaFromShafile(file: File): String = (IO read file split "\\s" headOption) getOrElse error("No SHA found for " + file) + + + def isValidSha(file: File): Boolean = + try (Process(Seq("shasum", "-p", "--check", file.getAbsolutePath), Some(file.getParentFile)).!! contains "OK") + catch { + case t: Exception => false + } + + + def pullFile(file: File, uri: String, s: TaskStreams): Unit = { + val url = remote_urlbase + "/" + uri + val fous = new java.io.FileOutputStream(file) + s.log.info("Pulling [" + url + "] to [" + file + "]") + try Http(dispatch.url(url) >>> fous) finally fous.close() + } + + 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") + // TODO - output to logger. + Http(sender >>> System.out) + } +} diff --git a/project/plugins.sbt b/project/plugins.sbt index 2dfee4b5c9..b49ece7527 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -4,4 +4,6 @@ resolvers += Resolver.url("scalasbt", new URL("http://scalasbt.artifactoryonline resolvers += "jgit-repo" at "http://download.eclipse.org/jgit/maven" +libraryDependencies += "net.databinder" %% "dispatch-http" % "0.8.6" + -- cgit v1.2.3 From 4c76201be849b658e29004cd5749f18198547b5d Mon Sep 17 00:00:00 2001 From: Josh Suereth Date: Tue, 6 Dec 2011 13:13:02 -0500 Subject: Fixed publish issue. * Cleaned up layered build settings definition * Removed scalaVersion specification from build (not NEEDED). * Fixed a migration from build.sbt to project/Build.scala where publish settings were only being used on the root project and not also used for sub-projects which are published. --- project/Build.scala | 12 ++-------- project/Layers.scala | 67 ++++++++++++++++++++++++++-------------------------- 2 files changed, 35 insertions(+), 44 deletions(-) (limited to 'project/Build.scala') diff --git a/project/Build.scala b/project/Build.scala index 6ffdffa005..0f48b3b742 100644 --- a/project/Build.scala +++ b/project/Build.scala @@ -32,7 +32,6 @@ object ScalaBuild extends Build with Layers { ), organization := "org.scala-lang", version := "2.10.0-SNAPSHOT", - scalaVersion := "2.10.0-SNAPSHOT", pomExtra := 2002 @@ -99,8 +98,7 @@ object ScalaBuild extends Build with Layers { ) - // maven/ivy settings I pulled from build.sbt to keep it lean and mean - // XXX not sure where they go though, please advise or fix + // Settings used to make sure publishing goes smoothly. def publishSettings: Seq[Setting[_]] = Seq( ivyScala ~= ((is: Option[IvyScala]) => is.map(_.copy(checkExplicit = false))), pomIncludeRepository := (_ => false), @@ -152,13 +150,7 @@ object ScalaBuild extends Build with Layers { ) // These are setting overrides for most artifacts in the Scala build file. - // TODO - what can we move into build.sbt... - // @PP: Ha, and here I'm moving stuff out of it. Clearly I need to - // be educated on the merits of having more stuff in build.sbt. I think - // of it as a good place for items I am frequently changing (logLevel, - // compiler options, etc.) and not so good for anything else. But you - // use this stuff a lot more than I do. - def settingOverrides: Seq[Setting[_]] = Seq( + def settingOverrides: Seq[Setting[_]] = publishSettings ++ Seq( crossPaths := false, publishArtifact in packageDoc := false, publishArtifact in packageSrc := false, diff --git a/project/Layers.scala b/project/Layers.scala index 84c926f072..50037f8f9f 100644 --- a/project/Layers.scala +++ b/project/Layers.scala @@ -48,42 +48,41 @@ trait Layers extends Build { * Note: The library and compiler are not *complete* in the sense that they are missing things like "actors" and "fjbg". */ def makeLayer(layer: String, referenceScala: Setting[Task[ScalaInstance]]) : (Project, Project) = { - val library = Project(layer + "-library", file(".")) settings( (settingOverrides ++ - Seq(version := layer, - // TODO - use depends on. - unmanagedClasspath in Compile <<= (exportedProducts in forkjoin in Compile).identity, - managedClasspath in Compile := Seq(), - scalaSource in Compile <<= (baseDirectory) apply (_ / "src" / "library"), - resourceDirectory in Compile <<= baseDirectory apply (_ / "src" / "library"), - defaultExcludes in unmanagedResources := ("*.scala" | "*.java" | "*.disabled"), - // TODO - Allow other scalac option settings. - scalacOptions in Compile <++= (scalaSource in Compile) map (src => Seq("-sourcepath", src.getAbsolutePath)), - classpathOptions := ClasspathOptions.manual, - resourceGenerators in Compile <+= (baseDirectory, version, resourceManaged, gitRunner) map Release.generatePropertiesFile("library.properties"), - referenceScala - )) :_*) + val library = Project(layer + "-library", file(".")) settings(settingOverrides: _*) settings( + version := layer, + // TODO - use depends on. + unmanagedClasspath in Compile <<= (exportedProducts in forkjoin in Compile).identity, + managedClasspath in Compile := Seq(), + scalaSource in Compile <<= (baseDirectory) apply (_ / "src" / "library"), + resourceDirectory in Compile <<= baseDirectory apply (_ / "src" / "library"), + defaultExcludes in unmanagedResources := ("*.scala" | "*.java" | "*.disabled"), + // TODO - Allow other scalac option settings. + scalacOptions in Compile <++= (scalaSource in Compile) map (src => Seq("-sourcepath", src.getAbsolutePath)), + classpathOptions := ClasspathOptions.manual, + resourceGenerators in Compile <+= (baseDirectory, version, resourceManaged, gitRunner) map Release.generatePropertiesFile("library.properties"), + referenceScala + ) // Define the compiler - val compiler = Project(layer + "-compiler", file(".")) settings((settingOverrides ++ - Seq(version := layer, - scalaSource in Compile <<= (baseDirectory) apply (_ / "src" / "compiler"), - resourceDirectory in Compile <<= baseDirectory apply (_ / "src" / "compiler"), - defaultExcludes in unmanagedResources := "*.scala", - resourceGenerators in Compile <+= (baseDirectory, version, resourceManaged, gitRunner) map Release.generatePropertiesFile("compiler.properties"), - // Note, we might be able to use the default task, but for some reason ant was filtering files out. Not sure what's up, but we'll - // stick with that for now. - unmanagedResources in Compile <<= (baseDirectory) map { - (bd) => - val dirs = Seq(bd / "src" / "compiler") - dirs.descendentsExcept( ("*.xml" | "*.html" | "*.gif" | "*.png" | "*.js" | "*.css" | "*.tmpl" | "*.swf" | "*.properties" | "*.txt"),"*.scala").get - }, - // TODO - Use depends on *and* SBT's magic dependency mechanisms... - unmanagedClasspath in Compile <<= Seq(forkjoin, library, fjbg, jline, msil).map(exportedProducts in Compile in _).join.map(_.flatten), - classpathOptions := ClasspathOptions.manual, - externalDeps, - referenceScala - ) - ):_*) + val compiler = Project(layer + "-compiler", file(".")) settings(settingOverrides:_*) settings( + version := layer, + scalaSource in Compile <<= (baseDirectory) apply (_ / "src" / "compiler"), + resourceDirectory in Compile <<= baseDirectory apply (_ / "src" / "compiler"), + defaultExcludes in unmanagedResources := "*.scala", + resourceGenerators in Compile <+= (baseDirectory, version, resourceManaged, gitRunner) map Release.generatePropertiesFile("compiler.properties"), + // Note, we might be able to use the default task, but for some reason ant was filtering files out. Not sure what's up, but we'll + // stick with that for now. + unmanagedResources in Compile <<= (baseDirectory) map { + (bd) => + val dirs = Seq(bd / "src" / "compiler") + dirs.descendentsExcept( ("*.xml" | "*.html" | "*.gif" | "*.png" | "*.js" | "*.css" | "*.tmpl" | "*.swf" | "*.properties" | "*.txt"),"*.scala").get + }, + // TODO - Use depends on *and* SBT's magic dependency mechanisms... + unmanagedClasspath in Compile <<= Seq(forkjoin, library, fjbg, jline, msil).map(exportedProducts in Compile in _).join.map(_.flatten), + classpathOptions := ClasspathOptions.manual, + externalDeps, + referenceScala + ) // Return the generated projects. (library, compiler) -- cgit v1.2.3 From b0e74c560ade7bfadb5bd86bc9bb127bc47e7e43 Mon Sep 17 00:00:00 2001 From: Josh Suereth Date: Fri, 9 Dec 2011 13:54:12 -0500 Subject: MSIL now part of layered compiles * The MSIL source code is now built at every layer as part of the compiler project. * The MSIL project is completely removed from other references. --- project/Build.scala | 20 ++++---------------- project/Layers.scala | 7 ++++--- 2 files changed, 8 insertions(+), 19 deletions(-) (limited to 'project/Build.scala') diff --git a/project/Build.scala b/project/Build.scala index 0f48b3b742..297f82e515 100644 --- a/project/Build.scala +++ b/project/Build.scala @@ -74,7 +74,7 @@ object ScalaBuild extends Build with Layers { ) // Collections of projects to run 'compile' on. - lazy val compiledProjects = Seq(quickLib, quickComp, continuationsLibrary, actors, swing, dbc, forkjoin, fjbg, msil) + lazy val compiledProjects = Seq(quickLib, quickComp, continuationsLibrary, actors, swing, dbc, forkjoin, fjbg) // Collection of projects to 'package' and 'publish' together. lazy val packagedBinaryProjects = Seq(scalaLibrary, scalaCompiler, swing, dbc, continuationsPlugin, jline, scalap) lazy val partestRunProjects = Seq(testsuite, continuationsTestsuite) @@ -179,17 +179,6 @@ object ScalaBuild extends Build with Layers { // Forkjoin backport lazy val forkjoin = Project("forkjoin", file(".")) settings(settingOverrides : _*) - // MSIL code generator - // TODO - This probably needs to compile in the layers, but Sabbus - // had it building against locker, so we'll do worse and build - // build against STARR for now. - lazy val msilSettings = settingOverrides ++ Seq( - defaultExcludes := ("tests"), - javacOptions ++= Seq("-source", "1.4"), - STARR - ) - lazy val msil = Project("msil", file(".")) settings(msilSettings: _*) - // -------------------------------------------------------------- // The magic kingdom. // Layered compilation of Scala. @@ -203,7 +192,6 @@ object ScalaBuild extends Build with Layers { val library = file("lib/scala-library.jar") val compiler = file("lib/scala-compiler.jar") val libJars = (file("lib") * "*.jar").get filterNot Set(library, compiler) - ScalaInstance("starr", library, compiler, launcher, libJars: _*) } @@ -312,12 +300,12 @@ object ScalaBuild extends Build with Layers { quickScalaInstance, target <<= (baseDirectory, name) apply (_ / "target" / _) ) - lazy val scalaLibrary = Project("scala-library", file(".")) settings(scalaLibArtifactSettings:_*) + lazy val scalaLibrary = Project("scala-library", file(".")) settings(publishSettings:_*) settings(scalaLibArtifactSettings:_*) // -------------------------------------------------------------- // Real Compiler Artifact // -------------------------------------------------------------- - lazy val packageScalaBinTask = Seq(quickComp, fjbg, msil).map(p => products in p in Compile).join.map(_.flatten).map(productTaskToMapping) + lazy val packageScalaBinTask = Seq(quickComp, fjbg).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, @@ -328,7 +316,7 @@ object ScalaBuild extends Build with Layers { quickScalaInstance, target <<= (baseDirectory, name) apply (_ / "target" / _) ) - lazy val scalaCompiler = Project("scala-compiler", file(".")) settings(scalaBinArtifactSettings:_*) dependsOn(scalaLibrary) + lazy val scalaCompiler = Project("scala-compiler", file(".")) settings(publishSettings:_*) settings(scalaBinArtifactSettings:_*) dependsOn(scalaLibrary) lazy val fullQuickScalaReference = makeScalaReference("pack", scalaLibrary, scalaCompiler, fjbg) // -------------------------------------------------------------- diff --git a/project/Layers.scala b/project/Layers.scala index 50037f8f9f..905d312fff 100644 --- a/project/Layers.scala +++ b/project/Layers.scala @@ -14,8 +14,6 @@ trait Layers extends Build { def forkjoin: Project /** Reference to Fast-Java-Bytecode-Generator library */ def fjbg: Project - /** Reference to MSIL generator library */ - def msil: Project /** A setting that adds some external dependencies. */ def externalDeps: Setting[_] @@ -68,6 +66,9 @@ trait Layers extends Build { version := layer, scalaSource in Compile <<= (baseDirectory) apply (_ / "src" / "compiler"), resourceDirectory in Compile <<= baseDirectory apply (_ / "src" / "compiler"), + unmanagedSourceDirectories in Compile <+= (baseDirectory) apply (_ / "src" / "msil"), + defaultExcludes := ("tests"), + javacOptions ++= Seq("-source", "1.4"), defaultExcludes in unmanagedResources := "*.scala", resourceGenerators in Compile <+= (baseDirectory, version, resourceManaged, gitRunner) map Release.generatePropertiesFile("compiler.properties"), // Note, we might be able to use the default task, but for some reason ant was filtering files out. Not sure what's up, but we'll @@ -78,7 +79,7 @@ trait Layers extends Build { dirs.descendentsExcept( ("*.xml" | "*.html" | "*.gif" | "*.png" | "*.js" | "*.css" | "*.tmpl" | "*.swf" | "*.properties" | "*.txt"),"*.scala").get }, // TODO - Use depends on *and* SBT's magic dependency mechanisms... - unmanagedClasspath in Compile <<= Seq(forkjoin, library, fjbg, jline, msil).map(exportedProducts in Compile in _).join.map(_.flatten), + unmanagedClasspath in Compile <<= Seq(forkjoin, library, fjbg, jline).map(exportedProducts in Compile in _).join.map(_.flatten), classpathOptions := ClasspathOptions.manual, externalDeps, referenceScala -- cgit v1.2.3 From 716ef5b0a6b4da94f44234226782a3f3d473fa5e Mon Sep 17 00:00:00 2001 From: Josh Suereth Date: Thu, 29 Dec 2011 08:38:39 -0500 Subject: All projects can be locked now. * Added 'lock' key to write 'compile.lock' file to target dir. * Added 'unlock' key to delete 'compile.lock' file to target dir. --- project/Build.scala | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'project/Build.scala') diff --git a/project/Build.scala b/project/Build.scala index 297f82e515..abab775666 100644 --- a/project/Build.scala +++ b/project/Build.scala @@ -11,6 +11,9 @@ object ScalaBuild extends Build with Layers { "Unlocks the locker layer of the compiler so that it will be recompiled on changed source files.") lazy val lockFile: SettingKey[File] = SettingKey("lock-file", "Location of the lock file compiling this project.") + // New tasks/settings specific to the scala build. + lazy val lock: TaskKey[Unit] = TaskKey("lock", "Locks this project so it won't be recompiled.") + lazy val unlock: TaskKey[Unit] = TaskKey("unlock", "Unlocks this project so it will be recompiled.") lazy val makeDist: TaskKey[File] = TaskKey("make-dist", "Creates a mini-distribution (scala home directory) for this build in a zip file.") lazy val makeExplodedDist: TaskKey[File] = TaskKey("make-exploded-dist", @@ -164,7 +167,9 @@ object ScalaBuild extends Build with Layers { // Most libs in the compiler use this order to build. compileOrder in Compile := CompileOrder.JavaThenScala, lockFile <<= target(_ / "compile.lock"), - skip in Compile <<= lockFile.map(_ exists) + skip in Compile <<= lockFile.map(_ exists), + lock <<= lockFile map { f => IO.touch(f) }, + unlock <<= lockFile map IO.delete ) // -------------------------------------------------------------- -- cgit v1.2.3