
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 }