summaryrefslogblamecommitdiff
path: root/project/build/ScalaSBTBuilder.scala
blob: c741f3710cd24153c8ee267fe30a4d53a08b3686 (plain) (tree)
1
2
3
4
5
6
7
8
9
            
                          





                                                                                      
                                                                                                                                                           

                                                   
                                                                                                                                                               
                    
                                                                     
                               
                                









                                           

                                          

 









































                                                                                                                  

                                                                    






                                                                                               
 
                                           

















                                                                                              





                                                      



                               
                





                                 
                

     









                                    




                                                                

                                                                     








                                                                         
                                                                                                           


                                           
                                                                   







                                                                                                                
                                                                                                                                  

                                                    


                                           




                                                                      
 




                                                               
 
                                                                                                                           






                                                                                                                                              

                                                                                 





                                                                
                                                                                                                                 






















                                                                                          

 
 


















                                                                                                                                                                        
                                

                                                                                                                                  

                                                                                                   



                                                                                











                                                                                                                   
   







                                                                                                                                       

                                                                                                                                                                     








                                                                                        

                                                      






















































                                                                                                                     
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 ##))

    }
  }
 }