summaryrefslogtreecommitdiff
path: root/project/build/Compilation.scala
blob: f634cbc287ba3c0a1d62b80bd207526f8e4621fc (plain) (blame)
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
112
113
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, log)
    runner.runTask
  }

}