2009-09-24 2 views
4

У меня есть следующая структура проекта:Сформировать Ant сборки файла

root/ 
    comp/ 
     env/ 
      version/ 
        build.xml 
      build.xml 
     build.xml 

Где корень/сост/окр/версия/build.xml является:

<project name="comp-env-version" basedir="."> 
    <import file="../build.xml" optional="true" /> 
    <echo>Comp Env Version tasks</echo> 
    <target name="run"> 
     <echo>Comp Env Version run task</echo> 
    </target> 
</project> 

корень/сост/окр /build.xml является:

<project name="comp-env" basedir="."> 
    <import file="../build.xml" optional="true" /> 
    <echo>Comp Env tasks</echo> 
    <target name="run"> 
     <echo>Comp Env run task</echo> 
    </target> 
</project> 

корня/сост/build.xml является:

<project name="comp" basedir="."> 
    <echo>Comp tasks</echo> 
</project> 

Каждого файл сборка импортирует файл сборки родительской и каждый ребенок наследует и переопределения родительских задачи/свойства.

Мне нужно, чтобы получить сгенерированный XML-код сборки без запуска ничего.

Например, если я бегу «муравей» (или что-то подобное) на корень/сост/окр/версия /, я хотел бы получить следующий вывод:

<project name="comp-env-version" basedir="."> 
    <echo>Comp tasks</echo> 
    <echo>Comp Env tasks</echo> 
    <echo>Comp Env Version tasks</echo> 
    <target name="run"> 
     <echo>Comp Env Version run task</echo> 
    </target> 
</project> 

Есть ли Ant плагин сделать это? С Maven? Каковы мои варианты, если нет?

EDIT: мне нужно что-то вроде "МВН помощи: эффективный-П" для Ant.

+0

Что именно вы пытаетесь выполнить? Состоит ли Comp = Component & Env = Environment? Вы пытаетесь создать сборку различных компонентов по конкретным средам? –

+0

Да, что-то в этом роде. Что у тебя на уме? – inakiabt

+0

Что-то вроде «mvn -Doutput = help: effective-pom», но для Ant. ммммм. Я не помню, чтобы что-то подобное. – rodrigoap

ответ

0

Eclipse понимает файлы Ant. Вы можете видеть, какие задачи видны в вашем внутреннем файле build.xml. Это будет не совсем тот формат, который вы запросили, но он может удовлетворить ваши потребности.

+0

Интересно, но мне нужно сделать этот файл сборки автоматическим, например, из командной строки. – inakiabt

0

Я писал сценарии сборки Ant в течение 7-8 лет, но я действительно не понимаю, чего вы пытаетесь достичь здесь. Возможно, это я, но я боюсь, что даже если вы заработаете свою работу (я уверен, что вы можете), вряд ли кто-нибудь ее поймет/поддержит.

Почему бы не хранить вещи очень просто и иметь родственные проекты?

root 
    build.xml 
    comp 
     build.xml 
    env 
     build.xml 
    version 
     build.xml 

отдельных build.xml файлы могут импортировать задачи определить где-то еще (используйте Macrodef для этого), и вашего верхнего уровня build.xml бы назвать отдельные из них последовательно?

Как только вы получите базовое строение, вы можете поиграть с Айви или Maven для более интересных вещей.

Но если вы действительно хотите сгенерировать файлы сборки, вы можете попробовать Groovy и его шаблонный двигатель.

+0

Спасибо, я ищу, чтобы сгенерировать результат build.xml «версии» (в данном случае). Что-то вроде «mvn help: effective-pom» для Ant. – inakiabt

0

Я бы посоветовал структурировать ваши файлы сборки, чтобы они использовали дерево зависимостей, которое действительно является муравьем. Если вы будете следовать советам @ Vladimir и структурировать свои файлы сборки, подобные этому, тогда вы можете иметь один файл сборки в «root» и рекурсивно выполнить свою сборку.Например:

<!-- iterate finds all build files, excluding this one 
    and invokes the named target 
--> 
<macrodef name="iterate"> 
    <attribute name="target"/> 
    <sequential> 
     <subant target="@{target}"> 
      <fileset dir="." 
        includes="**/build.xml" 
        excludes="build.xml"/> 
     </subant> 
    </sequential> 
</macrodef> 


<target name="build" description="Build all sub projects"> 
    <iterate target="build"/> 
</target> 

<target name="clean" description="Clean all sub projects"> 
    <iterate target="clean"/> 
</target> 
+0

Хороший совет, но это не то, что я ищу. Мне нужно сгенерировать файл сборки XML, наследующий все файлы build.xml от родителей. Я не хочу строить проект, я хочу получить сгенерированный файл сборки для вашего примера. – inakiabt

+0

Взгляните на документацию/пример для задачи субантенса - http://ant.apache.org/manual/CoreTasks/subant.html - если ваши включения в ваш макродекс выглядят как "**/version/build.xml" и вы устанавливаете «просто так», вы должны иметь возможность использовать задачу xslt и common2master.xsl для записи файла основной сборки. – DaveParillo

5

На основе описания import task, она работает очень похоже на предприятие включает в себя две дополнительных функциях:

  • мишень перекрывая
  • специальных свойств

