ANT. Переопределить свойства. Необязательное выполнение в одиночной цели

Я собираюсь опубликовать вопрос о том, что я видел варианты в другом месте, но где я не совсем видел ответ, который я придумал. Впоследствии я напишу свой ответ.

Для модуляции моей сборки script с использованием макросов я хотел бы добавить как updatetask, так и задачу, которую я хочу выполнить, если она не обновлена, в том же макросе.
Как это сделать? Использование тега script в порядке - если единственный уникальный атрибут, который передается, - это путь, содержащий обратную косую черту, и мне нужно иметь возможность передавать разные значения тегу script при разных вызовах. Мне нужно избегать любых проблем, которые могут возникнуть со строковыми литералами, когда задействована обратная косая черта. Используя уникальный атрибут, мне нужно обойти поведение свойства ant неизменяемого свойства и работать с шаблоном ant, который обычно использует 2 цели для обработки решений обработки uptodate и должен работать с обработкой обратных косых черт в строковых литералах javascript.

1
задан Canova 05 марта '10 в 20:21
источник поделиться

1 ответ

Примечание. Я работаю с ant 1.7. При локальном охвате в ant 1.8 есть дополнительные опции, так что неизменность не является такой большой проблемой, но некоторые из этих других советов будут по-прежнему полезны.

Во-первых, относительно вопроса о необязательном выполнении задачи на основе результатов uptodate в макросе - что означает, что вам не нужны 2 цели. Для этого используйте тег условия. < или > тег заставит его выполнять только второе условие, если первое условие не выполняется. Условие <scriptcondition> tag позволяет использовать javascript для выполнения других ant задач. Здесь пример (@tags указывает атрибуты макродефа):

<condition property="whatever" value="false">
  <or>
    <uptodate>
      <srcfiles dir="@{srcdir}" includes="@{srcincludes}" excludes="@{srcexcludes}"/>
      <mapper><chainedmapper>
        <flattenmapper/><!-- use any mappers you need to match source to target files-->
        <globmapper from="*.jxw" to="@{targetdir}\*W.java"/>
      </chainedmapper></mapper>
    </uptodate>
    <!-- w/ java 1.6 or later, you get a rhino javascript interpreter included w/ java-->
    <scriptcondition language="javascript" value="true">
      self.setValue(true);
      echo = project.createTask("echo");
      myArg1="@{myArg1}";
      myArg2="@{myArg2}";
      // need to create a reference from a classpath refid
      myReference = new org.apache.tools.ant.types.Reference(project,"@{my.classpath.id.string}");
      // get a handle to the ant java task, which we will use to execute a java program
      javaTask = project.createTask("java");
      javaTask.setFork(true);
      javaTask.setFailonerror(true);
      javaTask.setClassname("com.mycompany.mypackage.MySpecialClass");
      javaTask.setClasspathRef(myReference);
      javaTask.createArg().setValue(myArg1);
      javaTask.createArg().setValue(myArg2);

      //output the command line to standard out, for reference
      echo.setMessage(javaTask.getCommandLine());
      echo.perform();
      javaTask.perform();
    </scriptcondition>
  </or>
</condition>

Теперь, если вы похожи на меня, вы можете захотеть выполнить некоторую обработку с атрибутами, которые являются вашими вкладками macrodef, и произвести некоторые производные значения, на которые можно ссылаться в вашем макроопределении script. Если вы обрабатываете просто включает в себя сцепление атрибутов и строк, вы можете сделать это в блоке, если бы вы указали, что ваши атрибуты должны указывать второй набор атрибутов с настройкой по умолчанию, которая содержит шаги конкатенации. Однако, если вам нужно сделать что-то, что вы не можете подключить к атрибуту default, вам нужно будет поместить его в свойство. Поскольку свойства неизменяемы, вам нужно предпринять дополнительные шаги, чтобы дать вашим свойствам уникальные имена. Для этого вам поможет tstamp. Как правило, некоторая комбинация параметров, передаваемых вашему макросу, будет уникальной, но если эта уникальная комбинация включает обратную косую черту, вы захотите получить дополнительный уникальный идентификатор, используя тег tstamp, чтобы вы не сталкивались с проблемами обратной косой черты в вашем javascript, когда вы хотите использовать эти производные свойства. Здесь, как создать свои уникальные свойства, с которыми вы легко можете ссылаться в script.

<macrodef name="public.macro.example">
  <attribute name="srcpath"/>
    <sequential>
      <tstamp prefix="@{srcpath}"><format pattern="ddhhmmssSSS" property="time"/></tstamp>
      <private.macro.example srcpath="@{srcpath}" propertyPrefix="prop${@{srcpath}.time}"/>
    </sequential>
</macrodef>

<macrodef name="private.macro.example">
  <attribute name="srcpath"/>
  <attribute name="prefix"/>
  <sequential>
    <pathconvert property="@{prefix}.src"/>
    <!-- now you can do special things with ${@{prefix}.src}, even in javascript -->
    <script language="javascript">
      self.setValue(true);
      echo = project.createTask("echo");
      myPrefix="@{prefix}";
      mySpecialPropertyKey=myPrefix+".src";
      //if your special property contains backslashes or other special js characters
      // you need to use project.getProperty instead of a string literal to get the value
      mySpecialPropertyVal=project.getProperty(mySpecialPropertyKey);
      // do something with this derived value in javascript
      echo.setMessage("my special property = "+mySpecialPropertyVal);
      echo.perform();
    </script>
  </sequential>
</macrodef>

Прежде чем приступить к решению выше, я придумал взломанный стиль решения для переопределения свойства ant с новым значением. Хотя вы можете найти это полезным для переопределения свойства, потому что я делаю прямой вызов класса ant, существует риск того, что это может не совпадать с будущими версиями ant. Поскольку это похоже на хак, моя цель состоит в том, чтобы использовать вышеприведенный подход 2 макродефа, а не такой подход, когда это возможно. Обратите внимание, что этот конкретный вариант не поддерживает символы обратной косой черты, потому что атрибуты напрямую ссылаются на строковый литерал javascript. Сначала я использовал этот простой вариант для создания моего уникального префикса, что помешало необходимости использования метода macrodef для работы над неизменностью свойств. Однако вы можете адаптировать этот макродеф для использования второго макродефа и уникального префикса, чтобы получить "@{value}" в javascript, используя команду project.getProperty.

<macrodef name="public.canova.setproperty">
  <attribute name="name"/>
  <attribute name="value"/>
  <sequential>
    <script language="javascript">
      project.setUserProperty("@{name}","@{value}");
    </script>
  <sequential>
</macrodef>

Вначале краснеть, некоторые из них могут показаться немного сложными, но если вы сделаете свой макродеф правильно и построите макросы стиля компонента (т.е. не добавляйте код спагетти в свой макрос), ваши сценарии ant должны фактически стать короче, легче понять и легче поддерживать, и журналы будут легче следовать. Совет. Используйте только javascript, когда это необходимо, и когда вы его используете, предпочтительнее использовать его внутри макроса, чтобы он был инкапсулирован и скрыт от основной "логики" вашего ant script, тем самым помогая себе документируя и читаемый характер вашей основной "логики". Используйте комментарии, когда вещи не очевидны.

2
ответ дан Canova 05 марта '10 в 21:47
источник поделиться

Другие вопросы по меткам