Maven多模块项目的构建顺序是什么?

74

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

Parent
    - Module 1
    - Module 2

当我构建项目1时,我发现首先构建parent(顺序为parent->module1->module2)。然而对于项目2,parent是最后构建的(顺序为module1->module2->parent)。为什么两个项目的构建顺序不同?此外,我如何手动控制构建顺序?

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

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

<?xml version="1.0" encoding="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>parent-group-id</groupId>
    <artifactId>parent-artifact-id</artifactId>
    <version>parent-version</version>
    <packaging>pom</packaging>
    <name>parent-name</name>
    <modules>
        <module>module-1</module>
        <module>module-2</module>
    </modules>
</project>

可能是 在Maven中为多项目强制执行构建顺序 的重复问题。 - Naman
1
你如何调用这两个构建?这里的细节可能很重要。 - Thorbjørn Ravn Andersen
由于版本不匹配,我在一个多模块项目中遇到了这种行为。根pom.xml版本是手动提高的,但子模块pom.xml仍然引用旧的父版本。 - Ed Randall
自从 Maven 3.5.0+(2017)以来,您可以避免在每个模块中重复指定父版本,请参阅:https://dev59.com/Z2kv5IYBdhLWcg3wdQnm#51969067 - Ed Randall
4个回答

63
构建顺序由Maven反应堆确定,它是一种机制,通过对项目进行排序自动确保多模块构建的正确构建顺序。
请参阅官方文档以了解其工作原理。
它说:
以下关系在排序项目时受到尊重:
- 一个项目依赖于构建中的另一个模块 - 插件声明,其中插件是构建中的另一个模块 - 插件依赖于构建中的另一个模块 - 在构建元素中声明的顺序(如果没有其他规则适用) - 对构建中的另一个模块进行构建扩展声明
您无法手动控制构建顺序。 如果要更改顺序,必须更改影响反应器排序顺序的项目。

3
但这并不能解释为什么这两个项目有不同的构建顺序。 - Zhao Yi
1
不应该有任何不同。还有其他的差异吗?这些孩子有相同的父母吗? - user2189998
检查子模块中的父版本 - Ed Randall

14

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

编辑:我有一个问题。我知道项目1包含两个模块,项目2也是如此。但是,项目2中的模块是否明确声明了“parent” pom作为父级?我想也许你的项目1模块明确声明了父级pom,而项目2模块没有。这意味着项目2的“parent”实际上并不是真正的父级,因此在模块之前不必构建它。这只是我的猜测。


但是这两个父项目都是简单的 POM 项目,没有任何源代码。在这里依赖关系图并没有意义。 - Zhao Yi
引用父POM也是一种依赖。 - Illya Kysil

8

最近我在使用CentOS 7时遇到了这个问题。我将Maven从3.0.5更新到3.5.3后,问题得到了解决。如果其他人也遇到了这个问题,可以首先尝试更新Maven版本。


欢迎来到SO。这似乎是对一个如此老的问题的不太可能的答案。请参阅https://stackoverflow.com/help/how-to-answer,了解如何回答问题的帮助。 - Nick
5
我写这篇文章是为了像我一样遇到同样问题的人。当时我无法找到相关信息,最终我自己解决了问题,并将解决方法记录在这里,这样如果其他人也遇到相同问题并在谷歌上搜索相应内容,就可以找到这篇文章。 - Yiğit Duman

2

概述

为什么?

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

项目1中,module1module2都在<parent>部分中指定了父模块。 在项目2中,module1module2都没有在<parent>部分中指定父模块。

如何手动控制构建顺序?

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

请还参考POM介绍中有关聚合和继承的讨论。


详细信息

Maven中模块关系在聚合(<module>声明)和继承(<parent>声明)方面有4种可能的情况。

假设有一个打包为pom的模块A和一个模块B(打包类型不重要)。模块A可以是父模块或聚合模块。模块B可以引用A作为父模块或不引用。

情况1:

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

情况2:

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

  • 使用命令 mvn -f A/pom.xml 会先构建 B,然后再构建 A
  • 使用命令 mvn -f B/pom.xml 只会构建 B

情况3:

模块 A 包含 模块 B<modules> 中。模块 B 声明 A 为父模块。在这种情况下,模块 A 同时是父模块和聚合器(反应堆)模块 B

  • 使用命令 mvn -f A/pom.xml 会先构建 A,然后再构建 B
  • 使用命令 mvn -f B/pom.xml 只会构建 B,但是会使用 A 的 POM 文件来生成 B 的有效 POM 文件,通过从本地存储库解析或按照 /project/parent/relativePath 进行解析。

情况4:

模块 A 不包含 模块 B<modules> 中。模块 B 声明 A 为父模块。在这种情况下,模块 A 是模块 B 的父模块。

  • 使用命令 mvn -f A/pom.xml 只会构建 A
  • 使用命令 mvn -f B/pom.xml 只会构建 B,但是会使用 A 的 POM 文件来生成 B 的有效 POM 文件,通过从本地存储库解析或按照 /project/parent/relativePath 进行解析。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接