Skip to: Site menu | Main content

Gant

Xircles | Mailing Lists | Confluence | JIRA | Source

A Groovy-based build system that uses Ant tasks, but no XML.

Targets Print

A Gant target is a Groovy code sequence that has a name and an associate description:

target ( target-name : target-description ) target-closure

So for example:

target ( flob : 'Some message or other.' ) {
  print ( 'Some message.' )
}

Any legal Groovy string can be used as the target-name but if it a Groovy keyword then it must be explicitly a string.  So the default target must have the name 'default' so that the Groovy compiler does not try and interpret the name of the target as the default keyword.

The target-description string is used as the string to output when executing "gant -T" to discover the list of allowed command-line targets. The string must always be present but, if it is the empty string, the task will not be treated as a target callable from the command line, and so will not appear in the target listing. Only targets with non-empty descriptions are treated as callable targets.

The target-closure can contain any legal Groovy code. An AntBuilder is pre-defined and is called Ant, so calls can be made to any Ant task:

target ( flob : 'Some message or other.' ) {
  echo ( message : 'Some message.' )
}

The usual rules associated with working with an AntBuilder apply.

As each task labels a closure then tasks can be called from other tasks:

target ( adob : 'A target called adob.' ) {
  flob ( )
}

Target flob is called as part of task adob. This allows a lot of dependency information to be expressed. However, the calls are always made, there is no implicit checking whether a target has already been executed. Instead there is a method depends that can be used to handle the situation where a target should only be called if it has not been executed already in this run.

target ( adob : 'A target called adob.' ) {
  depends ( flob )
}

The depends method is an executable method so it can be called at any time in a target closure. This allows for a much more flexible expression of dependency than specifying dependencies as a property of the target (as is done in Ant for example).

In the above examples, the target name was always a string literal - Groovy 'stringyfies' the key of a map by default and that is what is happening here. Often, particularly when synthesizing targets programmatically (the huge benefit of Gant over Ant!), we want the name of the target to be constructed. No problem here, we can do things like:

aTargetName = 'something'
target ( ( aTargetName ) : 'A target called' + aTargetName + '.' ) {
  println ( 'Executing ' + aTargetName )
}

Putting parentheses around the bit before the colon means that Groovy evaluates the expression and uses the result as the target name.

You might contemplate using GStrings in target names, and indeed descriptions, for example:

target ( "X${something}" : '' )

However, this is, in general, not a good thing to do. The reason is that GStrings are evaluated only on actual use and this means that if variable bindings have changed, the target name you thought you had is not the target name you actually have. There can be too much dynamism some times. So it is always wise to ensure that target names are fully evaluated at the point of target definition. There is no block to target synthesis, it just means don't use GStrings as target names.