我有一个在 Ant 中构建的构建脚本,它有一个 macrodef,它接受一些默认参数,目标、根等,然后是可选的两个,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,我希望有关于如何正确执行此操作的正确方向的指针,在 macrodef(或目标,如果这是唯一的方法(中创建一个包罗万象的模板构建,它针对一个构建的文件测试多个源文件,同时还传递额外的类或库路径, 最好在一个列表中。
也许您可以使用几个<scriptdef>
任务来帮助分解这些宏。
首先,一个采用逗号分隔的目录列表并从中生成<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}
目录,但应该可以为此调整上述目录。