//
// Copyright (c) 2006, Brian Frank and Andy Frank
// Licensed under the Academic Free License version 3.0
//
// History:
// 3 Nov 06 Brian Frank Creation
//
**
** BuildJava is the base class for build scripts used to manage
** building Java source code into a Java jar file.
**
abstract class BuildJava : BuildScript
{
//////////////////////////////////////////////////////////////////////////
// Pod Meta-Data
//////////////////////////////////////////////////////////////////////////
**
** Required target jar file to build
**
Uri? jar
**
** Required list of dotted package names to compile. Each of these
** packages must have a corresponding source directory relative to the
** script directory.
**
Str[]? packages
**
** List of files to include in compiler classpath. The core
** Java rt.jar is always implied and should not be specified.
** These URIs are relative to the script dir.
**
Uri[]? cp
**
** Main class name to add to manifest if not null.
**
Str? mainClass
//////////////////////////////////////////////////////////////////////////
// Validate
//////////////////////////////////////////////////////////////////////////
private Void validate()
{
if (jar == null) throw fatal("Must set BuildJava.jar")
if (packages == null) throw fatal("Must set BuildJava.packages")
// boot strap checking - ensure that we aren't overwriting sys.jar
if (jar.name == "sys.jar")
{
if (Env.cur.homeDir == devHomeDir)
throw fatal("Must update 'devHome' for bootstrap build")
}
}
//////////////////////////////////////////////////////////////////////////
// Dump Env
//////////////////////////////////////////////////////////////////////////
override Void dumpEnv()
{
super.dumpEnv
oldLevel := log.level
log.level = LogLevel.silent
try
log.out.printLine(" javaHome: ${JdkTask(this).jdkHomeDir}")
catch (Err e)
log.out.printLine(" javaHome: $e")
finally
log.level = oldLevel
}
//////////////////////////////////////////////////////////////////////////
// Compile
//////////////////////////////////////////////////////////////////////////
**
** Compile Java source into jar
**
@Target { help = "Compile Java source into jar" }
Void compile()
{
validate
log.info("compile [${scriptDir.name}]")
log.indent
temp := scriptDir + `temp/`
jdk := JdkTask(this)
jarExe := jdk.jarExe
manifest := temp + `Manifest.mf`
jar := this.jar.toFile
// make temp dir
CreateDir(this, temp).run
// find all the packages which have out of date files
outOfDate := findOutOfDateDirs(temp)
if (outOfDate.isEmpty)
{
log.unindent
log.info("Up to date!")
return
}
// compile out of date packages
javac := CompileJava(this)
javac.src = outOfDate
javac.cp.add(temp)
if (cp != null) javac.cp.addAll(resolveFilesOrDirs(cp))
javac.outDir = temp
javac.run
// write manifest
log.info("Write Manifest [${manifest.osPath}]")
out := manifest.out
out.printLine("Manifest-Version: 1.0")
if (mainClass != null) out.printLine("Main-Class: $mainClass")
out.close
// ensure jar target directory exists
CreateDir(this, jar.parent).run
// jar up temp directory
log.info("Jar [${jar.osPath}]")
Exec(this, [jarExe, "cfm", jar.osPath, manifest.osPath, "-C", temp.osPath, "."], temp).run
log.unindent
}
private File[] findOutOfDateDirs(File temp)
{
acc := File[,]
packages.each |Str p|
{
path := Uri.fromStr(p.replace(".", "/") + "/")
srcDir := scriptDir + path
outDir := temp + path
if (anyOutOfDate(srcDir, outDir))
acc.add(srcDir)
}
return acc
}
private Bool anyOutOfDate(File srcDir, File outDir)
{
return srcDir.list.any |File src->Bool|
{
if (src.ext != "java") return false
out := outDir + (src.basename + ".class").toUri
return !out.exists || out.modified < src.modified
}
}
//////////////////////////////////////////////////////////////////////////
// Clean
//////////////////////////////////////////////////////////////////////////
**
** Delete all intermediate and target files
**
@Target { help = "Delete all intermediate and target files" }
Void clean()
{
log.info("clean [${scriptDir.name}]")
log.indent
Delete(this, scriptDir + `temp/`).run
Delete(this, jar.toFile).run
log.unindent
}
//////////////////////////////////////////////////////////////////////////
// Full
//////////////////////////////////////////////////////////////////////////
**
** Run clean, compile
**
@Target { help = "Run clean, compile" }
Void full()
{
clean
compile
}
}