使用maven -pl选项和从模块级别运行maven有什么区别?

kar*_*kir 5 pom.xml maven-3 maven multi-module maven-reactor

两者之间有什么区别吗?

C:/dev/path/to/Project> mvn package -pl MyModule -am -s settings.xml
Run Code Online (Sandbox Code Playgroud)

C:/dev/path/to/Project/MyModule> mvn package -am -s ../settings.xml
Run Code Online (Sandbox Code Playgroud)

就我而言,这两项行动的结果应该是一样的.

然而,在每种情况下,行为似乎都不同:前者似乎更广泛; 后者更快结束 - 我正在努力理解为什么会这样.

A_D*_*teo 14

让我们首先澄清一下有关多模块(聚合器)构建(即,从聚合器/父项目调用构建)和构建单个模块的内容.

我们使用以下示例:

-+ modules-project
 |- module-a
 |- module-b (depends on module-a)
Run Code Online (Sandbox Code Playgroud)

因此,模块项目将作为其pom的一部分具有以下内容:

<modules>
    <module>module-a</module>
    <module>module-b</module>
</modules>
Run Code Online (Sandbox Code Playgroud)

从module-project文件夹构建时:

module-project> mvn clean install
Run Code Online (Sandbox Code Playgroud)

Maven的反应堆将创建申报模块的依赖关系图,并建立相应的他们,因此模块一个将之前模块-B内置因为模块B依赖于模块一

module-b> mvn clean install
Run Code Online (Sandbox Code Playgroud)

可以正常工作,只构建module-b,将模块-a解析为依赖项(我们之前安装过),并在需要时将其作为构建类路径的一部分使用.

如果不是调用clean installon modules-project我们会调用a clean package,Maven就不会在我们的本地Maven缓存中安装任何东西,因此无法解析module-b项目中对module-a的依赖.澄清:

module-project> mvn clean package
Run Code Online (Sandbox Code Playgroud)

仍然会构建整个项目(包含所有子模块)并创建包(即jar文件).

module-b> mvn clean package
Run Code Online (Sandbox Code Playgroud)

现在会失败,因为对本地Maven缓存或任何Maven存储库中不存在对module-a的依赖,也就是说,它不作为依赖存在而且Maven对其他模块一无所知,它正在构建一个简单的项目(模块),不了解其他模块(由modules-project提供).当构建模块项目时,Maven正在构建具有更多信息的每个模块,知道模块与另一个模块的依赖关系,它不会在本地缓存或任何Maven存储库中查找模块间依赖关系.同样,它是一个反应堆构建.

这就是为什么只有在已经构建整个多模块项目并且至少在本地Maven缓存中安装其工件时,才能将子模块构建为单独的构建.这就是为什么最佳实践始终是从多模块项目开始工作,以便Maven拥有所有必需的信息,您可以:

  • 构建整个多模块项目(mvn clean install)
  • 通过-pl选项构建单个或一组模块(但仍然从多模块项目开始)
  • 构建单个或一组模块,并通过它们的依赖-pl-am选项(仍从多模块项目)

让我们现在澄清最后一点,它也将回答你的问题.

modules-project> mvn clean package -pl module-a
Run Code Online (Sandbox Code Playgroud)

运行正常,只构建模块-a作为反应堆构建的一部分.然而

modules-project> mvn clean package -pl module-b
Run Code Online (Sandbox Code Playgroud)

失败,因为Maven将按照要求尝试构建module-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选项将被忽略,如果不是反应器构建的一部分(因为它是一个选项反应器,而不是正常的生成)和Maven会仍尝试在本地缓存或存储库中查找module-a.

这就是为什么你应该总是从它的聚合器/父和通过-pl-am选项构建一个子模块,以确保:

  • 使用正确的依赖项和模块信息正确构建
  • 您构建了最新版本的代码/依赖项,而不是针对先前在maven缓存中安装的某些内容,这些内容可能与其模块的代码不一致

这也是为什么你的观察是正确的,你提到的第一个调用(从聚合器项目构建一个子模块)需要稍长一些,因为它不仅仅是子模块的构建,而是更多的东西(因为有更多的信息要处理,它是一个不同类型的构建,一个反应堆,也可能构建依赖模块),而直接构建一个子模块(从其目录)是一个更简单的Maven构建,因此也更快(但由于缺少一些信息,更容易出错).

有关这些反应堆构建选项的更多信息,请点击此处.