Scriptdef

描述

Scriptdef 可用于使用脚本语言定义 Apache Ant 任务。由 Apache BSFJSR 223 支持的 Ant 脚本语言可用于定义脚本。Scriptdef 提供了一种机制,可以将构建中的控制逻辑封装在 Ant 任务中,从而最大限度地减少在 Ant 本身中提供控制样式任务的需要。可以提供复杂的逻辑,同时保留 Ant 构建文件的简单结构。Scriptdef 也适用于为新的自定义任务创建原型。当然,随着脚本复杂度的增加,最好将任务定义迁移到基于 Java 的自定义任务中。

注意:此任务依赖于 Ant 发行版中未包含的外部库。有关更多信息,请参阅 库依赖项

可以使用 <attribute><element> 嵌套元素定义任务支持的属性和嵌套元素。这些元素可用于实现任务的脚本,作为两个集合样式脚本变量 attributeselementsattributes 集合中的元素可以通过属性名称访问。elements 集合可以通过嵌套元素名称访问。这将返回嵌套元素的所有实例的列表。此列表中的实例可以通过整数索引访问。

注意:Ant 将所有属性和元素名称转换为小写名称,因此即使您使用 name=SomeAttribute,您也必须使用 someattributeattributes 集合中检索属性的值。

名称 self自 Ant 1.6.3 起)是 scriptdef 任务实例的预定义引用。它可用于记录或与 Ant 的其余部分集成。self.text 属性包含传递给脚本的任何嵌套文本

如果未传入属性或元素,则 attributes.get()elements.get() 将返回 null。由脚本执行任何检查和验证。self.fail(String message) 可用于引发 BuildException

名称 project 是 Ant 项目的预定义引用。有关编写脚本的更多信息,请参阅 <script> 任务。

参数

属性 描述 必需
name 使用脚本创建的任务的名称
language 脚本编写的编程语言。必须是受支持的 Apache BSF 或 JSR 223 语言
manager 要使用的脚本引擎管理器。有关使用此属性的信息,请参阅 script 任务。 否;默认值为 auto
src 脚本作为文件的位置(如果不在内联中)
encoding 脚本作为文件的编码。自 Ant 1.10.2 起 否;默认为默认 JVM 字符编码
compiled 如果为 true,则在第一次评估之前编译脚本,以便更快地执行多次,前提是 managerjavax 且目标引擎实现了 javax.script.Compilable。请注意,bsf 管理器可能会自动编译脚本。自 Ant 1.10.2 起 否;默认为 false
uri 此定义应驻留的 XML 命名空间 URI。
classpath 传递到脚本的类路径。
classpathref 要使用的类路径,作为对在其他地方定义的路径的 引用 给出。
loaderRef 用于加载脚本的加载器的名称,由指定的类路径构建。这允许多个脚本定义重用相同的类加载器。
setbeans 此属性控制是否为运行脚本中的所有属性、引用和目标设置变量。如果此属性为 false,则仅设置 projectself 变量。如果此属性为 true,则设置所有变量。自 Ant 1.10.13 起 否;默认值为 false,以保持向后兼容性

作为嵌套元素指定的参数

attribute

属性 描述 必需
name 属性的名称
default 属性的默认值 自 Ant 1.10.13 起

element

属性 描述 必需
name 由脚本定义的任务支持的嵌套元素的名称
classname 要用于嵌套元素的类的类名。这直接指定类,是指定 Ant 类型名称的替代方法。
type 这是创建此元素时要使用的 Ant 任务或类型的名称。这是直接指定类名的替代方法。如果类型位于命名空间中,则 URI 和 : 必须作为前缀添加到类型。例如 type=antlib:example.org:newtype

classpath

有关使用此嵌套元素的信息,请参阅 script 任务。

任何资源集合

自 Ant 1.7.1 起

此任务可以从作为嵌套元素提供的任何资源加载脚本。

示例

以下定义创建了一个任务,该任务支持名为 attr 的属性和两个嵌套元素,一个是 fileset,另一个是 path。执行时,生成的 task 将记录属性的值和第一个 fileset 的 basedir

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

以下对上述脚本的变体列出了 fileset 元素的数量并遍历它们

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

当脚本存在语法错误时,scriptdef 名称将列在错误中。例如,在上面的脚本中,删除右大括号会导致以下错误

build.xml:15: SyntaxError: missing } in compound
statement (scriptdef <scripttest2>; line 10)

脚本错误仅在实际执行 script 任务时才会检测到。

下一个示例在 Jython 中使用嵌套文本。它还在新的 xml 命名空间中声明脚本,必须使用该命名空间来引用任务。在新的命名空间中声明脚本可确保 Ant 不会创建具有相同(命名空间、本地名称)名称对的任务。

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

下一个示例展示了 <classpath>loaderref 的使用,以访问 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"/>

测试脚本

测试脚本最简单的方法是使用 AntUnit Ant 库。这将运行脚本中以 test 开头的所有目标(及其依赖项)。