Skip to content
This repository
Fetching contributors…

Octocat-spinner-32-eaf2f5

Cannot retrieve contributors at this time

file 81 lines (77 sloc) 3.655 kb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81
/* sbt -- Simple Build Tool
* Copyright 2009, 2010 Mark Harrah
*/
package sbt
package compiler

import java.io.File

object ComponentCompiler
{
val xsbtiID = "xsbti"
val srcExtension = "-src"
val binSeparator = "-bin_"
val compilerInterfaceID = "compiler-interface"
val compilerInterfaceSrcID = compilerInterfaceID + srcExtension
val javaVersion = System.getProperty("java.class.version")
}
/** This class provides source components compiled with the provided RawCompiler.
* The compiled classes are cached using the provided component manager according
* to the actualVersion field of the RawCompiler.*/
class ComponentCompiler(compiler: RawCompiler, manager: ComponentManager)
{
import ComponentCompiler._
import sbt.IO.{copy, createDirectory, zip, jars, unzip, withTemporaryDirectory}
def apply(id: String): File =
try { getPrecompiled(id) }
catch { case _: InvalidComponent => getLocallyCompiled(id) }

/** Gets the precompiled (distributed with sbt) component with the given 'id'
* If the component has not been precompiled, this throws InvalidComponent. */
def getPrecompiled(id: String): File = manager.file( binaryID(id, false) )(IfMissing.Fail)
/** Get the locally compiled component with the given 'id' or compiles it if it has not been compiled yet.
* If the component does not exist, this throws InvalidComponent. */
def getLocallyCompiled(id: String): File =
{
val binID = binaryID(id, true)
manager.file(binID)( new IfMissing.Define(true, compileAndInstall(id, binID)) )
}
def clearCache(id: String): Unit = manager.clearCache(binaryID(id, true))
protected def binaryID(id: String, withJavaVersion: Boolean) =
{
val base = id + binSeparator + compiler.scalaInstance.actualVersion
if(withJavaVersion) base + "__" + javaVersion else base
}
protected def compileAndInstall(id: String, binID: String)
{
val srcID = id + srcExtension
withTemporaryDirectory { binaryDirectory =>
val targetJar = new File(binaryDirectory, id + ".jar")
compileSources(manager.files(srcID)(IfMissing.Fail), targetJar, id)
manager.define(binID, Seq(targetJar))
}
}
/** Extract sources from source jars, compile them with the xsbti interfaces on the classpath, and package the compiled classes and
* any resources from the source jars into a final jar.*/
private def compileSources(sourceJars: Iterable[File], targetJar: File, id: String)
{
val isSource = (f: File) => isSourceName(f.getName)
def keepIfSource(files: Set[File]): Set[File] = if(files.exists(isSource)) files else Set()

withTemporaryDirectory { dir =>
val extractedSources = (Set[File]() /: sourceJars) { (extracted, sourceJar)=> extracted ++ keepIfSource(unzip(sourceJar, dir)) }
val (sourceFiles, resources) = extractedSources.partition(isSource)
withTemporaryDirectory { outputDirectory =>
val xsbtiJars = manager.files(xsbtiID)(IfMissing.Fail)
manager.log.info("'" + id + "' not yet compiled for Scala " + compiler.scalaInstance.actualVersion + ". Compiling...")
val start = System.currentTimeMillis
try
{
compiler(sourceFiles.toSeq, xsbtiJars.toSeq ++ sourceJars, outputDirectory, "-nowarn" :: Nil)
manager.log.info(" Compilation completed in " + (System.currentTimeMillis - start) / 1000.0 + " s")
}
catch { case e: xsbti.CompileFailed => throw new CompileFailed(e.arguments, "Error compiling sbt component '" + id + "'") }
import sbt.Path._
copy(resources x rebase(dir, outputDirectory))
zip((outputDirectory ***) x_! relativeTo(outputDirectory), targetJar)
}
}
}
private def isSourceName(name: String): Boolean = name.endsWith(".scala") || name.endsWith(".java")
}
Something went wrong with that request. Please try again.