|
| 1 | +import sbt._ |
| 2 | +import Keys._ |
| 3 | +import ScalaBuildKeys._ |
| 4 | + |
| 5 | +/** All the settings related to *packaging* the built scala software. */ |
| 6 | +trait Packaging { self: ScalaBuild.type => |
| 7 | + |
| 8 | + // -------------------------------------------------------------- |
| 9 | + // Packaging a distro |
| 10 | + // -------------------------------------------------------------- |
| 11 | + lazy val scalaDistSettings: Seq[Setting[_]] = Seq( |
| 12 | + crossPaths := false, |
| 13 | + target <<= (baseDirectory, name) apply (_ / "target" / _), |
| 14 | + scalaSource in Compile <<= (baseDirectory, name) apply (_ / "src" / _), |
| 15 | + autoScalaLibrary := false, |
| 16 | + unmanagedJars in Compile := Seq(), |
| 17 | + genBinRunner <<= (fullClasspath in quickComp in Runtime) map (new ScalaToolRunner(_)), |
| 18 | + binDir <<= target(_/"bin"), |
| 19 | + genBin <<= genBinTask(genBinRunner, binDir, fullClasspath in Runtime, false), |
| 20 | + binDir in genBinQuick <<= baseDirectory apply (_ / "target" / "bin"), |
| 21 | + // Configure the classpath this way to avoid having .jar files and previous layers on the classpath. |
| 22 | + fullClasspath in Runtime in genBinQuick <<= Seq(quickComp,quickLib,scalap,actors,swing,fjbg,jline,forkjoin).map(classDirectory in Compile in _).join.map(Attributed.blankSeq), |
| 23 | + fullClasspath in Runtime in genBinQuick <++= (fullClasspath in Compile in jline), |
| 24 | + genBinQuick <<= genBinTask(genBinRunner, binDir in genBinQuick, fullClasspath in Runtime in genBinQuick, true), |
| 25 | + runManmakerMan <<= runManmakerTask(fullClasspath in Runtime in manmaker, runner in manmaker, "scala.tools.docutil.EmitManPage", "man1", ".1"), |
| 26 | + runManmakerHtml <<= runManmakerTask(fullClasspath in Runtime in manmaker, runner in manmaker, "scala.tools.docutil.EmitHtml", "doc", ".html"), |
| 27 | + // 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) |
| 28 | + // a seq of "plugin jars" (continuationsPlugin) and "binaries" (genBin) and "documentation" mappings (genBin) that this can aggregate. |
| 29 | + // really need to figure out a better way to pull jline + jansi. |
| 30 | + makeDistMappings <<= (genBin, |
| 31 | + runManmakerMan, |
| 32 | + runManmakerHtml, |
| 33 | + packageBin in scalaLibrary in Compile, |
| 34 | + packageBin in scalaCompiler in Compile, |
| 35 | + packageBin in jline in Compile, |
| 36 | + packageBin in continuationsPlugin in Compile, |
| 37 | + managedClasspath in jline in Compile, |
| 38 | + packageBin in scalap in Compile) map { |
| 39 | + (binaries, man, html, lib, comp, jline, continuations, jlineDeps, scalap) => |
| 40 | + val jlineDepMap: Seq[(File, String)] = jlineDeps.map(_.data).flatMap(_ x Path.flat) map { case(a,b) => a -> ("lib/"+b) } |
| 41 | + binaries ++ man ++ html ++ jlineDepMap ++ Seq( |
| 42 | + lib -> "lib/scala-library.jar", |
| 43 | + comp -> "lib/scala-compiler.jar", |
| 44 | + jline -> "lib/jline.jar", |
| 45 | + continuations -> "misc/scala-devel/plugins/continuations.jar", |
| 46 | + scalap -> "lib/scalap.jar" |
| 47 | + ) |
| 48 | + }, |
| 49 | + // Add in some more dependencies |
| 50 | + makeDistMappings <+= (packageBin in swing in Compile) map (s => s -> "lib/scala-swing.jar"), |
| 51 | + makeDistMappings <+= (packageBin in scalaReflect in Compile) map (s => s -> "lib/scala-reflect.jar"), |
| 52 | + makeDist <<= (makeDistMappings, baseDirectory, streams) map { (maps, dir, s) => |
| 53 | + s.log.debug("Map = " + maps.mkString("\n")) |
| 54 | + val file = dir / "target" / "scala-dist.zip" |
| 55 | + IO.zip(maps, file) |
| 56 | + s.log.info("Created " + file.getAbsolutePath) |
| 57 | + file |
| 58 | + }, |
| 59 | + makeExplodedDist <<= (makeDistMappings, target, streams) map { (maps, dir, s) => |
| 60 | + def sameFile(f: File, f2: File) = f.getCanonicalPath == f2.getCanonicalPath |
| 61 | + IO.createDirectory(dir) |
| 62 | + IO.copy(for { |
| 63 | + (file, name) <- maps |
| 64 | + val file2 = dir / name |
| 65 | + if !sameFile(file,file2) |
| 66 | + } yield (file, file2)) |
| 67 | + // Hack to make binaries be executable. TODO - Fix for JDK 5 and below... |
| 68 | + maps map (_._2) filter (_ startsWith "bin/") foreach (dir / _ setExecutable true) |
| 69 | + dir |
| 70 | + } |
| 71 | + ) |
| 72 | + lazy val scaladist = ( |
| 73 | + Project("dist", file(".")) |
| 74 | + settings (scalaDistSettings: _*) |
| 75 | + ) |
| 76 | + |
| 77 | + |
| 78 | +// Helpers to make a distribution |
| 79 | + |
| 80 | + /** Generates runner scripts for distribution. */ |
| 81 | + def genBinTask( |
| 82 | + runner: ScopedTask[ScalaToolRunner], |
| 83 | + outputDir: ScopedSetting[File], |
| 84 | + classpath: ScopedTask[Classpath], |
| 85 | + useClasspath: Boolean |
| 86 | + ): Project.Initialize[sbt.Task[Seq[(File,String)]]] = { |
| 87 | + (runner, outputDir, classpath, streams) map { (runner, outDir, cp, s) => |
| 88 | + IO.createDirectory(outDir) |
| 89 | + val classToFilename = Seq( |
| 90 | + "scala.tools.nsc.MainGenericRunner" -> "scala", |
| 91 | + "scala.tools.nsc.Main" -> "scalac", |
| 92 | + "scala.tools.nsc.ScalaDoc" -> "scaladoc", |
| 93 | + "scala.tools.nsc.CompileClient" -> "fsc", |
| 94 | + "scala.tools.scalap.Main" -> "scalap" |
| 95 | + ) |
| 96 | + if (useClasspath) { |
| 97 | + val classpath = Build.data(cp).map(_.getCanonicalPath).distinct.mkString(",") |
| 98 | + s.log.debug("Setting classpath = " + classpath) |
| 99 | + runner setClasspath classpath |
| 100 | + } |
| 101 | + def genBinFiles(cls: String, dest: File) = { |
| 102 | + runner.setClass(cls) |
| 103 | + runner.setFile(dest) |
| 104 | + runner.execute() |
| 105 | + // TODO - Mark generated files as executable (755 or a+x) that is *not* JDK6 specific... |
| 106 | + dest.setExecutable(true) |
| 107 | + } |
| 108 | + def makeBinMappings(cls: String, binName: String): Seq[(File,String)] = { |
| 109 | + val file = outDir / binName |
| 110 | + val winBinName = binName + ".bat" |
| 111 | + genBinFiles(cls, file) |
| 112 | + Seq( file -> ("bin/"+binName), outDir / winBinName -> ("bin/"+winBinName) ) |
| 113 | + } |
| 114 | + classToFilename.flatMap((makeBinMappings _).tupled) |
| 115 | + } |
| 116 | + } |
| 117 | + /** Creates man pages for distribution. */ |
| 118 | + def runManmakerTask(classpath: ScopedTask[Classpath], scalaRun: ScopedTask[ScalaRun], mainClass: String, dir: String, ext: String): Project.Initialize[Task[Seq[(File,String)]]] = |
| 119 | + (classpath, scalaRun, streams, target) map { (cp, runner, s, target) => |
| 120 | + val binaries = Seq("fsc", "scala", "scalac", "scaladoc", "scalap") |
| 121 | + binaries map { bin => |
| 122 | + val file = target / "man" / dir / (bin + ext) |
| 123 | + val classname = "scala.man1." + bin |
| 124 | + IO.createDirectory(file.getParentFile) |
| 125 | + toError(runner.run(mainClass, Build.data(cp), Seq(classname, file.getAbsolutePath), s.log)) |
| 126 | + file -> ("man/" + dir + "/" + bin + ext) |
| 127 | + } |
| 128 | + } |
| 129 | +} |
0 commit comments