ant学习笔记
转自 :李飞虎 blog :http://hi.baidu.com/annleecn/blog/category/ant%2Clog4j%2Cjunit
1,ant介绍
ant构建工具,我们能用到的多是它的编译,拷贝,复制,运行命令等功能.
ant的好处:1,跨平台,因为ant是使用java实现的;2,使用简单;3,语法清晰;4,功能强大.
ant做的很多事情,大部分是曾经一个叫make的工具所做的,make更多应用于c/c+ +;ant更多应用于java.
2,ant安装
到ant官方网站(http://ant.apache.org)上下载ant,我使用的是1.7.1.下载解压后,增加环境变量:
ANT_HOME:C:\TDDOWNLOAD\apache-ant-1.7.1
在path环境变量中加入ant的bin目录:%ANT_HOME%\bin
如果要让ant能支持JUnit,需要将JUnit的JUnit.jar放置在ant的lib目录,并记得改变CLASSPATH中原先有关于JUnt的设定,如:%ANT_HOME%\lib\junit.jar
cmd进入命令行界面,运行ant命令,可以测试是否安装成功
3,第一个ant脚本
3.1,用文本编写一个HelloWorld.java程序,代码如下:
package test.ant;
public class HelloWorld{
public static void main(String[] args){
System.out.println("hello world!");
}
}
3.2,用ant完成编译和运行
建立一个build.xml文件,内容如下:
<?xml version="1.0" encoding="UTF-8" ?>
<project name="HelloWorld" default="run" basedir=".">
<property name="src" value="src"/>
<property name="dest" value="classes"/>
<property name="hello_jar" value="hello1.jar"/>
<target name="init">
<mkdir dir="${dest}"/>
</target>
<target name="compile" depends="init">
<javac srcdir="${src}" destdir="${dest}"/>
</target>
<target name="build" depends="compile">
<jar jarfile="${hello_jar}" basedir="${dest}"/>
</target>
<target name="run" depends="build">
<java classname="test.ant.HelloWorld" classpath="${hello_jar}"/>
</target>
<target name="clean">
<delete dir="${dest}"/>
<delete dir="${hello_jar}"/>
</target>
<target name="rerun" depends="clean,run">
<ant target="clean"/>
<ant target="run"/>
</target>
</project>
3.3,解释上面的配置文件
<?xml version="1.0" encoding="UTF-8" ?>,指定一下版本号和编码方式,几乎所有的XML文件的第一行都是这样.
<project name="HelloWorld" default="run" basedir=".">,ant的所有内容必须包含在project元素里面,basedir是工作的根目录,default是默认要做的事.
<property name="src" value="src"/>,指定变量
<target name="compile" depends="init">
<javac srcdir="${src}" destdir="${dest}"/>
</target>,要运行的一个命令,depends是它所依赖的target,在执行前先检查depends是否被执行过,如果执行过则直接执行name的命令,否则先执行depends
的命令.
3.4,运行ant
新建一个文件夹,把HelloWorld.java文件放进去,在命令行进入build.xml文件所在的目录,再运行命令:ant;可以看到run命令以及它所依赖的命令都执行了一次.
如果只想执行某个命令,而不是默认命令,如执行build命令,则可以用:ant build;即格式为:ant + target name
4,整合多个build.xml文件的命令
在实际的工作过程中,可能会有一个项目分成很多个模块,每个模块因为由不同的人员负责,因此他们也写了build.xml文件,并且内容各不相同,这时要把它们整合到一起使用,这时有两个选择:
1,重新写一个build.xml;
2,利用他们已经写好的build.xml文件,进行整合.
例如,有三个小组,每个小组都有一个src文件夹和build.xml文件.这个时候可以建立三个文件夹src1,src2,src3,分别把他们的src和build放进去,然后写一个build.xml文件:
<?xml version="1.0" encoding="UTF-8" ?>
<project name="main" default="build" basedir=".">
<property name="bin" value="${basedir}\bin"/>
<property name="src1" value="${basedir}\src1"/>
<property name="src2" value="${basedir}\src2"/>
<property name="src3" value="${basedir}\src3"/>
<target name="init">
<mkdir dir="${bin}"/>
</target>
<target name="run">
<ant dir="${src1}" target="run"/>
<ant dir="${src2}" target="run"/>
<ant dir="${src3}" target="run"/>
</target>
<target name="clean">
<ant dir="${src1}" target="clean"/>
<ant dir="${src2}" target="clean"/>
<ant dir="${src3}" target="clean"/>
</target>
<target name="build" depends="init,call">
<copy todir="${bin}">
<fileset dir="${src1}">
<include name="*.jar"/>
</fileset>
<fileset dir="${src2}">
<include name="*.jar"/>
</fileset>
<fileset dir="${src3}">
<include name="*.jar"/>
</fileset>
</copy>
</target>
<target name="rebuild" depend="build,clean">
<ant target="clean"/>
<ant target="build"/>
</target>
</project>
OK,以上build.xml文件整合了三个build.xml子文件.
5,ant高级应用
property和xml include可以所build.xml中<property/>中的内容分离出来,共同使用,它们的优点如下:
property:维护简单,键值对容易记住;
xml include:不单可以提取出属性来,连target也可以
还是上面的例子,如果我想把src1,src2,src3这三个属性从xml中提取出来,可以新建一个文件all.properties,内容如下:
src1=D:\\study\\ant\\src1
src2=D:\\study\\ant\\src2
src3=D:\\study\\ant\\src3
然后,build.xml文件可以这样按下面的内容写,别人只需要更改配置文件,而不需要更改build.xml文件了.
<?xml version="1.0" encoding="UTF-8" ?>
<project name="main" default="build" basedir=".">
<property name="file" value="all.properties"/>
<property name="bin" value="${basedir}\bin"/>
<target name="init">
<mkdir dir="${bin}"/>
</target>
<target name="run">
<ant dir="${src1}" target="run"/>
<ant dir="${src2}" target="run"/>
<ant dir="${src3}" target="run"/>
</target>
<target name="clean">
<ant dir="${src1}" target="clean"/>
<ant dir="${src2}" target="clean"/>
<ant dir="${src3}" target="clean"/>
</target>
<target name="build" depends="init,call">
<copy todir="${bin}">
<fileset dir="${src1}">
<include name="*.jar"/>
</fileset>
<fileset dir="${src2}">
<include name="*.jar"/>
</fileset>
<fileset dir="${src3}">
<include name="*.jar"/>
</fileset>
</copy>
</target>
<target name="rebuild" depend="build,clean">
<ant target="clean"/>
<ant target="build"/>
</target>
<target name="test">
<ant dir="${src1}" target="test"/>
<ant dir="${src2}" target="test"/>
<ant dir="${src3}" target="test"/>
</target>
</project>
有时候又想给每个小组的build.xml加入几个target,一种做法是在每个小组的build.xml中加上target,然后在总的build.xml文件中调用,但有种更好的办法.可以写一个include.xml文件,内容如下:
<?xml version="1.0" encoding="UTF-8" ?>
<property name="src" value="src"/>
<property name="dest" value="classes"/>
<target name="test">
<ant target="run"/>
</target>
然后更改小组的build.xml文件,在文件头加上以下内容:
<!-- include a xml file , it can be common on property , can be also a target -->
<!DOCTYPE project [
<!ENTITY share-variable SYSTEM "file:../include.xml">
]>
&share-variable;
这个时候,只要在include.xml中添加property,target,子build.xml会同时添加这些property和target,而且不会让子build.xml变得更复杂.
添加后的build.xml文件内容如下:
6.ant常用命令
6.1,设置和使用classpath
设置代码如下:
<classpath id="project.class.path">
<pathelement path="${classpath}"/>
<fileset dir="lib">
<include name="**/*.jar"/>
</fileset>
<pathelement location="classes"/>
<dirset dir="build">
<include name="apps/**/classes"/>
<exclude name="apps/**/*Test*"/>
</dirset>
<filelist refid="third-party_jars"/>
</classpath>
使用代码如下:
<target>
<javac>
<classpath refid="project.class.path"/>
</javac>
</target>
6.2,输出信息
输出信息有两种写法:
1,<echo message="xxxx"/>
2,<echo>xxxx</echo>
输出一段XML
<echoxml file="subbuild.xml">
<project default="ann">
<target name="ann">
<echo>ann</echo>
</target>
</project>
</echoxml>
6.3,引入一个XML文件
<import file="../common-targets.xml"/>
6.4,拷贝和删除文件,目录
拷贝一个文件:
<copy file="myfile.txt" fofile="mycopy.txt"/>
拷贝一个文件到指定目录:
<copy file="myfile.txt" todir"../some/other/dir"/>
拷贝一个目录到另一个目录:
<copy todir="../new/dir">
<fileset dir="src_dir"/>
<exclude name="**/*.java"/>
</fileset>
</copy>
或
<copy todir="../dest/dir"
<fileset dir="src_dir" excludes="**/*.java"/>
</copy>
拷贝一个文件集合到一个目录,同时建立备份文件:
<copy todir="../backup/dir">
<fileset dir="src_dir"/>
<globmapper from="*" to="*.bak"/>
</copy>
拷贝一个集合的文件到一个目录,并替换掉@TITLE@
<copy todir="../backup/dir">
<fileset dir="src_dir"/>
<filterset>
<filter token="TITLE" value="Ann Lee"/>
</filterset>
</copy>
拷贝一个目录下的东西到另一个目录下
<copydir src="${src}/resources" dest="${dest}" includes="**/*.java" excludes="**/Test.java"/>
拷贝一个文件
<copyfile src="Test.java" dest="subdir/Test.java"/>
删除文件,目录,(拷贝中各种关于目录的操作也可以用在这里)
删除一个文件
<delete file="/lib/ant.jar"/>
删除一个目录
<delete dir="lib"/>
删除所有符合规则的文件(.bak文件)包括子目录
<delete>
<fileset dir="." includes="**/*.bak"/>
</delete>
删除当前目录下所有的文件和目录,包括当前目录
<delete includeEmptyDirs="true">
<fileset dir="build"/>
</delete>
删除当前目录下所有的文件和目录,不包括当前目录
<delete includeemptydirs="true">
<fileset dir="build" includes="**/*"/>
</delete>
删除当前目录下所有的svn相关文件(因为svn文件默认是excludes,所以要设置一下)
<delete defaultexcludes="false">
<fileset dir="src" includes="**/*.svn"/>
</delete>
删除文件目录树
<deltree dir="dist"/>
6.5,剪切文件
<move todir="some/new/dir">
<fileset dir="my/src/dir">
<include name="**/*.jar">
<exclude name="**/ant.jar/>
</fileset>
</move>
6.6重命名
<rename src="ann.jar" dest="ant-${version}.jar/>
6.7建立临时文件
在目录build下,建立名为temp.file,后缀为.xml的文件
<tempfile property="temp.file" destDir="build" suffix=".xml"/>
6.8,Touch的使用
如果文件不存在创建文件,如果存在,更改最后访问时间为当前系统时间
<touch file="myfile"/>
如果文件不存在创建文件,更改最后访问时间为06/28/2002 2:02 pm
<touch datetime="09/10/1974 4:30 pm">
<fileset dir="src_dir"/>
</touch>
6.9,Condition的使用
有<ant>,<or>,<not>等tag
<condition property="isMacOsButNotMacOsX">
<and>
<os family="mac"/>
<not>
<os family="unix"/>
</not>
</ant>
</condition>
6.10,替换replace
<replace file="configure.sh" value="defaultvalue" propertyFile="source/name.properties">
<replacefilter token="@token1@"/>
<replacefilter token="@token2@" value="value2"/>
<replacefilter token="@token2@" value="property.key"/>
</replace>
6.11,调用chmod
<chmod perm="go-rwx" type="file">
<fileset dir="/web">
<include name="**/*.cgi"/>
<include name="**/*.old"/>
</fileset>
<dirset dir="/web">
<include name="**/private_*"/>
</dirset>
</chmod>
6.12,checksum MD5运算
md5文件,然后把值放入ann.bar.MD5属性
<checksum file="ann.bar"/>
md5文件,然后把值放入annbarMD5属性
<checksum file="ann.bar" property="annbarMD5"/>
md5目录下的所有文件,然后建立一个.md5文件,把所有的md5值放入
<checksum>
<fileset dir=".">
<include name="ann*"/>
</fileset>
</checksum>
6.13,Available的使用
如果类存在,则设置属性Myclass.present为true,如果没有就false
<available classname="org.whatever.Myclass" property="Myclass.present"/>
如果文件存在则设置属性jaxp.jar.persent为true,否则为false
<property name="jaxp.jar" value="./lib/jaxp11/jaxp.jar"/>
<available file="${jaxp.jar}" property="jaxp.jar.present"/>
如果目录存在,则设置属性为true,否则为false
<available file="/usr/local/lib" type="dir" property="local.lib.present"/>
如果classpath下寻找class,存在则设置属性为true,否则为false
在工程tag下定义path,在target中使用
<property name="jaxp.jar" value="./lib/jaxp11/jaxp.jar"/>
<path id="jaxp" location="${jaxp.jar}"/>
<available classname="javax.xml.transform.Transformer" classpathref="jaxp" property="jaxp11.present"/>
如果在classpath下发现文件则设置属性为true,否则为false
<available property="hava.extras" resource="extratasks.properties">
<classpath>
<pathelement location="/usr/local/ant/extra.jar"/>
</classpath>
</available>
6.14,设置property
设置属性name-value
<property name="ann.dist" value="dist"/>
读取属性文件中的属性配置
<property file="ann.properties"/>
读取网络中的property-set
<property url="http://www.mysite.com/bla/props/ann.properties"/>
读取文件中的属性配置
<property resource="ann.properties"/>
读取环境变量
<property environment="env"/>
读取属性文件中的属性,并作为全局引用
<property file="/Users/antoine/.ant-golbal.properties"/>
6.15,错误处理
显示错误:
1,<fail>something wrong here.</fail>
2,<fail message="${属性}"/>
如果这个属性不存在显示错误:
<fail unless="failCondition" message="unless Condition"/>
如果这个属性存在显示错误
<fail if="failCondition" message="if Condition"/>
如果符合条件显示错误,(这里的条件是没有设置属性):
<fail message="tag condition">
<condition>
<not>
<isset property="failCondition"/>
</not>
</condition>
</fail>
6.16,建立一个目录
<mkdir dir="${dist}/lib"/>
6.17,打jar包
<jar destfile="${dist}/lib/app.jar" basedir="${build}/classes"/>
或者
<jar destfile="${dist}/lib/app.jar" basedir="${build}/classes" includes="mypackage/test/**" excludes="**/Test.class"/>
6.18,打Ear包
<ear destfile="build/myapp.ear" appxml="src/metadata/application.xml">
<fileset dir="build" includes="*.jar,*.war"/>
</ear>
6.19,执行程序
<target name="help">
<exec executable="cmd">
<arg value="/c"/>
<arg value="ant.bat"/>
<arg value="-p"/>
</exec>
</target>
6.20,运行jar包
带参数执行:
<java classname="test.Main">
<arg value="-h"/>
<classpath>
<pathelement loc ...