Как наследоваться от многомодульного проекта Maven со всеми его вкусностями?

Проблема, для которой я не могу найти красивое, масштабируемое решение:

У меня есть проект, который предоставляет несколько вариантов данного артефакта. Это было создано как многомодульный проект, в настоящее время с 3 модулями:

  • /flavor1_module
  • /flavor2_module
  • /flavor3_module

Дело в том, что у меня есть еще 50 проектов, которые нужно настроить таким же образом, т.е. предоставить 3 варианта.

Рассматриваемые решения:

  1. turning the already created multimodule project into a parent for all other 50 projects
    • Cons: It just doesn't work. The instructions kept withing parent's modules are not inherited, thus they are not executed.
  2. using maven-archetype-plugin to create a multi-module project template, and then creating all 50 projects based on the template
    • Cons: if I would need flavour4, I need to manually update all 50 projects to add flavour4_module (and duplicate its content). Not scalable.
  3. embedding the configuration of all flavours into a single pom and enable or disable them based on profiles (i.e. using composition by profiles instead of inheritance via modules). Then pointing the 50 projects to it, as their parent. This would create "inline" modules
    • Cons: I would need to implement on my own mechanisms which are provided by modules out of the box. (e.g. building every flavour in a separate directory). I would also lose the clear seperation that modules provide.

Любые идеи, как сделать это красиво? Есть ли другой вариант?

Спасибо, Лукаш

Изменить:

Другим вариантом может быть расширение maven-reactor-plugin с помощью < em>reactor:inject-modules, которая загрузит определение модуля из внешнего артефакта и прикрепит его определение как обычный модуль. Это создаст новый модуль на лету. Тогда все 50 проектов могут сделать этот pom.xml своим родителем.

Конфигурация будет выглядеть так (черновик):

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-reactor-plugin</artifactId>
  <version>1.0</version>
  <executions>
    <execution>
      <id>inject</id>
      <phase>initialize</phase>
      <goals>
        <goal>inject-modules</goal>
      </goals>
      <configuration>
        <modules>
          <module>
            <artifactId>flavour1_module</artifactId>
            <groupId>[ groupId ]</groupId>
            <version>[ version ]</version>
          </module>
          <module>
            <artifactId>flavour2_module</artifactId>
            <groupId>[ groupId ]</groupId>
            <version>[ version ]</version>
          </module>
          <module>
            <artifactId>flavour3_module</artifactId>
            <groupId>[ groupId ]</groupId>
            <version>[ version ]</version>
          </module>
        </modules>
      </configuration>
    </execution>
  </executions>
</plugin>

Имеет ли смысл идти по этому пути?

Обновление:

Написание плагина, который манипулирует списком модулей для выполнения (идея внедрения модуля, которую я описал выше), кажется невозможно реализовать, потому что модули обрабатываются ядром maven, а механизм не предназначен для расширения с помощью плагин. Это подтверждается тем фактом, что оба плагина выполняют одинаковую работу, то есть манипулируют списком выполняемых проектов:

сделайте свое дело, выполнив системный вызов для создания дочернего процесса maven. Для меня это не выход, потому что это очень нестабильное решение. Действительно, maven-reactor-plugin стал несовместим с Maven3.

maven-invoker-plugin по-прежнему выглядит многообещающе. Плагин изначально был разработан для запуска интеграционных тестов, но его можно было бы использовать для расширения, например. этап компиляции. Но для этого требуется, чтобы дочерние pom.xml-s рассматривались как ресурсы и изменялись на лету. Для проблемы, которую я здесь описал, решение было бы слишком сложным и нестабильным. Я бы предпочел что-то более легкое, что могло бы работать в памяти при построении модели maven.

Поэтому пока использую профили, стараясь сделать их максимально компактными. Вероятно, через какое-то время мне нужно будет снова подумать над проблемой.


person Lukasz Guminski    schedule 20.04.2012    source источник
comment
Означает ли это, что различные варианты артефактов различаются файлами конфигурации или они отличаются более важными частями?   -  person khmarbaise    schedule 21.04.2012
comment
На данный момент они отличаются конфигурационными файлами и форматом упаковки. В скором времени ожидается больше отличий.   -  person Lukasz Guminski    schedule 21.04.2012
comment
Хм. Упаковка? Вы имеете в виду, что несколько классов упакованы как jar, а затем упакованы в .tar.gz или что вы подразумеваете под форматом упаковки? Или просто структура пакета имеется в виду?   -  person khmarbaise    schedule 21.04.2012
comment
Каждая разновидность предназначена для разных клиентов, которые получают приложения с различным подмножеством ресурсов, упакованных внутри. Внутри также есть нативные части, скомпилированные для разных архитектур в зависимости от заказчика.   -  person Lukasz Guminski    schedule 21.04.2012
comment
@LukaszGuminski Достаточно забавно, но я не вижу цели внедрения модулей в плагин maven-reactor-plugin в версии 1.0, которая кажется последней. Кроме того, даже если это сработает, вам все равно придется вручную создавать эти модули?   -  person Kalpak Gadre    schedule 22.04.2012
comment
@Kal Такой функции нет. Вот почему я написал о расширении плагина maven-reactor-plugin с помощью реактора:inject-modules. Модули нужно будет создать один раз, затем они будут импортированы в родительский pom, как показано выше, а затем выполнены при сборке каждого из 50 проектов. Таким образом можно было бы избежать избыточности.   -  person Lukasz Guminski    schedule 23.04.2012
comment
Забавно, что я задал этот самый вопрос сегодня. Я думаю, что, возможно, я приблизился к лучшему решению, чем 1, 2 и 3 --> см. stackoverflow.com/questions/11749375/.   -  person Tony Lâmpada    schedule 01.08.2012
comment
И, пожалуйста, проголосуйте за MNG-5127 (или даже Поддержите его)   -  person Tony Lâmpada    schedule 01.08.2012


Ответы (4)


Теперь вы можете использовать плагин maven-tiles, чтобы получить желаемое поведение.

С помощью maven-tiles вы можете определять поведение сборки в разных pom и импортировать их куда угодно.

Рабочий пример прикреплен к MNG-5102 -- > daddy3.zip

Смирительная рубашка Maven, предназначенная только для наследования, теперь официально снята.

person Tony Lâmpada    schedule 02.10.2012
comment
Если mvn help:effective-pom работает с тайлами, то это было бы идеальным решением. Композиция решает эту проблему намного лучше, чем наследование. - person Lukasz Guminski; 30.10.2012

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

        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-assembly-plugin</artifactId>
            <version>2.2.1</version>
            <executions>
                <execution>
                    <goals>
                        <goal>single</goal>
                    </goals>
                    <id>assembly</id>
                    <phase>package</phase>
                    <configuration>
                        <descriptors>
                                <descriptor>one.xml</descriptor>
                        </descriptors>
                    </configuration>
                </execution>
                <execution>
                    <goals>
                        <goal>single</goal>
                    </goals>
                    <id>assembly</id>
                    <phase>package</phase>
                    <configuration>
                        <descriptors>
                                <descriptor>two.xml</descriptor>
                        </descriptors>
                    </configuration>
                </execution>
                <execution>
                    <goals>
                        <goal>single</goal>
                    </goals>
                    <id>assembly</id>
                    <phase>package</phase>
                    <configuration>
                        <descriptors>
                                                      <descriptor>three.xml</descriptor>
                        </descriptors>
                    </configuration>
                </execution>
            </executions>
        </plugin>

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

Я настоятельно рекомендую хранить нативные библиотеки в виде отдельного модуля и использовать механизм репозитория для установки в него скомпилированных библиотек. Вы можете использовать разные классификаторы для разделения платформ, например,

mylib-2.0.0-win32_x86.dll
mylib-2.0.0-linux_x86.so
mylib-2.0.0-linux_x86_64.so

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

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

Окончательное и более масштабируемое решение — создать собственную упаковку с помощью подключаемого модуля Maven.

person Kalpak Gadre    schedule 21.04.2012
comment
Такие решения работают, поскольку длительные различия между вкусами относительно невелики (например, ограничиваются упаковкой). Но в моем случае ответственность за предоставление каждого аромата лежит на другой команде, поэтому я не могу предположить, что изменения будут небольшими. - person Lukasz Guminski; 22.04.2012
comment
Организационное ограничение также означает для меня, что я не могу позволить встроить конфигурацию всех вкусов в один pom, не предоставив рудиментарной структуры, чтобы команды не мешали друг другу. Так что профили Maven как простой механизм группировки конфигураций — это минимум, который мне нужно предоставить. Но все же я бы предпочел модули. - person Lukasz Guminski; 22.04.2012
comment
Что касается нативных компонентов, то они уже управляются как отдельные проекты Maven. Но проблема, которую я описал в своем вопросе, затрагивает и их. Как описать, как компилировать для новой архитектуры без необходимости отдельного изменения каждого нативного проекта Maven? - person Lukasz Guminski; 22.04.2012
comment
Подводя итог, я до сих пор не вижу хорошего решения проблемы управления несколькими вариантами в больших проектах. - person Lukasz Guminski; 22.04.2012
comment
Кстати, в моем случае ресурсы также поддерживаются как отдельные проекты Maven. Таким образом, каждый вариант имеет свои собственные зависимости от необходимых ему ресурсов. Это уже указывает на то, что зависимости для всех разновидностей не должны храниться в одном pom, а должны быть разделены на модули, где каждый модуль управляет своими собственными зависимостями. - person Lukasz Guminski; 22.04.2012
comment
@Lukasz Giminski Как вы создаете нативные проекты? В прошлом у меня были нативные проекты, созданные с использованием файла make, где файл make вызывался через плагин Maven antrun. У Maven также есть плагин Native, но он мало им пользовался. В обоих случаях вам просто нужно делегировать сборку на нужную платформу? Я сделал это, используя агенты сборки в Jenkins, где каждый агент сборки представлял целевую платформу, такую ​​как Linux, Solaris, Windows и т. д. - person Kalpak Gadre; 22.04.2012
comment
Кроме того, если у вас есть файлы make, специфичные для платформы, вы можете справиться с этим, используя профили (активация по архитектуре). - person Kalpak Gadre; 22.04.2012
comment
Kal, Как собирать нативные компоненты напрямую к этому вопросу не относится. Но к вашему сведению, я использую antrun, который запускает сборку для разных архитектур с помощью кросс-компиляторов. Однако, поскольку для каждой архитектуры существует отдельный процесс сборки, мне пришлось самостоятельно решать, как собрать все разновидности процесса выпуска один за другим в отдельные каталоги. Это та особенность, которую модули дают из коробки, а с профилями гораздо сложнее. - person Lukasz Guminski; 23.04.2012

По моему опыту, вариант 3 работал лучше всего, но мне не приходилось масштабировать его так, как вам нужно — когда мне приходилось это делать, я использовал maven-ant-plugin для создайте параметризованный скрипт ant для выполнения настройки. У него есть некоторые недостатки, а именно работа с ant и maven, поэтому фактический POM труднее понять, но он обеспечивает большую гибкость, чем это возможно с maven.

person Steven Fines    schedule 07.07.2012
comment
Действительно, получилось довольно сложно :) И это еще не конец :/ Спасибо! - person Lukasz Guminski; 31.07.2012

Если вы используете maven 3, вы можете определить профили родительского pom и активировать их на основе существования файла. В дочерних модулях вы можете «наследовать вкусы», просто создавая пустые файлы.

Это лучше документировано по ссылкам ниже:

person Tony Lâmpada    schedule 01.08.2012