在运行时在 Ant 中创建具有动态内容的联合和 Macrodef 样式元素



我有一个在 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}目录,但应该可以为此调整上述目录。

相关内容

  • 没有找到相关文章

最新更新