从Tomcat的构建工作分离出来
Apache Ant是以Java编写的构建自动化工具。它最初由詹姆斯·邓肯·戴维森为Tomcat编写,用来把源代码整理、编译并打包成可发布的软件。当Tomcat代码交给Apache软件基金会后,其他Java项目也开始采用这套办法;2000年1月,Ant移入单独的CVS代码模块,与Tomcat的日常开发分开。
这项工作随后成为Jakarta社区共同维护的项目。1.1版手册列有斯特凡·博德维格、科纳·麦克尼尔、萨姆·鲁比等人的署名,内容已覆盖安装、任务扩展和构建事件。Ant的使用对象也由一个服务器项目,扩展为需要重复执行编译、文件处理和发布步骤的Java开发团队。
把操作系统命令换成Java任务
早期手册直接说明了设计动机:传统Make类工具把依赖关系与外部命令结合起来,而这些命令往往依赖Unix或某一种操作系统环境。同一项目换到另一平台后,构建脚本可能也要跟着修改;制表符等格式细节则进一步增加维护负担。
Ant把构建说明写成XML,把具体操作交给Java类实现的任务。创建目录、调用编译器或生成压缩包,都可以作为已命名的任务放入构建文件。开发者仍可用exec调用外部命令,但普通构建流程不必处处依赖命令行程序。这种可移植性以Java运行环境和相应工具可用为前提;1.1版手册要求JDK 1.1或更新版本,并需要兼容JAXP的XML解析器。
参考:[1]
项目、目标与依赖次序
构建文件中的project定义整个项目,target把若干任务组成一个目标,depends说明先做什么。例如,发布目标依赖编译目标,编译又依赖创建输出目录的目标。运行发布目标时,Ant先处理前置依赖,然后执行目标内的任务;同一目标在一次构建中只执行一次,即使多个目标都依赖它。
这套依赖关系主要安排工作次序,是否需要重新处理某个文件则由任务决定。1.1版javac任务会比较源文件与对应class文件,只编译尚无class文件或源文件较新的Java文件。因而,目标被执行与所有源文件重新编译不是同一件事,任务本身也参与判断实际需要完成的工作。
参考:[1]
一个编译并打包的小例子
可以按1.1版手册的结构建立一个小项目:源代码放在src目录,编译结果放在build目录,发行文件放在dist/lib目录。先设置这些目录属性,再让prepare目标用mkdir建立build;compile目标依赖prepare,用javac把src中的Java源文件编译到build。
最后,dist目标依赖compile,先建立dist/lib,再用jar把build中的结果封装为foo.jar。把dist设为项目默认目标后,执行ant即可沿着准备、编译、打包的依赖链完成工作。另设clean目标删除输出目录,便能清理旧结果。目录属性还允许同一份构建说明在不同位置使用,而不必逐项改写路径。
参考:[1]
2000年7月的独立发行
Ant随Tomcat 3.1在2000年4月19日面向更多使用者发行,这个早期版本后来常被称为0.3.1。7月19日发布的Ant 1.1,才是第一个正式独立发行版。其发布说明解释了为何不从1.0编号:先前随Tomcat流传的构建已被部分人称为“1.0.8”,因此独立版本选择1.1以避免混淆。
这次发行同时调整了具体行为。属性被规定为不可变,构建文件不能覆盖命令行或Java系统属性给出的值;旧构建文件一般仍可使用,但可能出现弃用警告。可选任务的编译结果另放在optional.jar中,而非全部装入基础二进制发行包。对已有用户而言,发布既意味着工具可以独立取得,也意味着需要核对这些兼容性变化。
可扩展任务与早期边界
1.1版已经说明如何编写自己的任务:扩展org.apache.tools.ant.Task类,用setter方法接收XML属性,并在execute方法中实现操作,再通过taskdef登记。构建文件因此可以保持统一形式,而项目专用的工作由新增Java任务承担。
Ant早期提供的是一套可复用的构建执行框架:它组织目标、传递属性,并调用各项任务。项目仍须自行说明源文件位置、编译路径和发布内容。2000年的独立发行把这套原本服务于Tomcat的做法交给更广泛的Java社区。