logo

abstract class

build::BuildJava

sys::Obj
  build::BuildScript
    build::BuildJava
   1  //
   2  // Copyright (c) 2006, Brian Frank and Andy Frank
   3  // Licensed under the Academic Free License version 3.0
   4  //
   5  // History:
   6  //   3 Nov 06  Brian Frank  Creation
   7  //
   8  
   9  **
  10  ** BuildJava is the base class for build scripts used to manage
  11  ** building Java source code into a Java jar file.
  12  **
  13  abstract class BuildJava : BuildScript
  14  {
  15  
  16  //////////////////////////////////////////////////////////////////////////
  17  // Pod Meta-Data
  18  //////////////////////////////////////////////////////////////////////////
  19  
  20    **
  21    ** Required target jar file to build
  22    **
  23    File jar := null
  24  
  25    **
  26    ** Required list of dotted package names to compile.  Each of these
  27    ** packages must have a corresponding source directory relative to the
  28    ** script directory.
  29    **
  30    Str[] packages := null
  31  
  32    **
  33    ** Main class name to add to manifest if not null.
  34    **
  35    Str mainClass := null
  36  
  37  //////////////////////////////////////////////////////////////////////////
  38  // Setup
  39  //////////////////////////////////////////////////////////////////////////
  40  
  41    **
  42    ** Validate subclass constructor setup required meta-data.
  43    **
  44    internal override Void validate()
  45    {
  46      ok := true
  47      ok &= validateReqField("jar")
  48      ok &= validateReqField("packages")
  49      if (!ok) throw FatalBuildErr.make
  50    }
  51  
  52  //////////////////////////////////////////////////////////////////////////
  53  // BuildScript
  54  //////////////////////////////////////////////////////////////////////////
  55  
  56    **
  57    ** Default target is `compile`.
  58    **
  59    override Target defaultTarget() { return target("compile") }
  60  
  61  //////////////////////////////////////////////////////////////////////////
  62  // Compile
  63  //////////////////////////////////////////////////////////////////////////
  64  
  65    @target="compile Java source into jar"
  66    Void compile()
  67    {
  68      log.info("compile [${scriptDir.name}]")
  69      log.indent
  70  
  71      temp     := scriptDir + `temp/`
  72      jdk      := JdkTask.make(this)
  73      jarExe   := jdk.jarExe
  74      manifest := temp + `Manifest.mf`
  75  
  76      // make temp dir
  77      CreateDir.make(this, temp).run
  78  
  79      // find all the packages which have out of date files
  80      outOfDate := findOutOfDateDirs(temp)
  81      if (outOfDate.isEmpty)
  82      {
  83        log.info("Up to date!")
  84        return
  85      }
  86  
  87      // compile out of date packages
  88      javac := CompileJava.make(this)
  89      javac.src = outOfDate
  90      javac.cp.add(temp)
  91      javac.outDir = temp
  92      javac.run
  93  
  94      // write manifest
  95      log.info("Write Manifest [${manifest.osPath}]")
  96      out := manifest.out
  97      out.printLine("Manifest-Version: 1.0")
  98      if (mainClass != null) out.printLine("Main-Class: $mainClass")
  99      out.close
 100  
 101      // ensure jar target directory exists
 102      CreateDir.make(this, jar.parent).run
 103  
 104      // jar up temp directory
 105      log.info("Jar [${jar.osPath}]")
 106      Exec.make(this, [jarExe.osPath, "cfm", jar.osPath, manifest.osPath, "-C", temp.osPath, "."], temp).run
 107  
 108      log.unindent
 109    }
 110  
 111    private File[] findOutOfDateDirs(File temp)
 112    {
 113      acc := File[,]
 114      packages.each |Str p|
 115      {
 116        path := Uri.fromStr(p.replace(".", "/") + "/")
 117        srcDir := scriptDir + path
 118        outDir := temp + path
 119        if (anyOutOfDate(srcDir, outDir))
 120          acc.add(srcDir)
 121      }
 122      return acc
 123    }
 124  
 125    private Bool anyOutOfDate(File srcDir, File outDir)
 126    {
 127      return srcDir.list.any |File src->Bool|
 128      {
 129        if (src.ext != "java") return false
 130        out := outDir + (src.basename + ".class").toUri
 131        return !out.exists || out.modified < src.modified
 132      }
 133    }
 134  
 135  //////////////////////////////////////////////////////////////////////////
 136  // Clean
 137  //////////////////////////////////////////////////////////////////////////
 138  
 139    @target="delete all intermediate and target files"
 140    Void clean()
 141    {
 142      log.info("clean [${scriptDir.name}]")
 143      log.indent
 144      Delete.make(this, scriptDir + `temp/`).run
 145      Delete.make(this, jar).run
 146      log.unindent
 147    }
 148  
 149  //////////////////////////////////////////////////////////////////////////
 150  // Full
 151  //////////////////////////////////////////////////////////////////////////
 152  
 153    @target="clean+compile"
 154    Void full()
 155    {
 156      clean
 157      compile()
 158    }
 159  
 160  }