注: [本文属原创内容,如需转载请写明出处 http://blog.sina.com.cn/xiaoxiang7788]
最近接手一个C/C++项目, 编译环境早就有了, 是使用bat来写的.其编译器又选择了arm编译器.在看集成脚本的时候,感觉bat脚本晦涩难懂,需认真揣摩才可以明白其编译流程.
大体流程如下: 一个大的项目下面又分成了N个小项目,每个小项目对应一个集成bat脚本,然后在bat里面调用arm编译器,根据不同的条件对不同的源码进行编译,如编译参数设置等,其中最让xiaoxiang恼火的是编译的源码必须要一个一个的写明在bat的arm编译参数里面.
于是xiaoxiang想到了ant的条件编译和for循环, 并尝试研究了一下.
现总结如下,一者方便后来者,二者方便自己备查.
此处为build.properties中的内容,其中内容可根据不同环境进行不同的参数值修改,xiaoxiang的想法是通过java应用界面来实现不同值的填写,并生成build.properties内容.
build.properties
compiled.codes = test.c,test1.c,test2.c,test3.c
compile.codes.fb = fb.c,fb1.c,fb2.c,fb3.c
compile.arg = true
switch.value = true
需要下载ant的扩展包ant-contrib.jar
ant <for>
<project name="compile-codes" default="main">
<property file="./build.properties"/>
//使用taskdef定制ant-contrib任务
<taskdef resource="net/sf/antcontrib/antcontrib.properties"/>
<target name="init">
<delete dir="../workspace"/>
<mkdir dir="../workspace"/>
</target>
<target name="compile">
<for list="${compile.codes}" param="cfile"> // cfile等价于java程序中的参数.
<sequential> //执行for的循环体, 若有多个循环体,需要写多个<sequential>
<exec executable="cmd"> //调用cmd窗口
<arg value="/c"/>
<arg value="armcc"/> //启动armcc
<arg value="-c"/>
<arg value="@{cfile}"/> //上面的cfile参数,通过此处的@{cfile}格式来取值
</exec>
</sequential>
</for>
</target>
<target name="main" depends="init,compile">
</target>
</project>
ant <if> <elseif>
<project name="compile-codes-if" default="main">
<property file="./build.properties"/>
//使用taskdef定制ant-contrib任务
<taskdef resource="net/sf/antcontrib/antcontrib.properties"/>
<target name="init">
<delete dir="../workspace"/>
<mkdir dir="../workspace"/>
</target>
<target name="condition">
<if>
//条件判断,判断arg1 与 arg2两者的值是否相符, 其中arg2为从build.properties中取出的值
<equals arg1="true" arg2="${compile.arg}" />
<then>
//若符合判断条件,即条件成功,使用antcall命令来执行某个target
<antcall target="compile.codes.main"/>
</then>
<elseif>
<equals arg1="${compile.arg}" arg2="false" />
<then>
<antcall target="compile.codes.fb"/>
</then>
</elseif>
<else>
//若所判断条件没有成功,则输出提示信息.
<echo message="The value of the compile.arg can not be matched." />
</else>
</if>
</target>
<target name="compile.codes.main">
<for list="${compile.codes.main}" param="mainfile">
<sequential>
<exec executable="cmd">
<arg value="/c"/>
<arg value="armcc"/>
<arg value="-c"/>
<arg value="@{mainfile}"/>
</exec>
</sequential>
</for>
</target>
<target name="compile.codes.fb">
<for list="${compile.codes.fb}" param="fbfile">
<sequential>
<exec executable="cmd">
<arg value="/c"/>
<arg value="armcc"/>
<arg value="-c"/>
<arg value="@{fbfile}"/>
</exec>
</sequential>
</for>
</target>
<target name="main" depends="init,condition">
</target>
</project>
这个ant-if条件判断主要依据是build.properties中compile.arg的值的设定.然后根据判断出的不同的条件去执行不同的<for>循环体. 两个<for>循环体就不做过多的介绍了,可以参看ant-for的内容.
ant-switch
<project name="switch-test" default="switch">
<property file="./build.properties"/>
<taskdef resource="net/sf/antcontrib/antcontrib.properties"/>
<target name="switch">
<switch value="${switch.value}">
<case value="true">
<ant dir="." target="main"/>
</case>
<case value="false">
<ant dir="." target="main"/>
</case>
<default>
<echo message="Please check the value of the switch.value, it can not match to anything." />
</default>
</switch>
</target>
</project>
相信学过java或者C的朋友,一看这个<switch>便知其实现的功能和<if>是差不多的,主要也是用于条件判断, 哪个符合便去执行哪个循环体. 不做过多的说明了, 若觉得<switch>不好用,建议使用<if><elseif>.
<if><elseif>通过合理的排版,加之以适当的条件判断值(可以在build.properties中写多个值用于判断), 相信<if><elseif>功能可以满足大部分xiaoxiang的需求.
稍做说明: ant提供了,<for> <if> <elseif> <switch>等扩展功能, 这样也就使得ant有了基本的编程能力. 至于以上部分有看不明白的朋友,可以留言交流. 欢迎批评指正.