我在Ant中构建了一个构建脚本,它有一个宏定义,该宏定义接受一些默认参数,比如target、root等,然后是可选的两个参数,分别是extrasrc-f和extrasrc c。在他们进来之后,我喜欢对所有相关的资源做一个最新的检查,然后只在目标是过期的情况下才进行构建。
我目前所拥有的,
<?xml version="1.0" encoding="UTF-8"?>
<project name="Custom build" default="default">
<taskdef resource="net/sf/antcontrib/antlib.xml"
classpath="C:/dev/ant/ant-contrib/ant-contrib-1.0b3.jar"/>
<macrodef name="checkuptodate">
<attribute name="target" />
<element name="resource" />
<sequential>
<condition property="needbuild">
<and>
<resourcecount when="greater" count="0"> <resource /> </resourcecount>
<not>
<uptodate targetfile="@{target}">
<srcresources> <resource /> </srcresources>
</uptodate>
</not>
</and>
</condition>
</sequential>
</macrodef>
<macrodef name="projbuild">
<attribute name="root" />
<attribute name="target" />
<element name="extrasrc-f" optional="true" />
<element name="extrasrc-c" optional="true" />
<sequential>
<local name="needbuild" />
<checkuptodate target="@{root}/bin/@{target}">
<resource>
<union>
<extrasrc-f />
<fileset dir="@{root}/src" includes="**/*.java" />
</union>
</resource>
</checkuptodate>
<if>
<istrue value="${needbuild}" />
<then>
<javac
srcdir="@{root}/src"
destdir="@{root}/bin"
includeantruntime="false"
>
<extrasrc-c />
</javac>
</then>
</if>
</sequential>
</macrodef>
<target name="default">
<projbuild root="." target="EntryPoint.class">
<extrasrc-f>
<fileset dir="Proj2/src" includes="**/*.java" />
<fileset dir="Proj3/src" includes="**/*.java" />
</extrasrc-f>
<extrasrc-c>
<classpath location="Proj2/src" />
<classpath location="Proj3/src" />
</extrasrc-c>
</projbuild>
</target>
</project>但是正如你所看到的,在这个时间点上,对于我来说,做我想做的事情是低效的,我必须创建并传递至少一个文件集和多个类路径。我真正想做的就是传入一个目录列表,然后从该信息中动态创建extrasrc-f和extrasrc-c元素,但对于我来说,我不知道如何才能做到这一点。
我读了很多关于Ant和Ant-Contrib时髦类的书,但我还没有读到任何能让我做这样的事情的东西,我确实觉得这很奇怪,因为对我来说这是一个显而易见的情况。
我是以一种非常错误的方式来处理这个问题,还是我遗漏了什么?如果我真的误用了Ant,我希望在正确的方向上指出如何正确地做到这一点,在宏定义(或目标,如果这是唯一的方法)中创建一个概括性的模板构建,它针对一个构建的文件测试多个源文件,同时也传递额外的类或库路径,最好是在一个单独的列表中。
发布于 2013-04-04 06:11:12
也许您可以使用几个任务来帮助分解这些宏。
首先,它接受以逗号分隔的目录列表,并从这些目录生成<union>。您需要提供要用来将联合引用为id属性的refid。有可选的包含和排除。
<scriptdef name="dirs2union" language="javascript">
<attribute name="dirs" />
<attribute name="id" />
<attribute name="includes" />
<attribute name="excludes" />
<![CDATA[
var dirs = attributes.get( "dirs" ).split( "," );
var includes = attributes.get( "includes" );
var excludes = attributes.get( "excludes" );
var union = project.createDataType( "union" );
project.addReference( attributes.get( "id" ), union );
for ( var i = 0; i < dirs.length; i++ ) {
var fs = project.createDataType( "fileset" );
fs.setDir( new java.io.File( dirs[i] ) );
if ( includes )
fs.setIncludes( includes );
if ( excludes )
fs.setExcludes( excludes );
union.add( fs );
}
]]>
</scriptdef>第二个非常类似的脚本执行与路径生成相同的操作:
<scriptdef name="dirs2path" language="javascript">
<attribute name="dirs" />
<attribute name="id" />
<![CDATA[
var dirs = attributes.get( "dirs" ).split( "," );
var path = project.createDataType( "path" );
project.addReference( attributes.get( "id" ), path );
for ( var i = 0; i < dirs.length; i++ ) {
var pe = project.createDataType( "path" );
pe.setLocation( new java.io.File( dirs[i] ) );
path.add( pe );
}
]]>
</scriptdef>一个示例用法可能是这样的:
<property name="dirs" value="Proj2/src,Proj3/src" />
<dirs2union dirs="${dirs}" id="my.union" includes="**/*.java" />
<dirs2path dirs="${dirs}" id="my.path" />
... later (e.g.) ...
<union refid="my.union" />
<classpath refid="my.path" />然后,您可以修改宏以获取dirs属性并在内部生成联合和类路径,也可以在别处生成这些并只传递引用。
我没有尝试在这个图例中包含@{root}目录,但是应该可以修改上面的目录。
https://stackoverflow.com/questions/10489186
复制相似问题