本地

自 Ant 1.8 起

描述

在当前作用域中添加一个本地属性。属性作用域存在于 Apache Ant 的各个“块”级别。这些包括目标以及 并行顺序 任务容器(包括 宏定义 主体)。给定作用域中的本地属性会“遮蔽”更高作用域中同名属性,包括全局作用域。请注意,在全局级别使用 Local 任务实际上会使属性对执行顶级操作的“匿名目标”变为本地属性;它不会为构建文件中的其他目标定义。

如果 <local> 任务在其定义之前,则属性将变为本地属性。请参阅示例部分。

参数

属性 描述 必需
name 要在当前作用域中声明的属性

作为嵌套元素指定的参数

名称

作为对 name 属性的替代(或与之结合),一个或多个嵌套 <name> 元素的嵌套文本指定要在本地作用域中声明的属性名称。自 Ant 1.10.13 起

示例

暂时遮蔽全局属性的值

<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>

输出

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

step2:
     [echo] In step2: foo is foo

这里 local 任务在目标 step1 的剩余部分中遮蔽了 foo 的全局定义。

创建线程本地属性

<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>

输出类似于

    [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

macrodef 中使用

这可能是 local 最有用的应用场景。如果您在 Ant 1.8.0 之前需要在 macrodef 中使用“临时属性”,您必须尝试想出一个在宏调用之间唯一的属性名称。

假设您想编写一个宏来创建给定文件的父目录。一个简单的做法是

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

但这会在第一次调用时创建一个全局属性 parent——由于属性不可变,任何后续调用都会看到相同的值,并尝试创建与第一次调用相同的目录。

在 Ant 1.8.0 之前,建议使用基于宏属性之一的属性名称,例如

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

现在,针对不同文件的调用将设置不同的属性,并且目录将被创建。不幸的是,这会“污染”全局属性空间。此外,在某些情况下,可能很难想出唯一的名称。

输入 <local>

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

每次调用都会获得一个名为 parent 的属性,并且根本不会存在任何全局属性。

使用嵌套名称元素

这种方式声明并执行单个任务,作为对需要比使用 @name 的单个调用更多 XML 行的补偿
<local>
  <name>foo</name>
  <name>bar</name>
  <name>baz</name>
</local>