ANT: Как прочитать свойство, установленное в цикле foreach - PullRequest
6 голосов
/ 16 марта 2011

Уважаемый, в настоящее время я сталкиваюсь с некоторой проблемой при получении значения свойства, установленного в цикле foreach. Может быть, один из вас мог бы помочь мне ...

Цель состоит в том, чтобы проверить, был ли изменен один файл папки с момента создания соответствующего jar-файла. Таким образом, я знаю, придется ли мне снова создавать банку. Что я делаю, так это просматриваю папку с циклом foreach и, если один файл соответствует моему тесту, присваиваем свойству значение true.

Проблема в том, что моя переменная, кажется, не существует после моего цикла ... Вот пример упрощенного кода, который имеет ту же проблему:

<target name="target">
    <taskdef resource="net/sf/antcontrib/antlib.xml" classpath="${lib.dir}/ant-contrib.jar"></taskdef>
    <foreach target="setVar" param="var" list="a,b"/>
    <echo>myreturn in target: ${env.myreturn}</echo>
    <property name="env.myreturn" value="c"/>
    <echo>myreturn in second: ${env.myreturn}</echo>
</target>
<target name="setVar">
    <property name="env.myreturn" value="${var}"/>
    <echo>myreturn in setVar: ${env.myreturn}</echo>
</target>

Результат этого кода:

target:
setVar:
 [echo] myreturn in setVar: a
setVar:
 [echo] myreturn in setVar: b
 [echo] myreturn in target: ${env.myreturn}
 [echo] myreturn in second: c
BUILD SUCCESSFUL

Кажется, переменная установлена ​​правильно, так как она может быть напечатана в цели "setVar", но нет способа извлечь значение из вызывающей цели.

Я также знаю, что невозможно присвоить значение свойству дважды. Но проблема даже не возникает ... Когда это произойдет, я мог бы добавить проверку значения свойства, прежде чем присвоить его, чтобы убедиться, что оно еще не инициализировано ...

У вас есть подсказка, как я могу решить мою проблему?

Заранее большое спасибо за помощь:)

Ответы [ 5 ]

7 голосов
/ 17 марта 2011

Попробуйте <for> задание из ant-contrib вместо <foreach>.Задача <for> использует возможности макросов Ant, появившиеся позже.Он работает быстрее и более гибок, чем старая задача <foreach>.Вы находитесь в том же контексте проекта при использовании <for>.Это означает, что свойства, установленные в цикле, будут видны вне цикла.Конечно, применяются обычные правила для свойств ... вы можете установить его только один раз ... если вы не используете задачу <var> из ant-contrib для перезаписи или отмены ранее установленных свойств.

Ах, радостиВзлом муравья.

3 голосов
/ 22 марта 2011

Даже если мне это больше не нужно, благодаря sudocode, я нашел решение для своего вопроса. Может быть, это может быть полезно для кого-то еще ...

Коллега рассказала о цели antcallback для ant-contrib: она позволяет вернуть результат от вызываемой цели к вызывающей. С помощью комбинации «for» target и «antcallback» можно сделать то, что я хотел сделать:

<target name="target">
    <taskdef resource="net/sf/antcontrib/antlib.xml" classpath="${lib.dir}/ant-contrib.jar"></taskdef>
    <for param="file">
        <path>
            <fileset dir="../myDirectory" includes="**/*" />
        </path>
        <sequential>
            <antcallback target="setVar" return="retValue">
                <param name="file" value="@{file}"/>
            </antcallback>
        </sequential>
    </for>
    <echo>result: ${retValue}</echo>
</target>
<target name="setVar">
    <property name="retValue" value="${file}"/>
</target>

«файл» содержит имя файла в каталоге. Он передается вызываемой цели как параметр со значением «@ {file}» («@» необходимо из-за реализации «for»).

В конце основной цели $ {retValue} содержит первое значение, установленное целью «setVar». При попытке установить его несколько раз не выдается никакой ошибки, поэтому нет необходимости проверять, была ли создана переменная, прежде чем устанавливать ее в цели setVar.

3 голосов
/ 16 марта 2011

Не уверен насчет вашей проблемы foreach, но вы не можете использовать задачу uptodate для ваших требований?

1 голос
/ 16 марта 2011

Задача <foreach> использует ту же логику, что и <antcall> под обложками, и любые свойства, установленные внутри цели, вызванной <antcall>, не имеют области действия за пределами выполнения этой цели.

Вдругими словами, свойство env.myreturn, которое вы определяете в цели setVar, теряется, как только выполнение этой цели завершается.

Этот тип сценариев действительно не предназначен для Ant.Библиотека Ant-contrib пытается исправить дыры, но она все еще изгибается.

Если вам нужно написать такие скрипты и вы хотите использовать задачи Ant для их достижения, взгляните на Gradle вместо.Это довольно приятное сочетание Groovy (для сценариев) и Ant (для задач).

0 голосов
/ 10 ноября 2017

Другие подходы здесь (<for>, <var>, <groovy>properties.put(....)</groovy>, <property>, <antcallback>) не работают с ANT 1.9.4, поэтому я использовал файловую систему, подобную этой (псевдокод):

<target name="outer">
  <for>  <antcall target="inner" />  </for>
  <loadproperties srcfile="tmpfile.properties" />
  <echo message="${outerprop}" />
</target>

  <target name="inner">
    <!-- did not work: -->
    <!--
      <property name="outerprop" value="true" /> 
      <var name="outerprop" value="true" /> 
      <groovy>properties.put('outerprop','true')</groovy>
      <antcallback target="setouterprop" />
    -->
    <echo message="outerprop=true" file="tmpfile.properties" />
  </target>

Возможно, другие подходы не сработали из-за моего <antcall>, но мне это нужно здесь. (outerprop изначально не установлен)

...