ant - uptodate 任务:仅重新生成过时的文件

问题描述:

我是 ant 的新手,而是习惯了 Makefile.在一个项目中,i18n语言模块Message_zh.class等,每次编译都是从zh.po等无条件构建的,虽然它们已经存在,浪费了很多时间.我认为这些是 build.xml 的相关部分:

I'm new to ant and rather used to Makefiles. In a project, the i18n language modules named Message_zh.class etc are built unconditionally from zh.po etc with every compile, although they already exist, which wastes much time. I figured these are the relevant parts of build.xml:

<target id="msgfmt" name="msgfmt">
    <mkdir dir="po/classes" />
    <propertyregex property="filename"
              input="${file}"
              regexp="[.]*/po/([^\.]*)\.po"
              select="\1"
              casesensitive="false" />
    <exec dir="." executable="msgfmt">
        <arg line="--java2 -d po/classes -r app.i18n.Messages -l ${filename} po/${filename}.po"/>
    </exec>
</target>

<target id="build-languageclasses" name="build-languageclasses" >
    <echo message="Compiling po files." />
    <foreach target="msgfmt" param="file">
      <path>
        <fileset dir="po" casesensitive="yes">
          <include name="**/*.po"/>
        </fileset>
      </path>
    </foreach>
</target>

目标 build-languageclasses 依赖于编译目标,因此,每次编译时,都会再次 msgfmted.仅当 1. po 文件已更改,或 2. 类文件不存在时,应如何编写它以调用 msgfmt?如果没有其他软件就可以做到这一点,我会很高兴.你能帮我举个例子吗?

The target build-languageclasses is depended on in the compile target and so, every compile, the whole bunch is msgfmted again. How should this be written to invoke msgfmt only if 1. the po file was changed, or 2. the class file doesn't exist? I would be glad if this would be possible without further software. Can you help or point me to an example?

第一次尝试解决对蚂蚁的行为没有影响:

A first attempt at solution makes no difference in ant's behaviour:

<target id="build-languageclasses" description="compile if Messages??.class files not uptodate" name="build-languageclasses" unless="i18n.uptodate">
  <condition property="i18n.uptodate">
    <uptodate>
      <srcfiles dir="${po}" includes="**/*.po"/>
      <mapper type="glob" from="${po}/*.po" to="${po}/classes/app/i18n/Messages*.class"/>
    </uptodate>
  </condition>
  <echo message="Compiling po files." />
  <foreach target="msgfmt" param="file">
    <path>
      <fileset dir="po" casesensitive="yes">
        <include name="**/*.po"/>
      </fileset>
    </path>
  </foreach>
</target> 

这里出了什么问题?

问题是您在运行 uptodate 任务之前正在测试属性 i18n.uptodate.您的条件块必须在您进入 build-languageclasses 目标之前运行.

The problem is that you are testing the property i18n.uptodate before you run the uptodate task. Your condition block must run before you enter the build-languageclasses target.

你应该像这样重新组织你的代码:

You should reorganize your code like that:

  • 删除主要目标上的unless="i18n.uptodate"
  • build-languageclasses 分成 2 个目标.
  • 第一个专用于条件的初始化,仅包含 块.
  • 第二个包含生成文件的代码()
  • remove the unless="i18n.uptodate" on the main target
  • split the build-languageclasses into 2 target.
  • the first is dedicated to the initialization of your condition and contains the <condition> block only.
  • the second that contains the code to generate you files (<foreach>)

第二个目标配置为根据第一个目标设置的属性 i18n.uptodate 有条件地运行.

The second target is configured to run conditionally depending on the property i18n.uptodate set by the first target.

EDIT - 这是最新任务的工作示例

EDIT - Here is a working example of the uptodate task

<property name="source" value="${basedir}/src"/>
<property name="dist" value="${basedir}/dist"/>

<target name="init">
    <condition property="that.uptodate">
        <uptodate>
            <srcfiles dir="${source}" includes="*.txt"/>
            <mapper type="glob" from="*.txt" to="${dist}/*.bat"/>
        </uptodate>
    </condition>
</target>

<target description="check that" name="dist" unless="that.uptodate" depends="init">
    <echo>we have something to do!</echo>
</target>

高米.