Ant,跨平台构建工具 Ant,Apache Jakarta 小组的产品,是用作主要在 UNIX 下找到的标准 Make 实用程序的 Java 替代品。Ant 使用 XML 定义 Make 规则,并且缺省情况下尝试读取位于启动它的目录中的文件 build.xml。
任务 任务是 Ant“命令”,例如 javac、mkdir、echo 等等。Ant 提供了一组常见的任务,大多数 Java 开发人员会发现这些任务对于他们的构建需求来说已经足够全面。Ant 允许开发人员提供他们自己的任务。这只是简单地扩展 Ant 类 org.apache.tools.ant.Task 的事情,并提供读方法、写方法以及执行方法。这样,您就可以扩展 Ant 以执行您项目预定的行为。
缺省情况下,为文件存取操作提供了一组丰富的任务(例如复制和删除)以及同 Java 相关的任务(例如 Javadoc 和 Javac)。Ant 还允许用 Java 编写的扩展任务并将其合并到 build.xml 文件中。例如,您可能需要扩展任务,以与 Visual Age 进行对接、从数据库检索数据或为您的构建调用第三方工具中的方法。虽然这种机制提供了一种扩展 Ant 的功能强大的方法,但扩展却是用 100% 的 Java 编写的。这适合于许多情况,其中扩展扮演一个十分离散且独立的角色,但将脚本作为扩展机制的使用却允许将通常的脚本类型的命令聚合成一个功能更多、更强大的整体。
除了将新的用 Java 编码的任务添加到 Ant XML 构建中之外,您还可以使用 BSF 脚本来扩充它。Jacl 同 Ant 合作得非常好。有了 Java 基础,Jacl 代码(最终就是 Tcl)就可以使用扩展,这些扩展允许 Tcl 代码在解释 Jacl 代码的 VM 中创建并使用 Java 对象。这个 VM 同 Ant 的 VM 相同,这意味着作为解析 build.xml 的结果,Ant 所创建的任何 Java 对象可以通过 Jacl 代码看到和访问。
目标 build.xml 文件包含一个或多个目标,目标是标识一节可执行内容的元素类型。每个 build.xml 可以有一个缺省目标,并且这可以通过在命令行为 Ant 指定所需的目标来覆盖这一缺省值。Makefile 的必然结果将是诸如 install、clean、dist-clean 等的目标。
特性 Ant 以两种方式使用 Java 特性:作为 build.xml 的实体,以及作为 Ant 在运行时读取的标准 Java 特性文件内的实体。您可以使用特性来改变构建的行为,或者作为在 Jacl 脚本内,一种为常规 Ant 运行时提供有关一段 Jacl 脚本产生结果的反馈的方式。
安装 Ant 下载 Ant 时,请确保下载包含 Ant 源代码的版本。当与 Ant 一起使用 Jacl 时,这是非常有价值的;它们会给您带来生成大多数 Jacl 扩展所需的内部信息。解压缩源码分发版并执行构建 Ant 的指令。(在我使用的版本中有一个 bootstrap.sh,它构建所有所需的 jar 文件)。您需要添加到您的类路径中的 jar 文件是(可以从 Ant 根目录中看到):
./lib/jaxp.jar ./lib/parser.jar ./build/lib/ant.jar ./build/lib/optional.jar 现在,您已经有了完整的文件集,并已经安装了 bsf.jar、jacl.jar 和 tcljava.jar 这些 jar。BSF 框架使得 Ant“程序”内的所有对象对您的 Jacl 代码都是可见的,Ant“程序”毕竟在与 Jacl 代码相同的 VM 上运行。知道了 Ant 中使用什么类,Jacl 代码就能够调用它们的方法、访问字段,等等 ? 甚至能够动态地创建 Ant 类的实例。
开始脚本编制 一旦安装了 Ant 并运行了简单的 build.xml 文件,如何嵌入 Jacl 呢? 通过在 build.xml 中简单地使用 <script> 元素来实现。由于脚本无须有良好的格式,因此您必须将它隐藏在 CDATA 元素中,使它对于 XML 解析器不可见,如清单 5 中所示。
清单 6 中的示例演示了如何设置和获取特性,还演示了该特性的作用域。第一节演示了一个纯 XML 示例,在该示例中使用 Ant <property> 任务设置特性。第二节演示了使用 Jacl 重新实现以设置特性的目标 b。无论您使用哪种方法设置特性,结果都是相同的,如最后一部分的 Ant 运行时输出所示。这演示了特性 x 在目标 c(已由 b 所调用过的)的作用域中,但返回到目标 a 时不再在作用域内。
如果您想从 Jacl 脚本中调用一个现有的目标作为替代会怎样呢?有一种方法可以实现这一点,它是对 Ant/Jacl 脚本工具集的一个强有力的补充。然而,实现这一点需要些许附加编码。我发现使用现有的 Ant API 以这种特别的方式来调用目标是不可能的,但是我可以通过以两种额外的方法扩展 Ant 提供的类之一来设法实现这一点。首先,您必须创建一个如清单 10 中所示的 Java 扩展类。
<target name="targetXYZ"> <echo message="This is targetXYZ !!"> </target> </project>
在一个可能有很多 build.xml 文件的大型项目中,建议您用 Ant 进一步将通用代码分开。在一个 XML 文件中,您可以存储所有的 XML 目标,这些目标实现了您可能在不同的 build.xml 文件中所用到的公共功能;这甚至无须有完整的良好形式 ? 它可以只是在运行时包含在每个依赖的 build.xml 文件中的一个 XML 片段。这可以通过使用清单 13 中所示的 XML include 技巧来实现。
当运行清单 13 时,会在运行时将公共文件 common.xml(它含有公共的 XML 目标)的内容插入到 %IncludeBuildCommon 出现的地方。
通过使用清单 10 中的 calltargetmod 扩展,您可以在 Ant 构建中实现一些优秀的功能,这些功能不可能使用其它方式实现。我将给出几个示例。
首先,您可以创建一个实现切换功能的目标,该功能允许执行路径根据一个 Ant 特性值流向分支中的一个方向。首先,通过重用 calltargetmod(最好放在推荐的 common.xml 文件中)和使用 calltargetmod 的 build.xml,创建清单 14 中实现切换功能本身的 XML 片段,如清单所示。