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
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
|
import sbt._
import xsbt.{AnalyzingCompiler, ScalaInstance}
import FileUtilities._
/**
* This trait define the compilation task.
* @author Grégory Moix
*/
trait Compilation {
self : ScalaBuildProject with BuildInfoEnvironment =>
def lastUsedCompilerVersion = layerEnvironment.lastCompilerVersion
def instantiationCompilerJar: Path
def instantiationLibraryJar: Path
def instanceScope[A](action: ScalaInstance => A): A = {
val instance = ScalaInstance(instantiationLibraryJar.asFile, instantiationCompilerJar.asFile, info.launcher, msilJar.asFile, fjbgJar.asFile)
log.debug("Compiler will be instantiated by :" +instance.compilerJar +" and :" +instance.libraryJar )
action(instance)
}
def compile(stepList: Step, clean:() => Option[String]): Option[String] = compile(stepList, Some(clean))
def compile(stepList: Step): Option[String] = compile(stepList, None)
/**
* Execute the different compilation parts one after the others.
*/
def compile(stepsList: Step, clean: Option[() => Option[String]]): Option[String] ={
instanceScope[Option[String]]{ scala =>
lazy val analyzing = new AnalyzingCompiler(scala, componentManager, xsbt.ClasspathOptions.manual, log)
def compilerVersionHasChanged: Boolean ={
val lastVersion = lastUsedCompilerVersion.value
!(lastVersion.compareTo(scala.actualVersion) == 0)
}
def checkAndClean(cleanFunction:() => Option[String]): Option[String] ={
if (compilerVersionHasChanged){
log.info("The compiler version used to build this layer has changed since last time or this is a clean build.")
lastUsedCompilerVersion.update(scala.actualVersion)
layerEnvironment.saveEnvironment
cleanFunction()
} else {
log.debug("The compiler version is unchanged. No need for cleaning.")
None
}
}
def compile0(steps: List[Step]): Option[String] = steps match {
case x :: xs => x match {
case c: CompilationStep => {
val conditional = new CompileConditional(c, analyzing)
log.info("")
conditional.run orElse copy(c) orElse earlyPackaging(c) orElse compile0(xs)
}
case _ => compile0(xs)
}
case Nil => None
}
/**
* When we finishe to compile a step we want to jar if necessary in order to
* be able to load plugins for the associated library
*/
def earlyPackaging(step: CompilationStep): Option[String] = step match {
case s: EarlyPackaging => {
val c = s.earlyPackagingConfig
log.debug("Creating jar for plugin")
jar(c.content.flatMap(Packer.jarPattern(_)), c.jarDestination, c.manifest, false, log)
}
case _ => None
}
def copy(step: CompilationStep): Option[String] = step match {
case s: ResourcesToCopy => s.copy
case _ => None
}
def cleanIfNecessary: Option[String] = clean match {
case None => None
case Some(f) => checkAndClean(f)
}
cleanIfNecessary orElse compile0(stepsList.topologicalSort)
}
}
}
trait LayerCompilation extends Compilation {
self : BasicLayer =>
protected def cleanCompilation: Option[String] = {
log.info("Cleaning the products of the compilation.")
FileUtilities.clean(layerOutput :: Nil, true, log)
}
/**
* Run the actual compilation. Should not be called directly because it is executed on the same jvm and that
* it could lead to memory issues. It is used only when launching a new sbt process to do the compilation.
*/
lazy val compilation = task {compile(allSteps, cleanCompilation _)}
def externalCompilation: Option[String] = {
val runner = new ExternalTaskRunner(projectRoot, this.name, compilation.name, "Error during external compilation", log)
runner.runTask
}
}
|