Local

Since Ant 1.8

Description

Adds a local property to the current scope. Property scopes exist at Apache Ant's various "block" levels. These include targets as well as the Parallel and Sequential task containers (including Macrodef bodies). A local property at a given scope "shadows" properties of the same name at higher scopes, including the global scope. Note that using the Local task at the global level effectively makes the property local to the "anonymous target" in which top-level operations are carried out; it will not be defined for other targets in the buildfile.

A property is made local if the <local> task precedes its definition. See the examples section.

Parameters

Attribute Description Required
name The property to declare in the current scope Yes

Parameters specified as nested elements

Name

As an alternative to (or in conjunction with) the name attribute, the nested text of each of one or more nested <name> elements specifies a property name to declare in the local scope. Since Ant 1.10.13

Examples

Temporarily shadow a global property's value

<property name="foo" value="foo"/>

<target name="step1">
    <echo>Before local: foo is ${foo}</echo>
    <local name="foo"/>
    <property name="foo" value="bar"/>
    <echo>After local: foo is ${foo}</echo>
</target>

<target name="step2" depends="step1">
    <echo>In step2: foo is ${foo}</echo>
</target>

outputs

step1:
     [echo] Before local: foo is foo
     [echo] After local: foo is bar

step2:
     [echo] In step2: foo is foo

here the local task shadowed the global definition of foo for the remainder of the target step1.

Creating thread local properties

<property name="foo" value="foo"/>

<parallel>
    <echo>global 1: foo is ${foo}</echo>
    <sequential>
        <local name="foo"/>
        <property name="foo" value="bar.1"/>
        <echo>First sequential: foo is ${foo}</echo>
    </sequential>
    <sequential>
        <sleep seconds="1"/>
        <echo>global 2: foo is ${foo}</echo>
    </sequential>
    <sequential>
        <local name="foo"/>
        <property name="foo" value="bar.2"/>
        <echo>Second sequential: foo is ${foo}</echo>
    </sequential>
    <echo>global 3: foo is ${foo}</echo>
</parallel>

outputs something similar to

    [echo] global 3: foo is foo
    [echo] global 1: foo is foo
    [echo] First sequential: foo is bar.1
    [echo] Second sequential: foo is bar.2
    [echo] global 2: foo is foo

Use inside macrodef

This probably is where local can be applied in the most useful way. If you needed a "temporary property" inside a macrodef in Ant prior to Ant 1.8.0 you had to try to come up with a property name that would be unique across macro invocations.

Say you wanted to write a macro that created the parent directory of a given file. A naive approach would be:

<macrodef name="makeparentdir">
    <attribute name="file"/>
    <sequential>
        <dirname property="parent" file="@{file}"/>
        <mkdir dir="${parent}"/>
    </sequential>
</macrodef>
<makeparentdir file="some-dir/some-file"/>

but this would create a global property parent on the first invocation—and since properties are not mutable, any subsequent invocation will see the same value and try to create the same directory as the first invocation.

The recommendation prior to Ant 1.8.0 was to use a property name based on one of the macro's attributes, like

<macrodef name="makeparentdir">
    <attribute name="file"/>
    <sequential>
        <dirname property="parent.@{file}" file="@{file}"/>
        <mkdir dir="${parent.@{file}}"/>
    </sequential>
</macrodef>

Now invocations for different files will set different properties and the directories will get created. Unfortunately this "pollutes" the global properties space. In addition, it may be hard to come up with unique names in some cases.

Enter <local>:

<macrodef name="makeparentdir">
    <attribute name="file"/>
    <sequential>
        <local name="parent"/>
        <dirname property="parent" file="@{file}"/>
        <mkdir dir="${parent}"/>
    </sequential>
</macrodef>

Each invocation gets its own property named parent and there will be no global property of that name at all.

Use of nested name elements

This style declares and executes a single task, as compensation for requiring more lines of XML than would individual invocations using @name:
<local>
  <name>foo</name>
  <name>bar</name>
  <name>baz</name>
</local>