Ant manifestclasspath: свойство уже установлено - PullRequest
1 голос
/ 28 июня 2011

Я хочу использовать manifestclasspath Задача Ant. У меня очень большой файл build.xml с парой импортированных других файлов сборки, и когда я его запускаю, я получаю следующее:

build.xml:1289: The following error occurred while executing this line:
build.xml:165: Property 'some.property' already set!

Я уверен, что это свойство определено только в manifestclasspath задании. Вот мой код:

<manifestclasspath property="some.property" jarfile="some.jar">
    <classpath refid="some.classpath"/>
</manifestclasspath>

Этот код находится внутри <project>.

Что я делаю не так? Есть ли способ добавить что-то вроде condition для установки свойства, только если оно еще не установлено? Я не хочу использовать пользовательские задачи Ant, такие как Ant Contrib if, если есть другие способы.

1 Ответ

1 голос
/ 29 июня 2011

Antcall открывает новую область проекта, но по умолчанию все свойства текущего проекта будут доступны в новом проекте. Также, если вы использовали что-то вроде =

<antcall target="whatever">
  <param name="some.property" value="somevalue"/>
</antcall>

в вызывающем проекте, тогда $ {some.property} также уже установлен и не будет перезаписываться, так как установленные свойства неизменяемы в ant по своему замыслу. Кроме того, вы можете установить для атрибута attributeitAll значение false, и в новый проект будут переданы только «пользовательские» свойства (переданные в командной строке с параметром -Dproperty = value). Таким образом, когда $ {some.property} не является пользовательским свойством, тогда используйте inheritAll = "false", и все готово.

кстати. Лучше использовать зависимость между целями с помощью атрибутов depen = "...", чем использовать antcall, потому что он открывает новую область проекта, и свойства, установленные в новом проекте, не возвращаются к вызывающей цели, потому что она живет в другом Масштаб проекта ..

После фрагмента, обратите внимание на разницу, сначала без атрибута inheritAll

<project default="foo">
 <target name="foo">
  <property name="name" value="value1" />
  <antcall target="bar"/>
 </target>

 <target name="bar">
  <property name="name" value="value2" />
  <echo>$${name} = ${name}</echo>
 </target>
</project>

вывод:

[echo] ${name} = value1

секунда с наследование всех = ложь

 <project default="foo">
     <target name="foo">
      <property name="name" value="value1" />
      <antcall target="bar" inheritAll="false" />
     </target>

     <target name="bar">
      <property name="name" value="value2" />
      <echo>$${name} = ${name}</echo>
     </target>
    </project>

вывод:

[echo] ${name} = value2

некоторые правила для antcall, он редко используется по уважительным причинам:
1. он открывает новую область проекта (запускает новый 'ant -buildfile yourfile.xml yourtarget')
, поэтому использует больше памяти, замедляя сборку
2. Будут вызваны и зависимые цели вызываемой цели!
3. свойства не передаются обратно вызывающей цели

В некоторых случаях это может быть нормально при вызове одной и той же «автономной» цели (цели, от которой она не зависит) с разными параметрами для повторного использования. Обычно для этого используются macrodef или scriptdef. Итак, подумайте дважды, прежде чем использовать antcall, который также добавляет излишнюю сложность вашим сценариям, потому что он работает против нормального потока.

Ответьте на свой вопрос в комментарии, используя график зависимостей вместо antcall
у вас есть цель, которая содержит все условия и устанавливает соответствующие свойства, которые могут оцениваться по целям с помощью атрибутов if и else для управления дальнейшим потоком

<project default="main">

 <target name="some.target">
  <echo>starting..</echo>
 </target>

 <!-- checking requirements.. -->
 <target name="this.target">
  <condition property="windowsbuild">
   <os family="windows"/>
  </condition>
  <condition property="windowsbuild">
   <os family="unix"/>
  </condition>
  <!-- ... -->
 </target>

 <!-- alternatively
  <target name="yet.another.target" depends="this.target" if="unixbuild">
 -->
 <target name="another.target" depends="this.target" unless="windowsbuild">
  <!-- your unixspecific stuff goes here .. -->
 </target>

 <!-- alternatively
  <target name="yet.another.target" depends="this.target" if="windowsbuild">
 -->
 <target name="yet.another.target" depends="this.target" unless="unixbuild">
  <!-- your windowspecific stuff goes here .. -->
 </target>

...