Для целей просмотра «эффективная сборка» Я не думаю, что требуется специальная обработка свойств (хотя она может быть добавлена ​​путем итерации вставленных целей). Таким образом, обработка для достижения этого становится.

  1. Разбирает build.xml к DOM
    • Для каждого верхнего уровня включает в себя тег найден (только верхний уровень разрешен), найти указываемый исходный файл.
    • Разберите ссылочный файл build.xml
    • Вставьте любой контент из ссылочного файла build.xml, который не сталкивается с файлами в текущем файле.
    • Повторите шаг 2 для ссылки build.xml файла (ов), пока больше не найден
    • Выхода результирующей DOM

Вы можете определить пользовательские задачи Ant, так что эта обработка может быть определены задача, которую нужно запустить из вашей сборки. См. Это tutorial для более подробной информации.

Вот базовая реализация, которая рекурсивно импортирует и вставляет элементы DOM из файлов, на которые делается ссылка. Там почти наверняка несколько ошибок в нем, как я бросил его вместе, но он должен делать в основном то, что вы после:

/** 
* Reads the build.xml and outputs the resolved build to stdout 
*/ 
public static void main(String[] args) { 
    try { 
     Element root = new EffectiveBuild().parse(new File(args[0])); 

     XMLOutputter outputter = new XMLOutputter(Format.getPrettyFormat()); 

     outputter.output(root, System.out); 
    } catch (Exception e) { 
     // TODO handle errors 
     e.printStackTrace(); 
    } 

} 

/** 
* Get the DOM for the passed file and iterate all imports, replacing with 
* non-duplicate referenced content 
*/ 
private Element parse(File buildFile) throws JDOMException, IOException { 
    Element root = getRootElement(buildFile); 

    List<Element> imports = root.getChildren("import"); 

    for (int i = 0; i < imports.size(); i++) { 
     Element element = imports.get(i); 

     List<Content> importContent = parseImport(element, root, buildFile); 

     int replaceIndex = root.indexOf(element); 

     root.addContent(replaceIndex, importContent); 

     root.removeContent(element); 
    } 

    root.removeChildren("import"); 

    return root; 
} 

/** 
* Get the imported file and merge it into the parent. 
*/ 
private List<Content> parseImport(Element element, Element currentRoot, 
     File buildFile) throws JDOMException, IOException { 
    String importFileName = element.getAttributeValue("file"); 
    File importFile = new File(buildFile.getParentFile(), importFileName) 
      .getAbsoluteFile(); 
    if (importFileName != null) { 
     Element importRoot = getRootElement(importFile); 

     return getImportContent(element, currentRoot, importRoot, 
       importFile); 
    } 

    return Collections.emptyList(); 
} 

/** 
* Replace the passed element with the content of the importRoot 
* (not the project tag) 
*/ 
private List<Content> getImportContent(Element element, 
     Element currentRoot, Element importRoot, File buildFile) 
     throws JDOMException, IOException { 

    if (currentRoot != null) { 
     // copy all the reference import elements to the parent if needed 
     List<Content> childNodes = importRoot.cloneContent(); 
     List<Content> importContent = new ArrayList<Content>(); 

     for (Content content : childNodes) { 
      if (content instanceof Element 
        && ((Element) content).getName().equals("import")) { 
       importContent.addAll(parseImport((Element) content, 
         currentRoot, buildFile)); 
      } 
      if (!existsInParent(currentRoot, content)) { 
       importContent.add(content); 
      } else { 
       // TODO note the element was skipped 
      } 
     } 

     return importContent; 
    } 

    return Collections.emptyList(); 
} 

/** 
* Return true if the content already defined in the parent 
*/ 
private boolean existsInParent(Element parent, Content content) { 
    if (content instanceof Text) { 
     if (((Text) content).getText().trim().length() == 0) { 
      // let the pretty printer deal with the whitespace 
      return false; 
     } 
     return true; 
    } 
    if (content instanceof Element) { 
     String id = ((Element) content).getAttributeValue("name"); 

     String name = ((Element) content).getName(); 
     List<Content> parentContent = parent.getChildren(); 

     if (id != null) { 
      for (Content content2 : parentContent) { 
       if (content2 instanceof Element 
         && ((Element) content2).getName().equals(name)) { 
        String parentId = ((Element) content2) 
          .getAttributeValue("name"); 

        if (parentId != null && parentId.equals(id)) { 
         return true; 
        } 
       } 
      } 
     } 
    } 
    return false; 
} 

/** 
* Parse the passed file. 
*/ 
private Element getRootElement(File buildFile) throws JDOMException, 
     IOException { 
    SAXBuilder builder = new SAXBuilder(); 
    builder.setValidation(false); 
    builder.setIgnoringElementContentWhitespace(true); 
    Document doc = builder.build(buildFile); 

    Element root = doc.getRootElement(); 
    return root; 
} 
0

Вы могли бы написать сценарий/приложение в Java, Groovy, Ruby или что вы знаете лучше всего ... скрипт будет анализировать xml файлов сборки и заменять «перенаправленные» цели своими переопределениями, фактически заменяя соответствующие узлы DOM. То, что вы получите, это ваш составной build.xml как DOM, который затем может быть сериализован.

Вы можете сохранить сценарий под рукой в ​​своем исходном элементе управления, чтобы вы могли регенерировать по мере необходимости.

Это может показаться немного экстремальным, но похоже, что большинство других решений выходит за рамки того, что вы ищете.

ПРИМЕЧАНИЕ. Вы можете запускать некоторые скриптовые языки из Ant, поэтому вы все равно можете использовать И как ваш инициатор.

Удачи.

+0

На самом деле см. Сообщение Rich Sellers ... Я не видел этого ... он избил меня до этой идеи. – cjstehno

+0

не стесняйтесь повышать меня :) –