UncleJ is a tool for building Java projects, like the ubiquitous make utility or the more common alternative in the Java world, Apache Ant. Unlike either of them, however, it is designed primarily as a Java API with a small reflection-based harness; in this way it is very similar to JUnit, a popular tool for Java unit testing. Although it is intended more as an alternative to Ant than a supplement, it can easily incorporate the large library of existing "tasks" which Ant uses to drive other tools.
The Uncle approach (it could easily be extended to non-Java platforms) is intended to be:
Version 1.5 of the Java language is the largest change since inner classes were added in version 1.1. Although many of its own libraries have been updated to support the new language features, many other classes already seem antiquated by using integer constants rather than enumerations, by taking Object parameters when they should be using generics, and so on.
Given that this tool is written as an API, it doesn't make sense to design it using old conventions when the new ones are about to be released. This is particularly true since build files generally do not ship; that is, by using UncleJ you are not requiring your customers to install version 1.5, only your build machine.
The de facto standard for building Java projects is currently an open source tool called Ant. It was designed as a more Java-friendly alternative to the classic POSIX tool make. Ant improved on make in several ways, importantly:
Unfortunately, it also took a few steps backward from make:
Ant wisely chose to resist the urge to come up with a completely new scripting language or file format, choosing the meta-standard XML format instead. Tasks are implemented in Java and so once the targets and dependencies are straightened out, Ant basically acts as a reflection-based bridge between XML and Java.
But... why have a bridge, why not just write the whole thing in Java instead? It may seem that, even moreso than XML, Java is awkwardly verbose for a simple build file. However, code completion, refactoring operations, and other features of modern IDEs make the verbosity less of an issue, and there are many things in Java's favor:
After investigating what an Ant build might look like in Java, I found that under the hood, Ant sports a fairly clean design. There is some legacy cruft, a strange need for every minor object to have an up-reference to the project object, and a few unusual object construction patterns, but on the whole most Tasks are not hard to configure and use. If you can replace the target hierarchy with some basic logic, it's more than possible to write a build using Ant as a Java library rather than through an XML build file.
However, targets and dependencies are a fairly elegant way to structure a build and they can be non-trivial to replace, particularly in large projects. This is the core functionality of the Uncle framework: it provides a way to represent projects and targets in Java itself, and the logic for building them in order. It also provides a simple command line to locate targets through reflection and build them.
After working with this solution a bit, it became apparent that a new task framework also has some advantages: simulated runs can be introduced, tasks can be made Serializable for copying and distribution, tasks that have huge interfaces for legacy reasons can be simplified, the need for every object in the system to have a reference to the Project can be removed, and so on. Therefore a "UTask" class has also been introduced along with some implementations of common tasks for compiling, copying, and so on. The huge library of existing Ant tasks cannot be ignored, however, and so a simple adapter (AntAdapterUTask) is provided for turning Ant Tasks into (slightly less functional) UTasks.
UncleJ is free to use. To try it out on your project, just download the latest release from the file section and follow the instructions in the README.html.
Project hosted by: