【问题标题】:How to inherit from a multimodule Maven project with all its goodies?如何从具有所有优点的多模块 Maven 项目继承?
【发布时间】:2012-05-02 00:04:35
【问题描述】:

我找不到好的、可扩展的解决方案的问题:

我有一个项目可以提供给定工件的多种风格。这是一个多模块项目,目前有 3 个模块:

  • /flavor1_module
  • /flavor2_module
  • /flavor3_module

问题是我还有另外 50 个项目需要以相同的方式设置,即提供 3 种风格。

考虑的解决方案:

  1. 将已创建的多模块项目变成所有其他 50 个项目的父项目
    • 缺点:它只是不起作用。保存在父模块中的指令不会被继承,因此它们不会被执行。
  2. 使用maven-archetype-plugin创建a multi-module project template,然后根据模板创建全部50个项目
    • 缺点:如果我需要 flavor4,我需要手动更新所有 50 个项目以添加 flavor4_module(并复制其内容)。不可扩展。
  3. 将所有风味的配置嵌入到单个 pom 中,并根据配置文件启用或禁用它们(即使用配置文件组合而不是通过模块继承)。然后将 50 个项目指向它,作为它们的父级。这将创建“内联”模块
    • 缺点:我需要实现我自己的机制,这些机制由开箱即用的模块提供。 (例如,在单独的目录中构建每种风味)。我也会失去模块提供的清晰分隔。

任何想法如何做得很好?还有其他选择吗?

谢谢, 卢卡斯

编辑:

另一种选择是使用 reactor:inject-modules 目标扩展maven-reactor-plugin,这将从外部工件下载模块定义,并将其定义附加为普通模块。这将动态创建一个新模块。那么所有 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 中变成了incompatible

maven-invoker-plugin 看起来仍然很有希望。该插件最初旨在运行集成测试,但可以使用它来扩展例如编译阶段。 但它要求将子 pom.xml-s 视为资源并即时修改。对于我在此处描述的问题,解决方案将过于复杂且不稳定。我更喜欢在构建 maven 模型时可以在内存中运行的更轻量级的东西。

所以现在我使用配置文件,试图使它们尽可能紧凑。可能过一段时间我需要重新考虑一下这个问题。

【问题讨论】:

  • 这是否意味着不同风格的工件在配置文件中有所不同,还是在更重要的部分有所不同?
  • 目前它们在配置文件和打包格式上有所不同。很快就会出现更多差异。
  • 嗯。包装?您的意思是要将多个类打包为 jar,然后打包到 .tar.gz 中,或者您所说的打包格式是什么意思?还是只是包的结构?
  • 每种风格都适用于不同的客户,他们收到的应用程序包含不同的资源子集。根据客户的不同,内部也有针对不同架构编译的原生部分。
  • @LukaszGuminski 很有趣,但我在 1.0 版的 maven-reactor-plugin 上看不到目标注入模块,这似乎是最新的。即使这样有效,您仍然需要手动创建这些模块吗?

标签: maven pom.xml multi-module


【解决方案1】:

现在您可以使用maven-tiles 插件来获得所需的行为。

使用 maven-tiles,您可以在不同的 pom 中定义构建行为,并在任何您喜欢的地方导入它们。

MNG-5102 附有一个工作示例 --> daddy3.zip

Maven 的仅限继承的紧身衣现已正式移除。

【讨论】:

  • 如果mvn help:effective-pom 与瓷砖一起使用,那么这将是一个完美的解决方案。组合比继承更好地解决了这个问题。
【解决方案2】:

在我看来,您可以为此创建多个不同的程序集描述符,并配置多个插件执行,每个执行引用不同的描述符。您必须将项目维护为单个模块而不是多模块项目。只要您的发行版包含相同的类集但不同的资源或库,它就可以工作。

        <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,并在那里配置装配 pluing,以便您可以从那里控制分发的数量和包装的变化。您的项目不需要了解不同包装的详细信息。

我强烈建议将本机库保留为单独的模块,并使用存储库机制将已编译的库安装到其中。您可以使用不同的分类器来隔离平台,例如,

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

然后,您可以在项目中将这些库作为依赖项引用,然后将它们与您的发行版一起打包。

整体解决方案将在很大程度上取决于各种发行版的差异以及打包发行版的整体过程,但我认为这会奏效。

最终且更具可扩展性的解决方案是通过实施 Maven 插件来创建自己的打包。

【讨论】:

  • 这种解决方案适用于口味之间的长期差异相对较小(例如,仅限于包装)。但就我而言,提供每种风味的责任属于不同的团队,所以我不能假设变化会很小。
  • 组织约束对我来说也意味着,我不能允许在单个 pom 中“内联”所有风味的配置,而不为团队提供不相互干扰的基本结构。所以 Maven 配置文件,作为一种简单的配置分组机制,是我需要提供的最少的东西。但我还是更喜欢模块。
  • 关于原生组件,它们已经作为单独的 Maven 项目进行管理。但是我在问题中描述的问题也影响了他们。如何描述如何为新架构编译,而不需要单独更改每个原生 Maven 项目?
  • 总结一下,对于大型项目中管理多种风格的问题,我仍然看不到一个好的解决方案。
  • 顺便说一句,在我的情况下,资源也作为单独的 Maven 项目维护。因此,每种风味对其所需的资源都有自己的依赖关系。这已经表明所有风格的依赖不应该在单个 pom 中维护,而是分成模块,每个模块管理自己的依赖。
【解决方案3】:

根据我的经验,选项 3 效果最好,但我不必像您需要的那样扩展它 - 当我不得不这样做时,我使用了 maven-ant -plugin 创建一个参数化的 ant 脚本来进行自定义。它有一些缺点——即同时使用 ant 和 maven,因此实际的 POM 更难以理解,但它确实比 maven 提供了更大的灵活性。

【讨论】:

  • 确实,它变得相当复杂 :) 这还没有结束 :/ 谢谢!
【解决方案4】:

如果您使用的是 maven 3,您可以定义父 pom 的配置文件并根据文件存在性激活它们。 在子模块上,您可以通过简单地创建空文件来“继承风味”。

这在下面的链接中有更好的记录:

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-08-21
    • 1970-01-01
    • 1970-01-01
    • 2018-01-19
    • 1970-01-01
    • 2011-07-07
    • 1970-01-01
    • 2012-01-07
    相关资源
    最近更新 更多