简体   繁体   English

如何继承多模块Maven项目及其所有好处?

[英]How to inherit from a multimodule Maven project with all its goodies?

The problem to which I cannot find a nice, scalable solution: 我无法找到一个好的,可扩展的解决方案的问题:

I have a project that delivers multiple flavours of the given artifact. 我有一个项目,可以提供给定工件的多种风格。 This has been set up as a multimodule project, currently with 3 modules: 这已被设置为多模块项目,目前有3个模块:

  • /flavour1_module / flavour1_module
  • /flavour2_module / flavour2_module
  • /flavour3_module / flavour3_module

The thing is that I have another 50 projects that need to be setup in the same way, ie delivering the 3 flavours. 问题是我还有另外50个需要以相同方式设置的项目,即提供3种口味。

Solutions considered: 解决方案:

  1. turning the already created multimodule project into a parent for all other 50 projects 将已创建的多模块项目转换为所有其他50个项目的父项目
    • 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 使用maven-archetype-plugin创建一个多模块项目模板 ,然后根据模板创建所有50个项目
    • Cons: if I would need flavour4, I need to manually update all 50 projects to add flavour4_module (and duplicate its content). 缺点:如果我需要flavour4,我需要手动更新所有50个项目以添加flavour4_module(并复制其内容)。 Not scalable. 不可扩展。
  3. embedding the configuration of all flavours into a single pom and enable or disable them based on profiles (ie using composition by profiles instead of inheritance via modules). 将所有flavor的配置嵌入到单个pom中,并根据配置文件启用或禁用它们(即使用配置文件组合而不是通过模块继承)。 Then pointing the 50 projects to it, as their parent. 然后将50个项目指向它,作为它们的父项。 This would create "inline" modules 这将创建“内联”模块
    • Cons: I would need to implement on my own mechanisms which are provided by modules out of the box. 缺点:我需要在我自己的机制上实现,这些机制由开箱即用的模块提供。 (eg building every flavour in a separate directory). (例如,在单独的目录中构建每个风味)。 I would also lose the clear seperation that modules provide. 我也会失去模块提供的明确分离。

Any ideas how to do it nicely? 任何想法如何做得很好? Is there any other option? 还有其他选择吗?

Thanks, Lukasz 谢谢,卢卡斯

Edit: 编辑:

Another option would be extending the maven-reactor-plugin with reactor:inject-modules goal, which would download module definition from an external artifact, and attach its definition as a normal module. 另一个选择是使用reactor扩展maven-reactor-plugin :inject-modules目标,它将从外部工件下载模块定义,并将其定义附加为普通模块。 This would create a new module on the fly. 这将动态创建一个新模块。 Then all 50 projects could make this pom.xml their parent. 然后所有50个项目都可以使这个pom.xml成为他们的父项。

The configuration would look like this (a draft): 配置看起来像这样(草稿):

<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>

Would going this way make sense? 这样做会有意义吗?

Update: 更新:

Writing a plugin that manipulates the list of modules to execute (the idea of module injection that I described above) doesn't seem to be possible to implement, because modules are processed by maven core, and the mechanism was not designed to be extended with a plugin. 编写一个操作要执行的模块列表的插件(我上面描述的模块注入的概念)似乎不可能实现,因为模块由maven核心处理,并且该机制不是为扩展而设计的一个插件。 This is confirmed by the fact that both plugins that do a similar job ie manipulating the list of projects to execute: 事实证明,两个插件都执行类似的工作,即操作要执行的项目列表:

do the trick by executing a system call to create maven child process. 通过执行系统调用来创建maven子进程。 For me it is not the way to go, because it's a very unstable solution. 对我而言,这不是一条路,因为这是一个非常不稳定的解决方案。 Indeed maven-reactor-plugin became incompatible with Maven3. 事实上, maven-reactor-plugin与Maven3 不兼容

maven-invoker-plugin still looks promising. maven-invoker-plugin仍然看起来很有前途。 The plugin was originally designed to run integration tests, but it would be possible to use it to extend eg the compilation phase. 该插件最初设计用于运行集成测试,但可以使用它来扩展例如编译阶段。 But it requires the child pom.xml-s to be treated as resources and modified on the fly. 但它需要将子pom.xml-s视为资源并在运行中进行修改。 For the problem that I described here the solution would be too complicated and unstable. 对于我在这里描述的问题,解决方案太复杂和不稳定。 I would prefer something lighter that could operate in memory while building maven model. 在构建maven模型时,我更喜欢可以在内存中运行的更轻的东西。

So for now I use profiles, trying to make them as compact as possible. 所以现在我使用配置文件,试图使它们尽可能紧凑。 Probably in a while I will need again to think about the problem. 可能有一段时间我需要再次思考这个问题。

Now you can use the maven-tiles plugin to get the desired behaviour. 现在,您可以使用maven-tiles插件来获得所需的行为。

With maven-tiles you can define build behaviours in different poms and import them wherever you like. 使用maven-tiles,您可以在不同的poms中定义构建行为,并将它们导入到您喜欢的任何位置。

There's a working sample attached to MNG-5102 --> daddy3.zip 有一个工作样本附加到MNG-5102 - > daddy3.zip

Maven's inheritance-only strait jacket is now officially removed. Maven的继承唯一的紧身夹克现已正式删除。

In my opinion, you could create multiple different assembly descriptors for this and configure multiple plugin executions with each execution referring to different descriptor. 在我看来,你可以为此创建多个不同的程序集描述符,并配置多个插件执行,每次执行都引用不同的描述符。 You will have to maintain your project as a single module instead of multi module project. 您必须将项目维护为单个模块而不是多模块项目。 Provided your distributions contain same set of classes but different resources or libraries, it could work. 如果您的发行版包含相同的类集但不同的资源或库,它可以工作。

        <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>

You could create a parent pom with assembly pluing configured there so that you can control the number of distributions and the change in packaging from there. 您可以使用在那里配置的程序集来创建父pom,以便您可以从那里控制分发数量和包装更改。 Your projects will not need to know about details of different packaging. 您的项目无需了解不同包装的详细信息。

I will strongly recommend to keep native libraries as separate module and use repository mechanism to install the compiled libraries into it. 我强烈建议将本机库保留为单独的模块,并使用存储库机制将已编译的库安装到其中。 You can use different classifiers to segregate the platforms like, 您可以使用不同的分类器来隔离平台,例如

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

You can then reference to these libraries as dependencies in your project and then be able to package them along with your distribution. 然后,您可以在项目中引用这些库作为依赖项,然后将它们与您的发行版一起打包。

The overall solution will greatly depend on how various distributions will differ and the overall process of packaging the distribution but I think this will work. 总体解决方案将在很大程度上取决于各种分布的不同以及包装分发的整个过程,但我认为这将有效。

The ultimate and more scalable solution is to create your own packaging by implementing a Maven Plugin. 最终和更具可扩展性的解决方案是通过实施Maven插件来创建自己的包装。

In my experience option 3 has worked the best, but I haven't had to scale it like you need to- when I've had to do that I've used the maven-ant-plugin to create a parameterized ant script to do the customization. 根据我的经验, 选项3工作得最好,但我没有必要像你需要那样扩展它 - 当我必须这样做时我已经使用maven-ant-plugin来创建一个参数化的ant脚本来做定制。 It has some downsides- namely working with both ant and maven so the actual POM is more difficult to comprehend but it does allow for more flexibility than is otherwise possible with maven. 它有一些缺点 - 即同时使用ant和maven,因此实际的POM更难以理解,但它确实允许比maven更多的灵活性。

If you are using maven 3, you can define profiles the parent pom and activate them base on file existance. 如果您使用的是maven 3,则可以定义父pom的配置文件,并根据文件存在情况激活它们。 On the child modules you can "inherit flavours" by simply creating empty files. 在子模块上,只需创建空文件即可“继承风味”。

This is better documented on the links below: 这在以下链接中有更好的记录:

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM