情况是,我有两个具有相同结构的Maven多模块项目:
Parent - Module 1 - Module 2
当我构建项目1时,我看到父项是首先构建的(命令是 parent-> module1-> module2 )。但是对于项目2,父项是最后构建的(订单是 module1-> module2-> parent )。为什么这两个项目有不同的构建订单?此外,如何手动控制构建顺序?
更新1:
两个父项目都是没有源代码的简单POM项目,因此我无法根据依赖关系图解释构建顺序。
更新2:
除了GAV和子模块名称之外,父POM是相同的:
<?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>
答案 0 :(得分:36)
构建顺序由Maven reactor确定,Maven reactor是一种通过对项目进行排序来自动确保多模块构建的正确构建顺序的机制。
请参阅the official documentation了解其工作原理。
它说:
在对项目进行排序时,以下关系得到遵守:
- 项目依赖于构建中的另一个模块
- 插件声明,其中插件是构建
中的另一个模块- 构建
中另一个模块的插件依赖项- 构建
中另一个模块的构建扩展声明- 元素中声明的顺序(如果没有其他规则适用)
您无法手动控制构建顺序。如果要更改订单,则必须对影响反应堆排序顺序的项目进行更改。
答案 1 :(得分:11)
在较高级别,构建顺序基于模块依赖关系图的topological sort。
编辑:问题。我知道项目1包含两个模块,项目2也是如此。但是项目2中的模块是否明确地将“父”pom声明为父项?我想也许你的项目1模块明确地声明了父pom,而项目2模块则没有。这意味着项目2“父”根本不是父母,因此不必在模块之前构建。无论如何,这是我的猜测。
答案 2 :(得分:2)
我最近一直在使用Centos 7生活这个问题。我从3.0.5将maven更新到3.5.3并且这个问题已经解决了。如果有人有此问题,请先尝试。
答案 3 :(得分:0)
总结
为什么?
Maven 正在使用 <module>
声明来确定要包含在当前运行中的模块列表。 Maven 使用 <parent>
声明为每个包含的模块生成有效的 POM,然后用于执行该模块的构建。
在项目 1 中,module1
和 module2
中的每一个都在 parent
部分指定了 <parent>
模块。
在项目 2 中,module1
和 module2
都没有在 parent
部分指定 <parent>
模块。
如何手动控制构建顺序?
通过更改模块之间的依赖关系,包括<parent>
、<dependencies>
、插件依赖关系等,如the official documentation中所述。
另请查看 Introduction to the POM 中关于聚合和继承的讨论。
详情
Maven 中模块关系在聚合(<module>
声明)和继承(<parent>
声明)方面有 4 种可能的场景。
让我们假设一个模块 A
带有包装 pom
和一个模块 B
(包装无关紧要)。模块 A
可以是父级或聚合器。模块 B
可以将 A
引用为父级,也可以不引用。
案例 1:
A
和 B
都没有相互引用 - 模块是独立的。
Maven无法控制构建顺序,每个模块独立构建,手动控制构建顺序。
情况 2:
模块A
包括模块B
中的<modules>
。模块 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
。