summaryrefslogtreecommitdiff
path: root/project/build/ScalaSBTBuilder.scala
blob: c741f3710cd24153c8ee267fe30a4d53a08b3686 (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
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
import sbt._
import ScalaBuildProject._

/**
 * This class is the entry point for building scala with SBT.
 * @author Grégory Moix
 */
class ScalaSBTBuilder(val info: ProjectInfo) extends Project with  ReflectiveProject {
  override def dependencies: Iterable[Project] = info.dependencies  ++ locker.dependencies ++ quick.dependencies ++ strap.dependencies ++ libs.dependencies
  override def shouldCheckOutputDirectories = false

  override def watchPaths = info.projectPath / "src" ** ("*.scala" || "*.java"||AdditionalResources.basicFilter) // Support of triggered execution at top level
  // Top Level Tasks
  lazy val build = task{None}.dependsOn(quick.binPack,quick.binQuick)
  lazy val clean = locker.clean
  lazy val docs = quick.scaladoc
  lazy val palo = locker.pack
  lazy val pasta = quick.pasta
  lazy val newStarr = quick.newStarr
  lazy val newLocker=locker.newLocker
  lazy val buildForkjoin=libs.buildForkjoin
  lazy val newForkjoin = libs.newForkjoin
  lazy val buildFjbg = libs.buildFjbg
  lazy val newFjbg = libs.newFjbg
  lazy val buildMsil = libs.buildMsil
  lazy val newMsil = libs.newMsil
  lazy val partest = quick.externalPartest
  lazy val testSuite = strap.testSuite



  // Top level variables

  /**
   * The version number of the compiler that will be created by the run of sbt. It is initialised once
   * the first time it is needed, meaning that this number will be kept
   * until sbt quit.
   */
  lazy val versionNumber:String ={
    def getTimeString:String ={
      import java.util.Calendar;
      import java.text.SimpleDateFormat;
      val formatString = "yyyyMMddHHmmss"
      new SimpleDateFormat(formatString) format( Calendar.getInstance.getTime)
    }
    def getVersion:String ={
      val version:String = projectVersion.value.toString
      val stopIndex = version.lastIndexOf('-')
      stopIndex match{
        case -1 => version
        case i => version substring(0,i)
      }
    }
    def getRevision:Int = {
      new SVN(info.projectPath).getRevisionNumber
    }

    getVersion+".r"+getRevision+"-b"+getTimeString
  }



  /* LAYER DEFINITIONS
   * We define here what's specific to each layer are they differ.
   * The common behavior is defined in the BasicLayer class
   * It is important that the class that extends BasicLayer are inner classes of ScalaSBTBuilder. If not, SBT will
   * not know what the main project definition is, as it will find many classes that extends Project
   */

  lazy val locker=project(info.projectPath,"locker", new LockerLayer(_))
  lazy val quick=project(info.projectPath,"quick",new QuickLayer(_,locker))
  lazy val strap=project(info.projectPath,"strap", new StrapLayer(_, quick))
  lazy val libs=project(info.projectPath,"libs", new LibsBuilder(_))


  /**
   * Definition of what is specific to the locker layer. It implements SimplePacker in order to
   * be able to create palo (packed locker)
   */
  class LockerLayer(info:ProjectInfo) extends BasicLayer(info,versionNumber,None)  with Packer{


    override lazy val nextLayer=Some(quick)
    lazy val instantiationCompilerJar = lib / compilerJarName
    lazy val instantiationLibraryJar = lib / libraryJarName
    lazy val lockFile = layerOutput / "locker.lock"

    /**
     * We override the definition of the task method in order to make the tasks of this layer
     * be executed only if the layer is not locked. Task of this layer that should be executed
     * whether the layer is locked or not should call super.task instead
     */
    override def task(action : => Option[String])=
      super.task{
        if (lockFile.exists) {
          log.info(name +" is locked")
          None
        }
        else action
      }

    def deleteLock = FileUtilities.clean(lockFile,log)
    def createLock = {
      log.info("locking "+name)
      FileUtilities.touch(lockFile,log)
    }

    /**
     * Task for locking locker
     */
    lazy val lock = super.task{
      createLock
    }

    /**
     * Task for unlocking locker
     */
    lazy val unlock = super.task{
      deleteLock
    }

    lazy val newLocker = super.task{
      createNewLocker
    }
    def createNewLocker = {
      deleteLock orElse
      buildLayer orElse
      createLock
    }


    /**
     *  Making locker being locked when it has finished building
     */
    override lazy val finishLayer = lock.dependsOn(build)

    override lazy val pack = super.task{packF}.dependsOn(finishLayer)


    override lazy val packingDestination:Path = outputRootPath /"palo"

    /**
     *  We must override the compilation steps as we only want to compile
     * the core library (and not actors,dbc, scalap, partest)
     */
     override lazy val libraryWS = {
        new WrapperStep(libraryConfig::Nil) with WrapperPackaging{
          lazy val packagingConfig = new PackagingConfiguration(libsDestination/libraryJarName, jarContent)
         }
     }
     override val minimalCompilation = true
     override lazy val pluginsWS:WrapperStep = new WrapperStep(Nil)
     override lazy val toolsWS = new WrapperStep(Nil)
  }


  /**
   * Definition of what is specific to the quick layer. It implements Packer in order to create pack, ScalaTools
   * for creating the binaries and Scaladoc to generate the documentation
   */
  class QuickLayer(info:ProjectInfo, previous:BasicLayer) extends BasicLayer(info,versionNumber,Some(previous)) with PartestRunner
          with Packer with ScalaTools with Scaladoc{

    override lazy val nextLayer=Some(strap)


    lazy val instantiationCompilerJar = previous.compilerOutput
    lazy val instantiationLibraryJar = previous.libraryOutput


    override lazy val packingDestination:Path = outputRootPath/ "pack"

    override def libraryToCopy = jlineJar::Nil
    override def compilerAdditionalJars = msilJar::fjbgJar::Nil
    override def libraryAdditionalJars = forkJoinJar::Nil



    override lazy val libraryWS = new WrapperStep(libraryConfig::actorsConfig::dbcConfig::swingConfig::Nil) with Packaging{
        def jarContent = List(libraryConfig , actorsConfig, continuationLibraryConfig).map(_.outputDirectory ##)
        lazy val starrJarContent=List(libraryConfig , actorsConfig,dbcConfig,swingConfig, continuationLibraryConfig).map(_.outputDirectory ##)
        lazy val packagingConfig = new PackagingConfiguration(libsDestination/libraryJarName,jarContent,libraryAdditionalJars)
        lazy val starrPackagingConfig = new PackagingConfiguration(packedStarrOutput/libraryJarName,starrJarContent)

    }

    override lazy val toolsWS = new WrapperStep(scalapConfig::partestConfig::Nil)

    // An additional task for building only the library of quick
    // Used for compiling msil
    lazy val compileLibraryOnly = task{
      compile(libraryConfig, cleanCompilation _)
    }
    lazy val externalCompileLibraryOnly = task{
      val runner = new ExternalTaskRunner(projectRoot,this.name,compileLibraryOnly.name,"Error during external compilation", log)
      runner.runTask
    }.dependsOn(startLayer)


    def createNewStarrJar:Option[String]={
      import Packer._
      createJar(libraryWS.starrPackagingConfig,log) orElse
      createJar(compilerConfig.starrPackagingConfig,log)
    }
    lazy val pasta = task{
      createNewStarrJar
    }.dependsOn(build)

    lazy val newStarr = task{
      val files = (packedStarrOutput ##) * "*.jar"
      FileUtilities.copy(files.get,lib,true,log) match{
        case Right(_) =>None
        case Left(_) =>Some("Error occured when copying the new starr to its destination")
      }

    }.dependsOn(pasta)





    /*
     * Defining here the creation of the binaries for quick and pack
     */
    private lazy val quickBinClasspath = libraryOutput::actorsOutput::dbcOutput::swingOutput::compilerOutput::scalapOutput::forkJoinJar::fjbgJar::msilJar::jlineJar::Nil
    private lazy val packBinClasspath  = Nil
    lazy val binQuick = tools(layerOutput / "bin", quickBinClasspath).dependsOn(finishLayer)
    lazy val binPack = tools(packingDestination / "bin", packBinClasspath).dependsOn(pack)


  }


  /**
   * Definition of what is specific to the strap layer
   */
  class StrapLayer(info:ProjectInfo, previous:BasicLayer) extends BasicLayer(info,versionNumber,Some(previous)) {

    lazy val instantiationCompilerJar = previous.compilerOutput
    lazy val instantiationLibraryJar = previous.libraryOutput
    private val quick = previous

    override lazy val libraryWS = new WrapperStep(libraryConfig::actorsConfig::dbcConfig::swingConfig::Nil) with WrapperPackaging{
        lazy val packagingConfig = new PackagingConfiguration(libsDestination/libraryJarName,Set())

         }

    override lazy val toolsWS= new WrapperStep(scalapConfig::partestConfig::Nil)



    def compare = {
      import PathConfig.classes
      def filter(path:Path)= path.descendentsExcept(AllPassFilter, HiddenFileFilter || "*.properties")
      Comparator.compare(this.pathLayout.outputDir/classes ##,quick.pathLayout.outputDir/classes ##, filter _ ,log)
    }

    lazy val testSuite=task{
      compare
    }

  }



  /**
   * An additional subproject used to build new version of forkjoin,fjbg and msil
   */
  class LibsBuilder(val info:ProjectInfo) extends ScalaBuildProject with ReflectiveProject with Compilation with BuildInfoEnvironment {
    override def dependencies = info.dependencies
    override def watchPaths = info.projectPath / "src" ** ("*.scala" || "*.java"||AdditionalResources.basicFilter) // Support of triggered execution at project level


    def buildInfoEnvironmentLocation:Path=outputRootPath / ("build-"+name+".properties")

    def instantiationCompilerJar:Path=locker.compilerOutput
    def instantiationLibraryJar:Path=locker.libraryOutput

    def libsDestination = layerOutput

    lazy val checkJavaVersion = task{
      val version = System.getProperty("java.version")
      log.debug("java.version="+version)
      val required = "1.6"
      if (version.startsWith(required)) None else Some("Incompatible java version : required "+required)
    }


    private def simpleBuild(step:CompilationStep with Packaging)=task{
      import Packer._
      compile(step) orElse createJar(step,log)
    }.dependsOn(locker.finishLayer)

    private def copyJar(step:CompilationStep with Packaging, name:String) = task {
      FileUtilities.copyFile(step.packagingConfig.jarDestination,lib/name,log)
    }

    lazy val newForkjoin = copyJar(forkJoinConfig,forkjoinJarName).dependsOn(buildForkjoin)
    lazy val buildForkjoin= simpleBuild(forkJoinConfig).dependsOn(checkJavaVersion)
    lazy val newFjbg = copyJar(fjbgConfig, fjbgJarName).dependsOn(buildFjbg)
    lazy val buildFjbg = simpleBuild(fjbgConfig)
    lazy val newMsil = copyJar(msilConfig,msilJarName).dependsOn(buildMsil)
    // TODO As msil contains scala files, maybe needed compile it with an ExternalSBTRunner
    lazy val buildMsil = simpleBuild(msilConfig).dependsOn(quick.externalCompileLibraryOnly)

    lazy val forkJoinConfig = new CompilationStep("forkjoin",pathLayout,log) with Packaging{
      def label = "new forkjoin library"
      override def sources: PathFinder  = sourceRoots.descendentsExcept("*.java", ".svn")
      def dependencies = Seq()
      def options = Seq()
      override def javaOptions = Seq("-target","1.5","-source","1.5","-g")
      lazy val packagingConfig = new PackagingConfiguration(libsDestination/forkjoinJarName,List(outputDirectory ##))

      // TODO Verify java options
    }

    lazy val fjbgConfig =  new CompilationStep("fjbg",pathLayout,log) with Packaging{
      def label = "new fjbg library"
      override def sources: PathFinder  = sourceRoots.descendentsExcept("*.java", ".svn")
      def dependencies = Seq()
      def options = Seq()
      override def javaOptions = Seq("-target","1.5","-source","1.4","-g")
      lazy val packagingConfig = new PackagingConfiguration(libsDestination/fjbgJarName,List(outputDirectory ##))

    }

    lazy val msilConfig =  new CompilationStep("msil",pathLayout,log) with Packaging{
      def label = "new msil library"
      override def sources: PathFinder  = sourceRoots.descendentsExcept("*.java"|"*.scala", ".svn"|"tests")
      def dependencies = Seq()
      override def classpath = super.classpath +++ quick.libraryOutput
      def options = Seq()
      override def javaOptions = Seq("-target","1.5","-source","1.4","-g")
      lazy val packagingConfig = new PackagingConfiguration(libsDestination/msilJarName,List(outputDirectory ##))

    }
  }
 }