Scriptdef
can be used to define an Apache Ant task using a scripting language. Ant
scripting languages supported by Apache
BSF or JSR 223 may be used to define the script. Scriptdef
provides a
mechanism to encapsulate control logic from a build within an Ant task minimizing the need for
providing control style tasks in Ant itself. Complex logic can be made available while retaining the
simple structure of an Ant build file. Scriptdef
is also useful for prototyping new
custom tasks. Certainly as the complexity of the script increases it would be better to migrate the
task definition into a Java based custom task.
Note: This task depends on external libraries not included in the Ant distribution. See Library Dependencies for more information.
The attributes and nested elements supported by the task may be defined
using <attribute>
and <element>
nested elements. These are
available to the script that implements the task as two collection style script
variables attributes
and elements
. The elements
in the attributes
collection may be accessed by the attribute
name. The elements
collection is accessed by the nested element name. This
will return a list of all instances of the nested element. The instances in this list may be
accessed by an integer index.
Note: Ant will turn all attribute and element names into all lowercase names, so
even if you use name=SomeAttribute
, you'll have to use someattribute
to
retrieve the attribute's value from the attributes
collection.
The name self
(since Ant 1.6.3) is a pre-defined reference to
the scriptdef
task instance. It can be used for logging, or for integration with the
rest of Ant. The self.text
attribute contains any nested text passed to
the script
If an attribute or element is not passed in, then attributes.get()
or elements.get()
will return null. It is up to the script to perform any
checks and validation. self.fail(String message)
can be used to raise
a BuildException
.
The name project
is a pre-defined reference to the Ant Project. For
more information on writing scripts, please refer to
the <script>
task.
Attribute | Description | Required |
---|---|---|
name | the name of the task to be created using the script | Yes |
language | The programming language the script is written in. Must be a supported Apache BSF or JSR 223 language | Yes |
manager | The script engine manager to use. See the script task for using this attribute. | No; default is auto |
src | The location of the script as a file, if not inline | No |
encoding | The encoding of the script as a file. since Ant 1.10.2. | No; defaults to default JVM character encoding |
compiled | If true, the script is compiled before the first evaluation for faster multiple executions,
on the condition that the manager is javaxand the target engine implements javax.script.Compilable . Note that the bsfmanager may automatically compile the script. since Ant 1.10.2. |
No; defaults to false |
uri | The XML namespace uri that this definition should live in. | No |
classpath | The classpath to pass into the script. | No |
classpathref | The classpath to use, given as a reference to a path defined elsewhere. | No |
loaderRef | the name of the loader that is used to load the script, constructed from the specified classpath. This allows multiple script definitions to reuse the same class loader. | No |
setbeans | This attribute controls whether to set variables for all properties, references and targets
in the running script. If this attribute is false, only the project and
self variables are set. If this attribute is trueall the variables are set. Since Ant 1.10.13 |
No; default falsefor backward compatibility |
Attribute | Description | Required |
---|---|---|
name | the name of the attribute | Yes |
default | the default value of the attribute Since Ant 1.10.13 | No |
Attribute | Description | Required |
---|---|---|
name | the name of the nested element to be supported by the task defined by the script | Yes |
classname | the classname of the class to be used for the nested element. This specifies the class directly and is an alternative to specifying the Ant type name. | No |
type | This is the name of an Ant task or type which is to be used when this element is to be
created. This is an alternative to specifying the class name directly. If the type is in a
namespace, the URI and a :must be prefixed to the type. For example type= antlib:example.org:newtype |
No |
See the script task for using this nested element.
Since Ant 1.7.1
This task can load scripts from any resource supplied as a nested element.
The following definition creates a task which supports an attribute called attr and two nested elements, one being a fileset and the other a path. When executed, the resulting task logs the value of the attribute and the basedir of the first fileset.
<scriptdef name="scripttest" language="javascript"> <attribute name="attr1"/> <element name="fileset" type="fileset"/> <element name="path" type="path"/> <![CDATA[ self.log("Hello from script"); self.log("Attribute attr1 = " + attributes.get("attr1")); self.log("First fileset basedir = " + elements.get("fileset").get(0).getDir(project)); ]]> </scriptdef> <scripttest attr1="test"> <path> <pathelement location="src"/> </path> <fileset dir="src"/> <fileset dir="main"/> </scripttest>
The following variation on the above script lists the number of fileset elements and iterates through them
<scriptdef name="scripttest2" language="javascript"> <element name="fileset" type="fileset"/> <![CDATA[ filesets = elements.get("fileset"); self.log("Number of filesets = " + filesets.size()); for (i = 0; i < filesets.size(); ++i) { self.log("fileset " + i + " basedir = " + filesets.get(i).getDir(project)); } ]]> </scriptdef> <scripttest2> <fileset dir="src"/> <fileset dir="main"/> </scripttest2>
When a script has a syntax error, the scriptdef
name will be listed in the
error. For example in the above script, removing the closing curly bracket would result in this
error
build.xml:15: SyntaxError: missing } in compound statement (scriptdef <scripttest2>; line 10)
Script errors are only detected when a script
task is actually executed.
The next example does uses nested text in Jython. It also declares the script in a new xml namespace, which must be used to refer to the task. Declaring scripts in a new namespace guarantees that Ant will not create a task of the same (namespace,localname) name pair.
<target name="echo-task-jython"> <scriptdef language="jython" name="echo" uri="https://example.org/script"> <![CDATA[ self.log("text: " +self.text) ]]> </scriptdef> </target> <target name="testEcho" depends="echo-task-jython" xmlns:s="https://example.org/script"> <s:echo>nested text</s:echo> </target>
The next example shows the use of <classpath>
and loaderref to get
access to the beanshell jar.
<scriptdef name="b1" language="beanshell" loaderref="beanshell-ref"> <attribute name="a"/> <classpath path="${user.home}/scripting/beanshell/bsh-1.3b1.jar"/> self.log("attribute a is " + attributes.get("a")); </scriptdef> <scriptdef name="b2" language="beanshell" loaderref="beanshell-ref"> <attribute name="a2"/> self.log("attribute a2 is " + attributes.get("a2")); </scriptdef> <b1 a="this is an 'a'"/> <b2 a2="this is an 'a2' for b2"/>
The easiest way to test scripts is to use the AntUnit Ant library. This will run all targets in a script that begin
with test
(and their dependencies).