Skip to content

Commit

Permalink
* move Environment classes to util/env module
Browse files Browse the repository at this point in the history
* move TrapExit, SelectMainClass to run module
* rearrange some compilation-related code
* Jetty-related code moved to web module
  • Loading branch information
harrah committed Jul 14, 2010
1 parent 6f3c699 commit d0fa1eb
Show file tree
Hide file tree
Showing 54 changed files with 534 additions and 2,072 deletions.
4 changes: 4 additions & 0 deletions .gitignore
@@ -0,0 +1,4 @@
LazyJettyRun6.scala
LazyJettyRun7.scala
project/plugins/project/
interface/src/main/resources/xsbt.version.properties
2 changes: 1 addition & 1 deletion LICENSE
@@ -1,4 +1,4 @@
Copyright (c) 2008, 2009, 2010 Mark Harrah, Tony Sloane, Jason Zaugg
Copyright (c) 2008, 2009, 2010 Steven Blundy, Josh Cough, Mark Harrah, Stuart Roebuck, Tony Sloane, Vesa Vilhonen, Jason Zaugg
All rights reserved.

Redistribution and use in source and binary forms, with or without
Expand Down
2 changes: 1 addition & 1 deletion NOTICE
@@ -1,4 +1,4 @@
Simple Build Tool (xsbt components other than sbt/)
Simple Build Tool
Copyright 2008, 2009, 2010 Mark Harrah, Jason Zaugg
Licensed under BSD-style license (see LICENSE)

Expand Down
File renamed without changes.
22 changes: 15 additions & 7 deletions compile/JavaCompiler.scala
Expand Up @@ -12,6 +12,8 @@ trait JavaCompiler
}
object JavaCompiler
{
type Fork = (Seq[String], Logger) => Int

def construct(f: (Seq[String], Logger) => Int, cp: ClasspathOptions, scalaInstance: ScalaInstance): JavaCompiler =
new JavaCompiler {
def apply(sources: Seq[File], classpath: Seq[File], outputDirectory: File, options: Seq[String])(implicit log: Logger) {
Expand All @@ -24,20 +26,26 @@ object JavaCompiler
if( code != 0 ) throw new CompileFailed(arguments.toArray, "javac returned nonzero exit code")
}
}
def directOrFork(cp: ClasspathOptions, scalaInstance: ScalaInstance): JavaCompiler = construct(directOrForkJavac, cp, scalaInstance)
def direct(cp: ClasspathOptions, scalaInstance: ScalaInstance): JavaCompiler = construct(directJavac, cp, scalaInstance)
def fork(cp: ClasspathOptions, scalaInstance: ScalaInstance): JavaCompiler = construct(forkJavac, cp, scalaInstance)
def directOrFork(cp: ClasspathOptions, scalaInstance: ScalaInstance)(implicit doFork: Fork): JavaCompiler =
construct(directOrForkJavac, cp, scalaInstance)

def direct(cp: ClasspathOptions, scalaInstance: ScalaInstance)(implicit doFork: Fork): JavaCompiler =
construct(directJavac, cp, scalaInstance)

def fork(cp: ClasspathOptions, scalaInstance: ScalaInstance)(implicit doFork: Fork): JavaCompiler =
construct(forkJavac, cp, scalaInstance)

val directOrForkJavac = (arguments: Seq[String], log: Logger) =>
def directOrForkJavac(implicit doFork: Fork) = (arguments: Seq[String], log: Logger) =>
try { directJavac(arguments, log) }
catch { case e: ClassNotFoundException =>
log.debug("com.sun.tools.javac.Main not found; forking javac instead")
forkJavac(arguments, log)
forkJavac(doFork)(arguments, log)
}

val forkJavac = (arguments: Seq[String], log: Logger) =>
/** `fork` should be a function that forks javac with the provided arguments and sends output to the given Logger.*/
def forkJavac(implicit doFork: Fork) = (arguments: Seq[String], log: Logger) =>
{
def externalJavac(argFile: File) = Process("javac", ("@" + normalizeSlash(argFile.getAbsolutePath)) :: Nil) ! log
def externalJavac(argFile: File) = doFork(("@" + normalizeSlash(argFile.getAbsolutePath)) :: Nil, log)
withArgumentFile(arguments)(externalJavac)
}
val directJavac = (arguments: Seq[String], log: Logger) =>
Expand Down
6 changes: 4 additions & 2 deletions compile/inc/CompileSetup.scala
Expand Up @@ -15,7 +15,7 @@ object CompileOrder extends Enumeration
// We cannot require an implicit parameter Equiv[Seq[String]] to construct Equiv[CompileSetup]
// because complexity(Equiv[Seq[String]]) > complexity(Equiv[CompileSetup])
// (6 > 4)
final class CompileOptions(val options: Seq[String])
final class CompileOptions(val options: Seq[String], val javacOptions: Seq[String])
final class CompileSetup(val outputDirectory: File, val options: CompileOptions, val compilerVersion: String, val order: CompileOrder.Value)

object CompileSetup
Expand All @@ -32,7 +32,9 @@ object CompileSetup
def equiv(a: File, b: File) = a.getAbsoluteFile == b.getAbsoluteFile
}
implicit val equivOpts: Equiv[CompileOptions] = new Equiv[CompileOptions] {
def equiv(a: CompileOptions, b: CompileOptions) = a.options sameElements b.options
def equiv(a: CompileOptions, b: CompileOptions) =
(a.options sameElements b.options) &&
(a.javacOptions sameElements b.javacOptions)
}
implicit val equivCompilerVersion: Equiv[String] = new Equiv[String] {
def equiv(a: String, b: String) = a == b
Expand Down
2 changes: 1 addition & 1 deletion compile/interface/API.scala
Expand Up @@ -300,7 +300,7 @@ final class API(val global: Global, val callback: xsbti.AnalysisCallback) extend
}
def isTopLevel(sym: Symbol): Boolean =
(sym ne null) && (sym != NoSymbol) && !sym.isImplClass && !sym.isNestedClass && sym.isStatic &&
!sym.hasFlag(Flags.SYNTHETIC)// && !sym.hasFlag(Flags.JAVA)
!sym.hasFlag(Flags.SYNTHETIC) && !sym.hasFlag(Flags.JAVA)
}

