从模块级别使用 maven -pl 选项和 运行 maven 有什么区别?
What is the difference between using maven -pl option and running maven from module level?
和
有区别吗
C:/dev/path/to/Project> mvn package -pl MyModule -am -s settings.xml
和
C:/dev/path/to/Project/MyModule> mvn package -am -s ../settings.xml
就我而言,这两个动作的结果应该是一样的。
但是,每种情况下的行为似乎都不同:前者似乎更广泛;后者似乎更广泛。后者结束得更快 - 我正在尝试理解为什么会这样。
让我们首先澄清一些关于多模块(聚合器)构建(即从 aggregator/parent 项目调用构建)和构建单个模块的内容。
让我们使用以下示例:
-+ modules-project
|- module-a
|- module-b (depends on module-a)
因此,modules-project 将在其 pom 中包含以下内容:
<modules>
<module>module-a</module>
<module>module-b</module>
</modules>
从模块项目文件夹构建时:
module-project> mvn clean install
Maven Reactor 将创建已声明模块的依赖图并相应地构建它们,因此模块-a 将在模块-b 之前构建,因为模块-b 依赖于模块-a
module-b> mvn clean install
可以正常工作,只构建模块 b,将模块 a 解析为依赖项(我们之前安装过),并在需要时将其用作构建类路径的一部分。
如果不是在模块项目上调用 clean install
我们会调用 clean package
,Maven 不会在我们的本地 Maven 缓存中安装任何东西,因此依赖于 module-a in无法解析 module-b 项目。澄清一下:
module-project> mvn clean package
仍将构建整个项目(及其所有子模块)并创建包(即 jar 文件)。
module-b> mvn clean package
现在会失败,因为对 module-a 的依赖不存在于本地 Maven 缓存中,也不存在于任何 Maven 存储库中,也就是说,它不作为依赖关系和 Maven 对其他模块一无所知,它正在构建一个简单的项目(模块),而无需了解其他模块(由 modules-project 提供)。相反,当构建模块项目时,Maven 使用更多信息构建每个模块,知道一个模块依赖于另一个模块,它不会在本地缓存或任何 Maven 存储库中查找模块间依赖性。同样,它是 reactor build.
这就是为什么只有当您已经构建了整个多模块项目并至少在本地 Maven 缓存中安装了它的工件时,您才能将子模块构建为单独的构建。这就是为什么最好的做法总是从多模块项目开始工作,这样 Maven 就有了所有需要的信息,你可以:
- 构建整个多模块项目(
mvn clean install
)
- 通过
-pl
选项构建单个或一组模块(但仍从多模块项目开始)
- 通过
-pl
和 -am
选项构建单个或一组模块 和 它们的依赖项(仍然来自多模块项目)
现在让我们澄清最后一点,这也将回答您的问题。
modules-project> mvn clean package -pl module-a
运行 会很好,只构建模块-a 作为反应堆构建的一部分。然而
modules-project> mvn clean package -pl module-b
会失败,因为 Maven 会按照要求尝试构建模块-b,但是,同样,会寻找模块-a 作为依赖项而不是模块,因此在本地 Maven 缓存或配置的 Maven 存储库中找不到它。
modules-project> mvn clean package -pl module-b -am
最终会正常工作,因为现在 Maven 也在构建依赖模块(感谢 -am
)并且知道在哪里可以找到它们(作为多模块信息的一部分,即 modules
节)。
我们来看最后一个案例:
module-b> mvn clean package -am
如果我们从未安装整个多模块项目(即我们总是运行 clean package
),会失败,-am
选项如果不是反应器构建的一部分,将被忽略(因为它是 reactor 的一个选项,而不是正常构建的选项)并且 Maven 仍会尝试在本地缓存或存储库中查找模块-a。
这就是为什么您应该始终从其 aggregator/parent 并通过 -pl
和 -am
选项构建子模块,以确保:
- 您构建正确,使用了正确的依赖项和模块信息
- 您是针对 code/dependency 的最新版本构建的,而不是针对您之前在 maven 缓存中安装的可能与其模块代码不一致的内容
这也是为什么你的观察是正确的,你提到的第一次调用(从聚合器项目构建子模块)花费的时间稍长,因为它不仅仅是子模块的构建,而是更多的东西(因为有更多信息可以过程,它是一种不同类型的构建,一个反应器构建,也可能构建依赖模块),而直接构建一个子模块(从它的目录)是一个更简单的 Maven 构建,因此也更快(但更容易出错,因为缺少一些信息)。
有关反应堆构建的这些选项的更多信息,请访问:
和
有区别吗C:/dev/path/to/Project> mvn package -pl MyModule -am -s settings.xml
和
C:/dev/path/to/Project/MyModule> mvn package -am -s ../settings.xml
就我而言,这两个动作的结果应该是一样的。
但是,每种情况下的行为似乎都不同:前者似乎更广泛;后者似乎更广泛。后者结束得更快 - 我正在尝试理解为什么会这样。
让我们首先澄清一些关于多模块(聚合器)构建(即从 aggregator/parent 项目调用构建)和构建单个模块的内容。
让我们使用以下示例:
-+ modules-project
|- module-a
|- module-b (depends on module-a)
因此,modules-project 将在其 pom 中包含以下内容:
<modules>
<module>module-a</module>
<module>module-b</module>
</modules>
从模块项目文件夹构建时:
module-project> mvn clean install
Maven Reactor 将创建已声明模块的依赖图并相应地构建它们,因此模块-a 将在模块-b 之前构建,因为模块-b 依赖于模块-a
module-b> mvn clean install
可以正常工作,只构建模块 b,将模块 a 解析为依赖项(我们之前安装过),并在需要时将其用作构建类路径的一部分。
如果不是在模块项目上调用 clean install
我们会调用 clean package
,Maven 不会在我们的本地 Maven 缓存中安装任何东西,因此依赖于 module-a in无法解析 module-b 项目。澄清一下:
module-project> mvn clean package
仍将构建整个项目(及其所有子模块)并创建包(即 jar 文件)。
module-b> mvn clean package
现在会失败,因为对 module-a 的依赖不存在于本地 Maven 缓存中,也不存在于任何 Maven 存储库中,也就是说,它不作为依赖关系和 Maven 对其他模块一无所知,它正在构建一个简单的项目(模块),而无需了解其他模块(由 modules-project 提供)。相反,当构建模块项目时,Maven 使用更多信息构建每个模块,知道一个模块依赖于另一个模块,它不会在本地缓存或任何 Maven 存储库中查找模块间依赖性。同样,它是 reactor build.
这就是为什么只有当您已经构建了整个多模块项目并至少在本地 Maven 缓存中安装了它的工件时,您才能将子模块构建为单独的构建。这就是为什么最好的做法总是从多模块项目开始工作,这样 Maven 就有了所有需要的信息,你可以:
- 构建整个多模块项目(
mvn clean install
) - 通过
-pl
选项构建单个或一组模块(但仍从多模块项目开始) - 通过
-pl
和-am
选项构建单个或一组模块 和 它们的依赖项(仍然来自多模块项目)
现在让我们澄清最后一点,这也将回答您的问题。
modules-project> mvn clean package -pl module-a
运行 会很好,只构建模块-a 作为反应堆构建的一部分。然而
modules-project> mvn clean package -pl module-b
会失败,因为 Maven 会按照要求尝试构建模块-b,但是,同样,会寻找模块-a 作为依赖项而不是模块,因此在本地 Maven 缓存或配置的 Maven 存储库中找不到它。
modules-project> mvn clean package -pl module-b -am
最终会正常工作,因为现在 Maven 也在构建依赖模块(感谢 -am
)并且知道在哪里可以找到它们(作为多模块信息的一部分,即 modules
节)。
我们来看最后一个案例:
module-b> mvn clean package -am
如果我们从未安装整个多模块项目(即我们总是运行 clean package
),会失败,-am
选项如果不是反应器构建的一部分,将被忽略(因为它是 reactor 的一个选项,而不是正常构建的选项)并且 Maven 仍会尝试在本地缓存或存储库中查找模块-a。
这就是为什么您应该始终从其 aggregator/parent 并通过 -pl
和 -am
选项构建子模块,以确保:
- 您构建正确,使用了正确的依赖项和模块信息
- 您是针对 code/dependency 的最新版本构建的,而不是针对您之前在 maven 缓存中安装的可能与其模块代码不一致的内容
这也是为什么你的观察是正确的,你提到的第一次调用(从聚合器项目构建子模块)花费的时间稍长,因为它不仅仅是子模块的构建,而是更多的东西(因为有更多信息可以过程,它是一种不同类型的构建,一个反应器构建,也可能构建依赖模块),而直接构建一个子模块(从它的目录)是一个更简单的 Maven 构建,因此也更快(但更容易出错,因为缺少一些信息)。
有关反应堆构建的这些选项的更多信息,请访问: