********************** * How does it works? * ********************** If you have a look at the easyant.ant script, you will see that it basically initialize Ivy with a repository provided in the "repository" directory. This repository is supposed to be available online in a released version of easyant, and contains the build modules available to the user. Then it uses the loadmodule task provided by easyant, which basically parses an Ivy file (module.ivy) and look for instructions in the Ivy file for easyant (similar to the pom concept actually). Finally the easyant script tries to import a file called module.ant in the user directory (the module to build), in the example there is no such file, but this would let the user customize the build with an Ant script if necessary. In the example you find two instructions: * the build type, which tells basically which build module should be imported (considered as an extends, see below) * a property definition, as you would have in an Ant script The idea is to have a very limited options of customizing the build in the Ivy file: settings properties, and telling which main build module should be imported. If you need more, you have to use a module.ant file. Ok, so the main build script is actually the build-std-java build module. But let's now have a look at the build modules available in the repository. There is three types of build modules: ******************* * + build plugins * ******************* build plugins are there to actually define each block of the build system. They interact with each other by relying on the file system and properties (for instance run-java expect java classes to be in directory pointed by ${target.main.classes}). For the whole build choreography they rely on phases. Each build plugin define the expected "parameters" (i.e. the expected properties, paths and phases) by using a parameter task like this: This is intended to be used both for validation and documentation, ATM only basic validation is performed. abstract-test provides test compilation feature checkstyle provides code quality feature clean-std provides project cleaning feature compile-java provides java compilation feature compile-scala provides scala compilation feature compile-test-java provides java compilation feature for tests compile-test-scala provides scala compilation feature for tests common-ivy provides ivy features (like features, clean cache, etc...) deps-lib provides very basic dependency management based on local lib directory emma provides code coverage features ivy-provisioning provides dependency management based on ivy javadoc provides javadoc features package-jar provides jar packaging feature package-war provides webapp packaging feature publication provides publication features (to share projects with your team) resources-std provides basic resources management, a la maven run-java provides java bytecode execution feature scaladoc provides scaladoc features test-junit provides junit tests compilation and execution feature test-testng provides testng tests compilation and execution feature ************************ * + phases description * ************************ phases descriptions define an ordered set of build phases. Build phases are responsible for the build choreography at macro level. They are inspired by the same concept in Maven. In practice they are very similar to Ant targets, except that their dependencies can be defined by the dependency target using a syntax like this: This basically adds the target "xxx" to the list of dependencies of the phase "yyy". Usually you use only one phases definition build module. phases-std describes the standard phases of a build. These phase are directly inspired by maven 2 standard phases. ***************** * + build types * ***************** build types are intended to provide a full build for a particular type of project (simple java, war, ear, ...). EasyAnt? would come with a set of build types modules, but users could extend/replace these types as they want. Then in most cases they could simply define which build type to import for each module (either standard or custom), and that's pretty much all. Hence you usually import only one build type module at a time. build-std-java a standard build for simple java modules, relying on standard phases, and providing compilation, execution and unit tests build-webapp-java a standard build for webapp java modules, relying on standard phases, and providing compilation, execution and unit tests build-std-scala? a standard build for simple scala modules, relying on standard phases, and providing compilation, execution and unit tests OK, I think you should now get a pretty good overview of how does it work. One missing piece is the tasks used to import build modules: ea:include and ea:import. Both of these tasks actually relies on Ivy to locate and download a build module (= an Ant script) and then use the import task to actually import the script. ea:import is basically the same as a regular import. Overriding targets is part of what you can do when you use import, and you usually import only one other build module. ea:include is a kind of import which puts the imported targets in a particular namespace. This allows to have a complete freedom of target names in each build module you use: several modules can define an "init" target for instance, and none of them will override each other. *************************************** * What a build module should document * *************************************** * phases on which it relies * parameters (properties, resource collections, paths), with for each if it is required or not, default value. * expected environment (files in a directory, a server up and running, ...) * results produced A build module should always check that the set of pre conditions is met in the validate phase (for static pre conditions) or at execution (for dynamic pre conditions). If ever what is considered static pre condition by a module is actually generated by another one, it is still possible to assign the build module validate phase to a phase triggered after the execution of the other build module (using phase mapping with the 'use' task). ********************* * Ant Modifications * ********************* Here you can find a list of ant modifications : ea:path similar to path but add an override attribute (Possible values are true / false / append / prepend) ea:include task A way to import ant file using "namespace" ea:import task Equivalents to the current import task ea:phase A kind of target that contains ONLY dependencies, useful to make build modules easily reusable in a standard build antlet Not yet implemented ***************** * easyant tasks * ***************** ************** * + ea:path * ************** ea:path is similar to path but add an override attribute with these values: * true: new definition will take precedence over preceding one if any * false: new definition will be discarded if any definition already exists * append: new definition will be added to the existing one if any * prepend: new definition will be added at the beginning of the existing one if any ************ * + ea:include * ************ The include mechanism is similar to the current import task, excepts that it automatically prefix all targets of the used build module (=ant script). The prefix used by default is the name of the imported project, but it can be overriden when calling "include". This is useful to use features provided by a build module, while preserving a namespace isolation to avoid names collisions. While possible, overriding a target defined in a included module is not recommended. To do so, the import mechanism is preferred. Example: module A: module B: This is equivalent to: OR for module B: which is equivalent to: **************** * + ea:import * **************** The import mechanism is equivalent to the current import mechanism. ********** * Phases * ********** a phase is a kind of target with special features: * have no body, only dependencies * dependencies are created on the fly (when a target is assigned to a phase) * order of dependencies is not guaranteed * are not prefixed in 'use', and never overriden * when using the 'use' task, it's possible to provide phase mapping This is useful to make build modules easily reusable in a standard build (with standard phases), without requiring any specific orchestration. In a sense it's similar to the 'before' attribute, except that the before is easily overridable with phase mapping when imported with a 'use'. Example: module A: module B: This is equivalent to: OR for module B: This is equivalent to: In a module plugin it's possible to assign a target to a phase which is not declared in the build module. It makes the module dependent on the caller to declare the phase prior to the use call (or use phase mapping), and as such becomes a requirement of the module. ******************************** * antlet (not yet implemented) * ******************************** ANTLET (not yet implemented related to ticket:8) ΒΆ An Antlet is an Ant script which is installed in Ant home, and that can easily be used by ant command line. This wold help use Ant with predefined scripts, without having to remember the path to provide to -f options For instance a directory called antlets could be added in ANT_HOME, each sub directory defining one Antlet: $ANT_HOME/antlets/fixcrlf/ $ANT_HOME/antlets/easyant/ $ANT_HOME/antlets/ivy/ ... These antlets can be listed using the ant command line: ant -list-antlets fixcrlf utilities to fix EOL in current directory easyant simple yet powerful build system for Java projects ivy manage your Ivy based repositories ... Then using an antlet is as simple as: ant -m easyant Build file: $ANT_HOME/antlets/easyant/antlet.ant ... BUILD SUCCESSFUL This is actually equivalent to: ant -f $ANT_HOME/antlets/easyant/antlet.ant