Introducing Schmant
Schmant is a tool for building software artifacts.
It provides a runtime environment and a set of tools (tasks) for your build scripts.
Build scripts are written in any of the four supported scripting languages; Groovy, JavaScript,
JRuby and Jython. The runtime environment gives the scripts access to
all Java classes, EntityFS classes and any number of
user-supplied classes too, so build scripts can be made as simple or complex as they need to be.
This simple example is borrowed from
User's guide.
It shows how Java classes are compiled and then bundled in a Jar file.
import java.io.File
import java.text.SimpleDateFormat
import java.util.Date
import org.entityfs.util.Directories
import org.schmant.support.io.TempFileUtil
import org.schmant.support.entityfs.SchmantFileSystems
import org.schmant.task.jdk.jar.JarTF
import org.schmant.task.jdk.javac.jdk6.Jdk6JavacTF
// Compile files from the directory /home/me/myproject/src and put the
// resulting class files in a temporary directory. The source files have
// compilation dependencies to all Jar files in /home/me/myproject/lib
// and to the Jar file /home/me/myproject/optlib/opt.jar
// A temporary java.io.File directory for the compiled classes. This,
// along with all of its contents, will be automatically deleted when
// Schmant exits (unless the -k flag was used when Schmant was
// launched).
def ctarget = TempFileUtil.createTempDir()
// This is the lib directory expressed as a (read only) EntityFS
// Directory. By using a Directory, the script can use the utility
// methods of Directories to extract the files it wants. See below.
def libDir = SchmantFileSystems.getEntityForDirectory(
new File("/home/me/myproject/lib"), true)
// Get all jar files from the lib directory. The jar files are returned
// as a Set of EntityFS EFile:s
def depjars = Directories.getAllFilesMatching(libDir, "*.jar")
// Add a dependency from the optlib directory. This is a Java File.
depjars.add(new File("/home/me/myproject/optlib/opt.jar"))
// Compile the Java source files.
new Jdk6JavacTF().
addSource(new File("/home/me/myproject/src")).
addClasspathEntries(depjars).
setTarget(ctarget).run()
// A timestamp for the built archive
def timestamp = new SimpleDateFormat("yyyyMMddHHmm").
format(new Date())
// Build the Jar file. Put it in /home/me/myproject
new JarTF().
addSource(ctarget).
setTarget(
new File("/home/me/myproject/myproject" + timestamp + ".jar")).
run()
// Compile files from the directory /home/me/myproject/src and put the
// resulting class files in a temporary directory. The source files have
// compilation dependencies to all Jar files in /home/me/myproject/lib
// and to the Jar file /home/me/myproject/optlib/opt.jar
// A temporary java.io.File directory for the compiled classes. This,
// along with all of its contents, will be automatically deleted when
// Schmant exits (unless the -k flag was used when Schmant was
// launched).
ctarget = TempFileUtil.createTempDir();
// This is the lib directory expressed as a (read only) EntityFS
// Directory. By using a Directory, the script can use the utility
// methods of Directories to extract the files it wants. See below.
libDir = SchmantFileSystems.getEntityForDirectory(
new File("/home/me/myproject/lib"), true);
// Get all jar files from the lib directory. The jar files are returned
// as a Set of EntityFS EFile:s
depjars = Directories.getAllFilesMatching(libDir, "*.jar");
// Add a dependency from the optlib directory. This is a Java File
depjars.add(new File("/home/me/myproject/optlib/opt.jar"));
// Compile the Java source files.
new Jdk6JavacTF().
addSource(new File("/home/me/myproject/src")).
addClasspathEntries(depjars).
setTarget(ctarget).run();
// A timestamp for the built archive
// java.text.SimpleDateFormat must be fully qualified since the
// java.text package classes are not automatically imported by Schmant.
// The "Packages" prefix is for telling JavaScript that it is a Java
// package. It is required sometimes. See the chapter on script language
// support for more information.
timestamp = new Packages.java.text.SimpleDateFormat("yyyyMMddHHmm").
format(new Date());
// Build the Jar file. Put it in /home/me/myproject
new JarTF().
addSource(ctarget).
setTarget(
new File("/home/me/myproject/myproject" + timestamp + ".jar")).
run();
# Compile files from the directory /home/me/myproject/src and put the
# resulting class files in a temporary directory. The source files have
# compilation dependencies to all Jar files in /home/me/myproject/lib
# and to the Jar file /home/me/myproject/optlib/opt.jar
# A temporary java.io.File directory for the compiled classes. This,
# along with all of its contents, will be automatically deleted when
# Schmant exits (unless the -k flag was used when Schmant was launched).
ctarget = Schmant::TempFileUtil.createTempDir
# This is the lib directory expressed as a (read only) EntityFS
# Directory. By using a Directory, the script can use the utility
# methods of Directories to extract the files it wants. See below.
#
# File is not included in the Schmant module, so we have to access it
# through the Java module instead.
libDir = Schmant::SchmantFileSystems.getEntityForDirectory(
Java::JavaIo::File.new("/home/me/myproject/lib"), true)
# Get all jar files from the lib directory. The jar files are returned
# as a Set of EntityFS EFile:s
depjars = Schmant::Directories.getAllFilesMatching(libDir, "*.jar")
# Add a dependency from the optlib directory. This is a Java File.
depjars.add(Java::JavaIo::File.new("/home/me/myproject/optlib/opt.jar"))
# Compile the Java source files.
Schmant::Jdk6JavacTF.new.
addSource(Java::JavaIo::File.new("/home/me/myproject/src")).
addClasspathEntries(depjars).
setTarget(ctarget).run
# A timestamp for the built archive
timestamp = Java::JavaText::SimpleDateFormat.new("yyyyMMddHHmm").
format(Java::JavaUtil::Date.new)
# Build the Jar file. Put it in /home/me/myproject
Schmant::JarTF.new.
addSource(ctarget).
setTarget(
Java::JavaIo::File.new(
"/home/me/myproject/myproject" + timestamp + ".jar")).
run
# Compile files from the directory /home/me/myproject/src and put the
# resulting class files in a temporary directory. The source files have
# compilation dependencies to all Jar files in /home/me/myproject/lib
# and to the Jar file /home/me/myproject/optlib/opt.jar
# A temporary java.io.File directory for the compiled classes. This,
# along with all of its contents, will be automatically deleted when
# Schmant exits (unless the -k flag was used when Schmant was launched).
ctarget = TempFileUtil.createTempDir()
# This is the lib directory expressed as a (read only) EntityFS
# Directory. By using a Directory, the script can use the utility
# methods of Directories to extract the files it wants. See below.
libDir = SchmantFileSystems.getEntityForDirectory(
File("/home/me/myproject/lib"), True)
# Get all jar files from the lib directory. The jar files are returned
# as a Set of EntityFS EFile:s
depjars = Directories.getAllFilesMatching(libDir, "*.jar")
# Add a dependency from the optlib directory. This is a Java File.
depjars.add(File("/home/me/myproject/optlib/opt.jar"))
# Compile the Java source files.
Jdk6JavacTF(). \
addSource(File("/home/me/myproject/src")). \
addClasspathEntries(depjars). \
setTarget(ctarget).run()
# A timestamp for the built archive
#
# SimpleDateFormat is not automatically imported by the preparation
# script.
from java.text import SimpleDateFormat
timestamp = SimpleDateFormat("yyyyMMddHHmm"). \
format(Date())
# Build the Jar file. Put it in /home/me/myproject
JarTF(). \
addSource(ctarget). \
setTarget(File("/home/me/myproject/myproject" + timestamp + ".jar")). \
run()
As the example above shows, Schmant includes the
EntityFS APIs and utilities for working
with files and directories.
Interpreted arguments
The
source
and
target
properties of tasks that support
them, for instance, accept
Object
arguments. The task tries to
interpret an untyped argument as something useful (often using the
ArgumentInterpreter
class). This gives the build scripts great flexibility in what kinds of arguments they can
throw at the tasks. The first example above used plain Java
File
arguments, and the
second example used Schmant's
DirectoryAndFilter.
All available tasks bundled with Schmant are listed in the Task
factory reference (The user's guide explains the difference between tasks and task factories.)
In addition to the tasks bundled with Schmant, there are also tasks in separate
task packages.
Task executors
Instead of running the tasks when they are defined, a Schmant script may
choose to use one or several
task
executors for distributing the workload over several execution threads. This
can often drastically reduce the time required for builds, but it introduces the
need to handle dependencies between related tasks.
Project repositories
Schmant comes with tools for working with
project
repositories. A project repository contains a collection of
projects.
This can be an
Eclipse
workspace with
java
projects. The
JavaWorkspaceBuilderTF task
can be used for building projects in a project repository. There are also tools for resolving dependencies between projects and for
filtering
projects by, for instance,
type
or
name.
Migration from Ant
To assist those daring enough to migrate away from Apache Ant, Schmant comes with the
AntTF task. It can run whole Ant scripts or
single Ant tasks.
Further reading
The next stop on the road to Schmant enlightenment is the
User's guide.