用Ant构建脚本(2)
用Ant构建脚本(2)
二、用Ant写buildfile
Ant的buildfile是用xml写的。每一个buildfile包含了一个项目和一个及一个以上的对象。对象包含了多个任务元素。buildfile的每一个任务元素能有一个id属性,能在之后通过值来引用。这个值是唯一的。
build.xml文件是区分大小写的。其使用关键是编写build.xml文件,build.xml文件有五个主要的标识,如下:
1、Project元素
定义项目的属性,该标识有三个可以选择的属性:
Name项目的名称;
Default默认执行的target对象;
Basedir用于计算所有其它路径的基本路径(“.”表示当前路径)。该属性可以被basedir property覆盖,当覆盖时,该属性会被忽略。
示例:
<project name="examples" default="all" basedir=".">
2、Target元素
定义Ant命令的编译对象。
如Ant converter的编译对象是<target name="converter">
Target标识的属性解释如下:
Name,定义target的名字,供Ant命令使用;
Depends,定义它所依赖的其它执行对象,多个时用“,”隔开,即依赖表;
If,条件执行,执行target所需要设定的属性名,其property的值被设置后执行;
Unless,条件执行,执行target需要清除设定的属性名;其property的值未被设置时执行;
Description,该target功能的简单描述。
如:
<target name="converter" depends="init,compile,link,build">
Ant程序执行的先后顺序是init, compile, link, build。
一个target可以依赖于其它的target。在定义时要注意它们的依赖关系和顺序。如下:
<target name="A"/>
<target name="B" depends="A"/>
<target name="C" depends="B"/>
<target name="D" depends="C,B,A"/>
假定我们想执行目标D,从它的依赖属性看,你可以认为第一个目标是C,然后是B,再是A。不对,C依赖于B,B又依赖于A,因此,首先执行A,接着B,再是C,最后是D。
一个target只执行一次,即使有多个target依赖于它。
一个target还有完成它的执行的能力,除非对它单独设置了一个属性。这个属性允许你更好的控制建立过程,它依靠系统的状态,如:java版本,操作系统,命令行的属性定义等。
※※注意:Ant只检查是否设置了property,而不管它们的值。即便你设置的property是空字符串,也表示property存在。如:
<target name="build-module-A" if="module-A-present"/>
<target name="build-own-fake-module-A" unless=module-A-present"/>
在第一个例子中,如果设置了property的module-A-present值(任意值),target将被运行。
在第二个例子中,如果设置了property的module-A-present值(任意值),target则不能被执行。
3、Task元素
Tasks,定义要执行的命令的代码,一个task可以有多个属性或者参数,所有的task都有一个task名字属性。attribute的值可以包含一个property的引用。在task被执行前这些引用都会被处理。target有如下的通用结构:
<name attribute1="value1" attribute2="value2".../>
name是target的名字,attributeN是attribute的名字,valueN是attribute的值。
所有的task共享一个task名attribute。attribute的值将被输出的log消息中,在Ant执行时实现。
Ant有一套内置的task,以及一些可选的task,你也可以编写自己的task。task能够指定ID属性,如下:
<taskname id="taskID".../>
taskname是task的名字,taskID是这个task唯一的识别符。通过它你能更好地在脚本中或其它task中引用该task。例如:
<script...>
task1.setFoo("bar");
</script>
为这个特殊的task实例设置foo的attribute。在另一个task中,你通过project.getReference("task1")可以访问这个实例。
再如:
<javac srcdir="ejb/account" destdir="build/ejb/account" classpath="c:/j2sdk1.5/lib/j2ee.jar"/>
相当于执行命令javac -d build/ejb/account -classpath c:/j2sdk1.5/lib/j2ee.jar。
※※注意一:如果task1还没有运行,那么它还没有被配置;如果它在后面被配置,那么你对实例做的任何操作都将重来。
※※注意二:Ant未来的版本不喜欢反向兼容这个操作,因为这儿根本没有任何task实例。
4、Properties
定义tasks命令可以使用的属性,一个项目可以由一套property。property是固定不变的。无论谁设置了一个property,那么它就是固定不变的了。Ant定义的原则是先定义的有效,也就是说相同的属性,定义了多次,只有第一次的值是有效的。
有五种方式来设置property:
(1)通过name和value的attribute来设置;
(2)通过name和refid的attribute来设置;
(3)通过文件的attribute,如文件名、文件property来载入。这个property文件有一定的格式,通过使用类java.util.Properties来定义;
(4)通过用使用的property文件的resource名来设置resource的attribute。property文件的格式通过使用类java.util.Properties来定义;
(5)通过用使用的前缀来设置envirenment的attribute。通过前缀提供的名字和变量名的期限,为每一个环境变量定义property。
尽管这些方式的组合是可能的,但最好一次使用一种设置方式。
其属性参数如下:
name,设置的property名;
value,property的值;
location,路径;
refid,其它地方定义的对象的引用;
resource,property文件的源文件名;
file,property文件的文件名;
environment,当重新载入环境变量时使用的前缀;
classpath,要使用的源文件的路径;
classpathref,带引用的要使用的源文件的路径;
prefix,前缀。“.”表示当前的前缀。
举例:
<property name="buoo.dist" value="dest"/>
<property file="buoo.properties"/>
<property resource="buoo.properties"/>
<property file="${user.home}/.Ant-global.properties"/>
<property environment="env"/>
<echo message="Number of Processors=${env.NUMBER_OF_PROCESSORS}"/>
<echo message="Ant_HOME is set to =${env.Ant_HOME}"/>
一个property有一个名字和一个值,名字是大小写敏感的。property可以被用在task的attribute中。用${}来代替。
例如:一个名为“builddir”的property,值为“build”,那么它可以象这样使用:${builddir}/classes。它在运行时被作为build/classes。
property此标识在target标识下使用,如:
<target name="init">
<property name="build" value="build"/>
</target>
使用properties标识的代码如下:
<target name="prepare" depends="init">
<mkdir dir="${build}"/>
</target>
通过“${}”标识引用变量。
5、Built-in Properties
Ant提供了访问所有的系统property的方法,即build-in properties。似乎它们是用<property>定义的,例如,${os.name}扩展了操作系统名。
系统properties指的是可以查看System.getProperties返回的值,下面列出一些Java的系统属性:
(1)java.version:Java运行环境的版本;
(2)java.home:Java的安装目录;
(3)java.class.path:Java的CLASSPATH值;
(4)java.io.tmpdir:默认的临时路径;
(5)os.name:操作系统的名字;
(6)file.separator:文件分隔符(UNIX用“/”);
(7)path.separator:路径分隔符(UNIX用“:”);
(8)user.name:登陆操作系统的用户名;
(9)user.dir:用户当前的工作目录。
这些内建属性(build-in properties)可以直接像property那样引用。
除此之外,Ant还提供了自身的内建属性(build-in properties)供使用。
(1)basedir:项目的basedir的绝对路径,用<project>的basedir属性来定义;
(2)ant.file:buildfile的绝对路径;
(3)ant.version:Ant的版本;
(4)ant.project.name:当前执行的项目名;它通过<project>的name属性来设置;
(5)ant.java.version:Ant检测到的Java虚拟机的版本,当前它能有“1.1”,“1.2”,“1.3”,“1.4”等值。
如下所示:使用<echo>标签将这些内置的特性值输出。
<?xml version="1.0" encoding="UTF-8"?>
<project name="test" default="run">
<target name="run">
<echo message="${java.class.path}"/>
<echo message="${java.io.tmpdir}"/>
<echo message="${user.name}"/>
<echo message="${os.name}"/>
<echo message="${basedir}"/>
<echo message="${ant.file}"/>
<echo message="${ant.version}"/>
<echo message="${ant.project.name}"/>
<echo message="${ant.java.version}"/>
<echo message="${user.name}"/>
</target>
</project>
※※注意:
1、我们是在任何target外部声明的property。<property>、<typedef>和<taskdef>任务是特殊的,它们能在任何target外部来声明。当你这样做时,在任何target被执行前它们先进行求值。除此之外,没有任何其它的task能在target外部进行声明。
2、我们还有一些target描述,这会产生项目帮助请求选项为任何target列出它们,其它的target是内部的并且不会被列出。
3、最后,为了这个target,在src子目录下工作的源文件应该被存储在一个目录树下,用于匹配包名。检查<javac>任务可获得详情。