65

情况是,我有两个结构相同的 Maven 多模块项目:

家长
    - 模块 1
    - 模块 2

当我构建项目 1 时,我看到先构建父级(顺序是parent->module1->module2)。但是对于项目 2,最后构建了父级(顺序为module1->module2->parent)。为什么这两个项目有不同的构建顺序?此外,如何手动控制构建顺序?

更新1:
两个父项目都是没有源代码的简单POM项目,所以我无法根据依赖图解释构建顺序。

更新 2:
除了 GAV 和子模块名称之外,父 POM 是相同的:

<?xml 版本="1.0" 编码="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http:// /maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>父组ID</groupId>
    <artifactId>parent-artifact-id</artifactId>
    <version>父版本</version>
    <包装>pom</包装>
    <name>父名</name>
    <模块>
        <module>module-1</module>
        <module>module-2</module>
    </模块>
</项目>
4

4 回答 4

53

构建顺序由 Maven 反应器确定,这是一种通过对项目进行排序来自动确保多模块构建的正确构建顺序的机制。

请参阅官方文档了解其工作原理。

它说:

排序项目时遵循以下关系:

  • 项目依赖于构建中的另一个模块
  • 插件声明,其中插件是构建中的另一个模块
  • 插件依赖于构建中的另一个模块
  • 构建中另一个模块的构建扩展声明
  • 元素中声明的顺序(如果没有其他规则适用)

您无法手动控制构建顺序。如果要更改顺序,则必须对影响反应器排序顺序的项目进行更改。

于 2012-06-21T04:57:02.767 回答
14

在高层次上,构建顺序基于模块依赖图的拓扑排序

编辑:问你问题。我知道项目 1 包含两个模块,项目 2 也是如此。但是项目 2 中的模块是否明确将“父”pom 声明为父节点?我在想也许你的项目 1 模块明确声明了父 pom,而项目 2 模块没有。这意味着项目 2“父级”根本不是真正的父级,因此不必在模块之前构建。无论如何,这是我的猜测。

于 2012-06-21T05:00:48.003 回答
8

我最近在使用 CentOS 7 时遇到了这个问题。我将 Maven 从 3.0.5 更新到 3.5.3,问题已经解决。如果有人也有这个问题,您可以先尝试这样做。

于 2018-05-30T10:55:48.817 回答
2

概括

为什么?

Maven 使用<module>声明来确定要包含在当前运行中的模块列表。Maven 使用<parent>声明为每个包含的模块生成有效的 POM ,然后用于执行该模块的构建。

Project 1中,每个module1module2指定parent模块中的<parent>部分。在Project 2中,既不module1也不module2指定parent模块中的<parent>部分。

如何手动控制构建顺序?

通过更改模块之间的依赖关系,包括<parent>、、<dependencies>插件依赖等,如官方文档中所述

另请查看POM 简介以了解有关聚合和继承的讨论。


细节

Maven中模块关系的可能场景有聚合(<module>声明)和继承(<parent>声明)四种情况。

让我们假设一个A带有包装pom的模块和一个模块B(包装无关紧要)。该模块A可以是父模块或聚合器。该模块B可以引用A为父级,也可以不引用。

情况1:

既不相互引用,A也不B相互引用 - 模块是独立的。Maven 无法控制构建顺序,每个模块都是独立构建的,具有手动构建顺序控制。

案例二:

该模块A 包括. B_ <modules>该模块B 未声明 A为父模块。在这种情况下,模块A是模块的聚合器。B

  • Maven 调用mvn -f A/pom.xml将首先构建B,然后A.
  • Maven 调用mvn -f B/pom.xml只会构建B

案例3:

该模块A 包括. B_ <modules>该模块B 声明 A为父模块。在这种情况下,模块A既是模块的父模块,是模块的聚合器(反应器) 。B

  • Maven 调用mvn -f A/pom.xml将首先构建A,然后B.
  • Maven 调用mvn -f B/pom.xmlB仅构建,但将使用 POMA生成有效的 POM,B方法是从本地存储库或通过以下方式解析它/project/parent/relativePath

案例4:

该模块A B包括<modules>. 该模块B 声明 A为父模块。在这种情况下,模块A是模块的父级。B

  • Maven 调用mvn -f A/pom.xml只会构建A
  • Maven 调用mvn -f B/pom.xmlB仅构建,但将使用 POMA生成有效的 POM,B方法是从本地存储库或通过以下方式解析它/project/parent/relativePath
于 2021-02-24T13:27:03.613 回答