Antlib

描述

Antlib 文件是一个根元素为 antlib 的 xml 文件。Antlib 的元素是 Apache Ant 定义任务,例如 Taskdef 或任何扩展 org.apache.tools.ant.taskdefs.AntlibDefinition 的 Ant 任务。

当前与 Ant 捆绑在一起的声明集执行此操作的是

  1. Typedef
  2. Taskdef
  3. Macrodef
  4. Presetdef
  5. Scriptdef

一组任务和类型可以在 antlib 文件中一起定义。例如,文件 sample.xml 包含以下内容

<?xml version="1.0"?>
<antlib>
    <typedef name="if" classname="org.acme.ant.If"/>
    <typedef name="scriptpathmapper"
             classname="org.acme.ant.ScriptPathMapper"
             onerror="ignore"/>
    <macrodef name="print">
        <attribute name="file"/>
        <sequential>
            <concat taskname="print">
                <fileset dir="." includes="@{file}"/>
            </concat>
        </sequential>
    </macrodef>
</antlib>

它定义了两种类型或任务,ifscriptpathmapper。此 antlib 文件可以在构建脚本中使用,如下所示

<typedef file="sample.xml"/>

<typedef> 的其他属性也可以使用。例如,假设 sample.xml 位于包含类的 jar 文件 sample.jar 中,以下构建片段将定义 ifscriptpathmapper 任务/类型,并将它们放置在命名空间 URI samples:/acme.org 中。

<typedef resource="org/acme/ant/sample.xml"
         uri="samples:/acme.org"/>

然后可以按如下方式使用这些定义

<sample:if valuetrue="${props}" xmlns:sample="samples:/acme.org">
    <sample:scriptpathmapper language="beanshell">
        some bean shell
    </sample:scriptpathmapper>
</sample:if>

Antlib 命名空间

具有模式 antlib:java.package 的命名空间 URI 会得到特殊处理。

当 Ant 遇到具有此模式的命名空间 URI 的元素时,它将检查默认类路径中的包目录中是否存在名为 antlib.xml 的资源。

例如,假设文件 antcontrib.jar 已放置在目录 ${ant.home}/lib 中,并且它包含资源 net/sf/antcontrib/antlib.xml,其中包含所有 antcontrib 的定义,以下构建文件将自动加载 antcontrib 定义在位置 HERE

<project default="deletetest" xmlns:antcontrib="antlib:net.sf.antcontrib">
    <macrodef name="showdir">
        <attribute name="dir"/>
        <sequential>
            <antcontrib:shellscript shell="bash">  <!-- HERE -->
                ls -Rl @{dir}
            </antcontrib:shellscript>
        </sequential>
    </macrodef>

    <target name="deletetest">
        <delete dir="a" quiet="yes"/>
        <mkdir dir="a/b"/>
        <touch file="a/a.txt"/>
        <touch file="a/b/b.txt"/>
        <delete>
            <fileset dir="a"/>
        </delete>
        <showdir dir="a"/>
    </target>
</project>

资源位于默认类路径中的要求可能会在 Ant 的未来版本中删除。

从构建文件内部加载 antlib

如果您想将 antlib 与本地 Ant 安装分开,例如因为您想将该 jar 保存在项目的 SCM 系统中,则必须指定一个类路径,以便 Ant 可以找到该 jar。最好的解决方案是使用 <taskdef> 加载 antlib。

<project xmlns:antcontrib="antlib:net.sf.antcontrib">
    <taskdef uri="antlib:net.sf.antcontrib"
             resource="net/sf/antcontrib/antlib.xml"
             classpath="path/to/ant-contrib.jar"/>

    <target name="iterate">
        <antcontrib:for param="file">
            <fileset dir="."/>
            <sequential>
                <echo message="- @{file}"/>
            </sequential>
        </antcontrib:for>
    </target>
</project>

当前命名空间

在 antlib 中定义的定义可以在 antlib 中使用。但是,定义所在的命名空间取决于使用 antlib 的 <typedef>。为了解决这个问题,在 antlib 执行期间,定义将放置在命名空间 URI ant:current 中。例如,以下 antlib 定义了任务 <if>、类型 <isallowed> 和一个宏 <ifallowed>,该宏使用任务和类型

<antlib xmlns:current="ant:current">
    <taskdef name="if" classname="org.acme.ant.If"/>
    <typedef name="isallowed" classname="org.acme.ant.Isallowed"/>
    <macrodef name="ifallowed">
        <attribute name="action"/>
        <element name="do"/>
        <sequential>
            <current:if>
                <current:isallowed test="@{action}"/>
                <current:then>
                    <do/>
                </current:then>
            </current:if>
        </sequential>
    </macrodef>
</antlib>

其他示例和注释

Antlib 可以使用其他 antlib。

由于 antlib 中定义的名称位于调用 <typedef> 或通过自动元素解析指定的命名空间 URI 中,因此可以重复使用核心 Ant 类型和任务中的名称,前提是调用方使用命名空间 URI。例如,以下 antlib 可用于为各种任务定义默认值

<antlib xmlns:antcontrib="antlib:net.sf.antcontrib">
    <presetdef name="javac">
        <javac deprecation="${deprecation}"
               debug="${debug}"/>
    </presetdef>
    <presetdef name="delete">
        <delete quiet="yes"/>
    </presetdef>
    <presetdef name="shellscript">
        <antcontrib:shellscript shell="bash"/>
    </presetdef>
</antlib>

这可以按如下方式使用

<project xmlns:local="localpresets">
    <typedef file="localpresets.xml" uri="localpresets"/>
    <local:shellscript>
        echo "hello world"
    </local:shellscript>
</project>