Cool, it sounds nice from your description. I checked out your github, but didn't find any examples of how your system works.
I think the ideal way for builds to work is to be able to define packages (that can be source, libraries, data, a genrule that runs a shell command) and the dependencies of that package (references to other packages). The build system should just know how to build various kinds of code (or maybe have one spot for configuring how your Java build runs, for example). It should also know what output files to look for, so that it can avoid re-building files over and over again. For the common languages, it can deduce where the built file should be. For genrules, the developer can specify what the output files are.
Issues I had with ant:
Ant requires you to specify the mechanics for how to build everything. It is difficult to impossible to express more complicated build rules (e.g. arbitrary shell commands were a huge pain). It also was very slow for incremental builds involving multiple projects, and it did not provide incremental builds for most build artifacts. For example, if an 'ant' rule generates a file, it will do so every time unless you write custom code to skip doing that based on hash or timestamp.
Ant is fine for one blog of code, but when you want to stop building the world, I find things get very difficult. It became painfully slow to build stuff, and difficult to write build files correctly as our system grew.
I don't have a ton of experience with other systems, but they seem to share a lot of the same problems.
Our packages work exactly the way you describe: a module which can build anything you like, and which has references to other packages for its dependencies.
Apters build steps let you run an arbitrary command, commonly a shell script. For more common cases (a C package with autotools, Java with Ant, etc), you can import a module which knows how to build them, and let it do all the work. (That module is versioned too.)
The language looks something like this:
let env = merge [deps.libfoo, deps.libbar, deps.gcc, prefix "src" (deps.source)]
in extract "/installpath" (build env "/buildscript")
This would merge together some dependencies, including the source code, run a build script in that environment, and extract the installation path from the result. /buildscript would likely contain something like "make DESTDIR=/installpath install".
deps.libfoo and deps.libbar get mapped to other Apters packages via a dependency list.
We handle incremental builds through caching: any build step with identical inputs (by hash) will use a cached result.
I think the ideal way for builds to work is to be able to define packages (that can be source, libraries, data, a genrule that runs a shell command) and the dependencies of that package (references to other packages). The build system should just know how to build various kinds of code (or maybe have one spot for configuring how your Java build runs, for example). It should also know what output files to look for, so that it can avoid re-building files over and over again. For the common languages, it can deduce where the built file should be. For genrules, the developer can specify what the output files are.
Issues I had with ant: Ant requires you to specify the mechanics for how to build everything. It is difficult to impossible to express more complicated build rules (e.g. arbitrary shell commands were a huge pain). It also was very slow for incremental builds involving multiple projects, and it did not provide incremental builds for most build artifacts. For example, if an 'ant' rule generates a file, it will do so every time unless you write custom code to skip doing that based on hash or timestamp.
Ant is fine for one blog of code, but when you want to stop building the world, I find things get very difficult. It became painfully slow to build stuff, and difficult to write build files correctly as our system grew.
I don't have a ton of experience with other systems, but they seem to share a lot of the same problems.
One of the closest ones I saw was gyp (http://code.google.com/p/gyp/), but it didn't support Java