// In 2.8, attributes is renamed to annotations
Expand Down
2 changes: 1 addition & 1 deletion compile/persist/AnalysisFormats.scala
Expand Up @@ -42,7 +42,7 @@ object AnalysisFormats
implicit def fileFormat: Format[File] = wrap[File, String](_.getAbsolutePath, s => new File(s))
// can't require Format[Seq[String]] because its complexity is higher than Format[CompileOptions]
implicit def optsFormat(implicit strF: Format[String]): Format[CompileOptions] =
wrap[CompileOptions, Seq[String]](_.options, os => new CompileOptions(os))(seqFormat[String])
wrap[CompileOptions, (Seq[String],Seq[String])](co => (co.options, co.javacOptions), os => new CompileOptions(os._1, os._2))

implicit val orderFormat: Format[CompileOrder.Value] = enumerationFormat(CompileOrder)
implicit def seqFormat[T](implicit optionFormat: Format[T]): Format[Seq[T]] = viaSeq[Seq[T], T](x => x)
Expand Down
39 changes: 1 addition & 38 deletions ivy/IvyInterface.scala
Expand Up @@ -365,41 +365,4 @@ object ModuleConfiguration
{
def apply(org: String, resolver: Resolver): ModuleConfiguration = apply(org, "*", "*", resolver)
def apply(org: String, name: String, resolver: Resolver): ModuleConfiguration = ModuleConfiguration(org, name, "*", resolver)
}
/*
object Credentials
{
/** Add the provided credentials to Ivy's credentials cache.*/
def add(realm: String, host: String, userName: String, passwd: String): Unit =
CredentialsStore.INSTANCE.addCredentials(realm, host, userName, passwd)
/** Load credentials from the given file into Ivy's credentials cache.*/
def apply(file: String, log: Logger): Unit = apply(Path.fromFile(file), log)
/** Load credentials from the given file into Ivy's credentials cache.*/
def apply(file: File, log: Logger): Unit = apply(Path.fromFile(file), log)
/** Load credentials from the given file into Ivy's credentials cache.*/
def apply(path: Path, log: Logger)
{
val msg =
if(path.exists)
{
val properties = new scala.collection.mutable.HashMap[String, String]
def get(keys: List[String]) = keys.flatMap(properties.get).firstOption.toRight(keys.head + " not specified in credentials file: " + path)
impl.MapUtilities.read(properties, path, log) orElse
{
List.separate( List(RealmKeys, HostKeys, UserKeys, PasswordKeys).map(get) ) match
{
case (Nil, List(realm, host, user, pass)) => add(realm, host, user, pass); None
case (errors, _) => Some(errors.mkString("\n"))
}
}
}
else
Some("Credentials file " + path + " does not exist")
msg.foreach(x => log.warn(x))
}
private[this] val RealmKeys = List("realm")
private[this] val HostKeys = List("host", "hostname")
private[this] val UserKeys = List("user", "user.name", "username")
private[this] val PasswordKeys = List("password", "pwd", "pass", "passwd")
}*/
}
40 changes: 28 additions & 12 deletions main/AggressiveCompile.scala
Expand Up @@ -6,36 +6,38 @@ package sbt
import inc._

import java.io.File
import sbt.compile.{AnalyzingCompiler, CompilerArguments}
import compile.{AnalyzingCompiler, CompilerArguments, JavaCompiler}
import classpath.ClasspathUtilities
import classfile.Analyze
import xsbti.api.Source
import xsbti.AnalysisCallback
import CompileSetup._
import sbinary.DefaultProtocol.{ immutableMapFormat, immutableSetFormat, StringFormat }

final class CompileConfiguration(val sources: Seq[File], val classpath: Seq[File], val previousAnalysis: Analysis,
val previousSetup: Option[CompileSetup], val currentSetup: CompileSetup, val getAnalysis: File => Option[Analysis],
val maxErrors: Int, val compiler: AnalyzingCompiler)
final class CompileConfiguration(val sources: Seq[File], val classpath: Seq[File], val javaSrcBases: Seq[File],
val previousAnalysis: Analysis, val previousSetup: Option[CompileSetup], val currentSetup: CompileSetup, val getAnalysis: File => Option[Analysis],
val maxErrors: Int, val compiler: AnalyzingCompiler, val javac: JavaCompiler)

class AggressiveCompile(cacheDirectory: File)
{
def apply(sources: Seq[File], classpath: Seq[File], outputDirectory: File, options: Seq[String], compiler: AnalyzingCompiler, log: Logger): Analysis =
def apply(compiler: AnalyzingCompiler, javac: JavaCompiler, sources: Seq[File], classpath: Seq[File], outputDirectory: File, javaSrcBases: Seq[File] = Nil, options: Seq[String] = Nil, javacOptions: Seq[String] = Nil, maxErrors: Int = 100)(implicit log: Logger): Analysis =
{
val setup = new CompileSetup(outputDirectory, new CompileOptions(options), compiler.scalaInstance.actualVersion, CompileOrder.Mixed)
compile1(sources, classpath, setup, store, Map.empty, compiler, log)
val setup = new CompileSetup(outputDirectory, new CompileOptions(options, javacOptions), compiler.scalaInstance.actualVersion, CompileOrder.Mixed)
compile1(sources, classpath, javaSrcBases, setup, store, Map.empty, compiler, javac, maxErrors)
}

def withBootclasspath(args: CompilerArguments, classpath: Seq[File]): Seq[File] =
args.bootClasspath ++ classpath

def compile1(sources: Seq[File], classpath: Seq[File], setup: CompileSetup, store: AnalysisStore, analysis: Map[File, Analysis], compiler: AnalyzingCompiler, log: Logger): Analysis =
def compile1(sources: Seq[File], classpath: Seq[File], javaSrcBases: Seq[File], setup: CompileSetup, store: AnalysisStore, analysis: Map[File, Analysis], compiler: AnalyzingCompiler, javac: JavaCompiler, maxErrors: Int)(implicit log: Logger): Analysis =
{
val (previousAnalysis, previousSetup) = extract(store.get())
val config = new CompileConfiguration(sources, classpath, previousAnalysis, previousSetup, setup, analysis.get _, 100, compiler)
val result = compile2(config, log)
val config = new CompileConfiguration(sources, classpath, javaSrcBases, previousAnalysis, previousSetup, setup, analysis.get _, maxErrors, compiler, javac)
val result = compile2(config)
store.set(result, setup)
result
}
def compile2(config: CompileConfiguration, log: Logger)(implicit equiv: Equiv[CompileSetup]): Analysis =
def compile2(config: CompileConfiguration)(implicit log: Logger, equiv: Equiv[CompileSetup]): Analysis =
{
import config._
import currentSetup._
Expand All @@ -46,11 +48,24 @@ class AggressiveCompile(cacheDirectory: File)
val apiOrEmpty = (api: Either[Boolean, Source]) => api.right.toOption.getOrElse( APIs.emptyAPI )
val cArgs = new CompilerArguments(compiler.scalaInstance, compiler.cp)
val externalAPI = apiOrEmpty compose Locate.value(withBootclasspath(cArgs, classpath), getAPI)

val compile0 = (include: Set[File], callback: AnalysisCallback) => {
IO.createDirectory(outputDirectory)
val arguments = cArgs(sources.filter(include), classpath, outputDirectory, options.options)
val incSrc = sources.filter(include)
val arguments = cArgs(incSrc, classpath, outputDirectory, options.options)
compiler.compile(arguments, callback, maxErrors, log)
val javaSrcs = incSrc.filter(javaOnly)
if(!javaSrcs.isEmpty)
{
import Path._
val loader = ClasspathUtilities.toLoader(classpath, compiler.scalaInstance.loader)
// TODO: Analyze needs to generate API from Java class files
Analyze(outputDirectory, javaSrcs, javaSrcBases, log)(callback, loader) {
javac(javaSrcs, classpath, outputDirectory, options.javacOptions)
}
}
}

val sourcesSet = sources.toSet
val analysis = previousSetup match {
case Some(previous) if equiv.equiv(previous, currentSetup) => previousAnalysis
Expand All @@ -64,6 +79,7 @@ class AggressiveCompile(cacheDirectory: File)
case Some((an, setup)) => (an, Some(setup))
case None => (Analysis.Empty, None)
}
def javaOnly(f: File) = f.getName.endsWith(".java")

import AnalysisFormats._
// The following intermediate definitions are needed because of Scala's implicit parameter rules.
Expand Down
6 changes: 4 additions & 2 deletions main/AggressiveCompiler.scala
Expand Up @@ -3,7 +3,7 @@
*/
package sbt

import sbt.compile.AnalyzingCompiler
import sbt.compile.{AnalyzingCompiler, JavaCompiler}
import java.io.File
import System.{currentTimeMillis => now}
import Path._
Expand All @@ -25,18 +25,20 @@ class AggressiveCompiler extends xsbti.AppMain
val launcher = app.scalaProvider.launcher
val sources = cwd ** ("*.scala" | "*.java")
val target = cwd / "target"
val javaBaseDirs = cwd :: Nil
val outputDirectory = target / "classes"
val classpath = outputDirectory +++ (cwd * "*.jar") +++(cwd * (-"project")).descendentsExcept( "*.jar", "project" || HiddenFileFilter)
val cacheDirectory = target / "cache"
val options = args.tail.toSeq
val log = new ConsoleLogger with Logger with sbt.IvyLogger
val componentManager = new ComponentManager(launcher.globalLock, app.components, log)
val compiler = new AnalyzingCompiler(ScalaInstance(args.head, launcher), componentManager, log)
val javac = JavaCompiler.directOrFork(compiler.cp, compiler.scalaInstance)( (args: Seq[String], log: Logger) => Process("javac", args) ! log )

val agg = new AggressiveCompile(cacheDirectory)
try
{
val analysis = agg(sources.get.toSeq, classpath.get.toSeq, outputDirectory, options, compiler, log)
val analysis = agg(compiler, javac, sources.get.toSeq, classpath.get.toSeq, outputDirectory, javaBaseDirs, options)(log)
processResult(analysis, command)
true
}
Expand Down
21 changes: 0 additions & 21 deletions project/build/SbtProject.scala
Expand Up @@ -12,7 +12,6 @@ abstract class SbtProject(info: ProjectInfo) extends DefaultProject(info) with t
def extraResources = descendents(info.projectPath / "licenses", "*") +++ "LICENSE" +++ "NOTICE"
override def mainResources = super.mainResources +++ extraResources

override def testOptions = ExcludeTests("sbt.ReflectiveSpecification" :: Nil) :: super.testOptions.toList
override def normalizedName = "sbt"

override def managedStyle = ManagedStyle.Ivy
Expand Down Expand Up @@ -41,10 +40,6 @@ abstract class SbtProject(info: ProjectInfo) extends DefaultProject(info) with t

val ivy = "org.apache.ivy" % "ivy" % "2.1.0" intransitive()
val jsch = "com.jcraft" % "jsch" % "0.1.31" intransitive()
val jetty = "org.mortbay.jetty" % "jetty" % "6.1.14" % "optional"

val jetty7server = "org.eclipse.jetty" % "jetty-server" % "7.0.1.v20091125" % "optional"
val jetty7webapp = "org.eclipse.jetty" % "jetty-webapp" % "7.0.1.v20091125" % "optional"

val testInterface = "org.scala-tools.testing" % "test-interface" % "0.5"

Expand All @@ -64,20 +59,4 @@ abstract class SbtProject(info: ProjectInfo) extends DefaultProject(info) with t
override def packageSrcJar= defaultJarPath("-sources.jar")
/*val sourceArtifact = Artifact(artifactID, "src", "jar", "sources")
val docsArtifact = Artifact(artifactID, "doc", "jar", "javadoc")*/

/* For generating JettyRun for Jetty 6 and 7. The only difference is the imports, but the file has to be compiled against each set of imports. */
override def compileAction = super.compileAction dependsOn (generateJettyRun6, generateJettyRun7)
def jettySrcDir = mainScalaSourcePath / "sbt" / "jetty"
def jettyTemplate = jettySrcDir / "LazyJettyRun.scala.templ"

lazy val generateJettyRun6 = generateJettyRun(jettyTemplate, jettySrcDir / "LazyJettyRun6.scala", "6", jettySrcDir / "jetty6.imports")
lazy val generateJettyRun7 = generateJettyRun(jettyTemplate, jettySrcDir / "LazyJettyRun7.scala", "7", jettySrcDir / "jetty7.imports")
def generateJettyRun(in: Path, out: Path, version: String, importsPath: Path) =
task
{
(for(template <- FileUtilities.readString(in asFile, log).right; imports <- FileUtilities.readString(importsPath asFile, log).right) yield
FileUtilities.write(out asFile, processJettyTemplate(template, version, imports), log).toLeft(()) ).left.toOption
}
def processJettyTemplate(template: String, version: String, imports: String): String =
template.replaceAll("""\Q${jetty.version}\E""", version).replaceAll("""\Q${jetty.imports}\E""", imports)
}

0 comments on commit d0fa1eb

Please sign in to comment.