如何构造一个多模块的Maven项目以一次编译它? [英] How to structure a multi-modules Maven project to compile it at once?
问题描述
我有一个包含多个模块和子模块的Maven项目,我想一次进行编译,即仅使用一次调用"mvn clean install".
I have a Maven project with multiple modules and sub-modules and i want to compile it at once, i.e. using only one call to "mvn clean install".
对于基本项目,以下结构将起作用:
For a basic project, the following structure would work:
.
├── modules
│ ├── moduleA
│ │ └── pom.xml <--- Module A POM
│ ├── moduleB
│ │ └── pom.xml <--- Module B POM
│ └── pom.xml <--- Super POM (at the root of "modules" folder)
└── pom.xml <--- Aggregator POM
聚合器为:
<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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.test</groupId>
<artifactId>aggregator</artifactId>
<packaging>pom</packaging>
<version>1.0.0-SNAPSHOT</version>
<modules>
<module>modules</module>
<module>modules/moduleA</module>
<module>modules/moduleB</module>
</modules>
</project>
超级POM:
<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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.test</groupId>
<artifactId>super-pom</artifactId>
<packaging>pom</packaging>
<version>1.0.0-SNAPSHOT</version>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
</dependencies>
</dependencyManagement>
</project>
模块A的POM:
<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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>moduleA</artifactId>
<parent>
<groupId>org.test</groupId>
<artifactId>super-pom</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
</project>
模块B相似.
在项目的根目录下,运行"mvn clean install"命令会给出(清除.m2/repository文件夹后):
When at the root of the project, running "mvn clean install" command gives (after cleaning up the .m2/repository folder):
[...]
[INFO] ------------------------------------------------------------------------
[INFO] Reactor Summary:
[INFO]
[INFO] super-pom .......................................... SUCCESS [ 0.450 s]
[INFO] moduleA ............................................ SUCCESS [ 1.746 s]
[INFO] moduleB ............................................ SUCCESS [ 0.029 s]
[INFO] agregator .......................................... SUCCESS [ 0.006 s]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
现在,如果我想要更复杂的东西(但仍使用一个超级POM),例如:
Now if I want something that is more complex (but still using one super POM), such as:
.
├── modules
│ ├── lib1
│ │ ├── moduleA1
│ │ │ └── pom.xml
│ │ ├── moduleB1
│ │ │ └── pom.xml
│ │ └── pom.xml <--- lib1 aggregator POM
│ ├── lib2
│ │ ├── moduleA2
│ │ │ └── pom.xml
│ │ ├── moduleB2
│ │ │ └── pom.xml
│ │ └── pom.xml <--- lib2 aggregator POM
│ └── pom.xml <--- Super POM
└── pom.xml <--- Aggregator POM
根POM为:
<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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.test</groupId>
<artifactId>agregator</artifactId>
<packaging>pom</packaging>
<version>1.0.0-SNAPSHOT</version>
<modules>
<module>modules</module>
<module>modules/lib1</module>
<module>modules/lib2</module>
</modules>
</project>
Lib1 POM:
<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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.test</groupId>
<artifactId>lib1-agregator</artifactId>
<packaging>pom</packaging>
<version>1.0.0-SNAPSHOT</version>
<modules>
<module>moduleA1</module>
<module>moduleB1</module>
</modules>
</project>
并且,例如,模块A1 POM:
And, for instance moduleA1 POM:
<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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<artifactId>moduleA1</artifactId>
<parent>
<groupId>org.test</groupId>
<artifactId>super-pom</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
</project>
Maven无法解决POM文件(清理了.m2/repository文件夹之后):
Maven does not manage to resolve the POM files (after cleaning up the .m2/repository folder):
[INFO] Scanning for projects...
[ERROR] [ERROR] Some problems were encountered while processing the POMs:
[WARNING] 'parent.relativePath' of POM org.test:moduleA1:[unknown-version] (/Users/ben/IdeaProjects/ComplexMavenStructure/modules/lib1/moduleA1/pom.xml) points at org.test:lib1-agregator instead of org.test:super-pom, please verify your project structure @ line 7, column 13
[FATAL] Non-resolvable parent POM for org.test:moduleA1:[unknown-version]: Could not find artifact org.test:super-pom:pom:1.0.0-SNAPSHOT and 'parent.relativePath' points at wrong local POM @ line 7, column 13
[WARNING] 'parent.relativePath' of POM org.test:moduleB1:[unknown-version] (/Users/ben/IdeaProjects/ComplexMavenStructure/modules/lib1/moduleB1/pom.xml) points at org.test:lib1-agregator instead of org.test:super-pom, please verify your project structure @ line 7, column 13
[FATAL] Non-resolvable parent POM for org.test:moduleB1:[unknown-version]: Could not find artifact org.test:super-pom:pom:1.0.0-SNAPSHOT and 'parent.relativePath' points at wrong local POM @ line 7, column 13
[WARNING] 'parent.relativePath' of POM org.test:moduleA2:[unknown-version] (/Users/ben/IdeaProjects/ComplexMavenStructure/modules/lib2/moduleA2/pom.xml) points at org.test:lib2-agregator instead of org.test:super-pom, please verify your project structure @ line 7, column 13
[FATAL] Non-resolvable parent POM for org.test:moduleA2:[unknown-version]: Could not find artifact org.test:super-pom:pom:1.0.0-SNAPSHOT and 'parent.relativePath' points at wrong local POM @ line 7, column 13
[WARNING] 'parent.relativePath' of POM org.test:moduleB2:[unknown-version] (/Users/ben/IdeaProjects/ComplexMavenStructure/modules/lib2/moduleB2/pom.xml) points at org.test:lib2-agregator instead of org.test:super-pom, please verify your project structure @ line 7, column 13
[FATAL] Non-resolvable parent POM for org.test:moduleB2:[unknown-version]: Could not find artifact org.test:super-pom:pom:1.0.0-SNAPSHOT and 'parent.relativePath' points at wrong local POM @ line 7, column 13
@
[ERROR] The build could not read 4 projects -> [Help 1]
[ERROR]
[ERROR] The project org.test:moduleA1:[unknown-version] (/Users/ben/IdeaProjects/ComplexMavenStructure/modules/lib1/moduleA1/pom.xml) has 1 error
[ERROR] Non-resolvable parent POM for org.test:moduleA1:[unknown-version]: Could not find artifact org.test:super-pom:pom:1.0.0-SNAPSHOT and 'parent.relativePath' points at wrong local POM @ line 7, column 13 -> [Help 2]
[ERROR]
[ERROR] The project org.test:moduleB1:[unknown-version] (/Users/ben/IdeaProjects/ComplexMavenStructure/modules/lib1/moduleB1/pom.xml) has 1 error
[ERROR] Non-resolvable parent POM for org.test:moduleB1:[unknown-version]: Could not find artifact org.test:super-pom:pom:1.0.0-SNAPSHOT and 'parent.relativePath' points at wrong local POM @ line 7, column 13 -> [Help 2]
[ERROR]
[ERROR] The project org.test:moduleA2:[unknown-version] (/Users/ben/IdeaProjects/ComplexMavenStructure/modules/lib2/moduleA2/pom.xml) has 1 error
[ERROR] Non-resolvable parent POM for org.test:moduleA2:[unknown-version]: Could not find artifact org.test:super-pom:pom:1.0.0-SNAPSHOT and 'parent.relativePath' points at wrong local POM @ line 7, column 13 -> [Help 2]
[ERROR]
[ERROR] The project org.test:moduleB2:[unknown-version] (/Users/ben/IdeaProjects/ComplexMavenStructure/modules/lib2/moduleB2/pom.xml) has 1 error
[ERROR] Non-resolvable parent POM for org.test:moduleB2:[unknown-version]: Could not find artifact org.test:super-pom:pom:1.0.0-SNAPSHOT and 'parent.relativePath' points at wrong local POM @ line 7, column 13 -> [Help 2]
[ERROR]
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR]
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/ProjectBuildingException
[ERROR] [Help 2] http://cwiki.apache.org/confluence/display/MAVEN/UnresolvableModelException
我需要先构建超级pom:
I need to first build the super pom:
cd modules/
mvn clean install
只有这样,它才能编译:
And only then will it compile:
[INFO] Reactor Summary:
[INFO]
[INFO] super-pom .......................................... SUCCESS [ 0.271 s]
[INFO] moduleA1 ........................................... SUCCESS [ 1.202 s]
[INFO] moduleB1 ........................................... SUCCESS [ 0.027 s]
[INFO] lib1-agregator ..................................... SUCCESS [ 0.006 s]
[INFO] moduleA2 ........................................... SUCCESS [ 0.027 s]
[INFO] moduleB2 ........................................... SUCCESS [ 0.022 s]
[INFO] lib2-agregator ..................................... SUCCESS [ 0.007 s]
[INFO] agregator .......................................... SUCCESS [ 0.007 s]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
如果不进行两步编译,您将如何构造项目以使其正常工作?
How would you structure the project to make it work without this two-steps compilation?
:如注释中所述,将Super POM的relativePath添加到模块POM中会使代码使用一个命令行进行编译.
: as discussed in the comments, adding the relativePath of the Super POM to the modules POMs would make the code compile with one command line.
但是,即使我只将lib1分发给某些开发人员,即使我的超级POM在Maven存储库中,如果没有整个项目结构,lib1也不会编译.这使项目的模块化程度降低了.
However, if I want to distribute only lib1 to some developers, even though my super POM is on a Maven repository, lib1 would not compile without the whole project structure. This makes the project less modular.
推荐答案
让我像您一样开始,但是我对它们的命名有些不同:
Let me start like you did, but I name the things a little bit differently:
.
├── modules-root
│ ├── moduleA
│ │ └── pom.xml <--- Module A POM
│ ├── moduleB
│ │ └── pom.xml <--- Module B POM
│ └── pom.xml <--- modules root
└── pom.xml <--- project-root
让我们从project-root
开始,它看起来像这样:
Let's start with the project-root
, which will look like this:
<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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.test</groupId>
<artifactId>project-root</artifactId>
<packaging>pom</packaging>
<version>1.0.0-SNAPSHOT</version>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.11</version>
<scope>test</scope>
</dependency>
</dependencies>
</dependencyManagement>
<modules>
<module>modules-root</module>
</modules>
</project>
module-parent
将如下所示.我要强调的是,这仅包含对moduleA
和moduleB
的引用,并且将从project-root
继承 :
The module-parent
will look like this. I will emphasis that this contains only the reference to the moduleA
and moduleB
and will inherit from the project-root
:
<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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.test</groupId>
<artifactId>project-root</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<groupId>org.test.module</groupId>
<artifactId>module-parent</artifactId>
<packaging>pom</packaging>
<modules>
<module>moduleA</module>
<module>moduleB</module>
</modules>
</project>
moduleA
将如下所示.请注意,这将从module-parent
(父级)开始继承,该级别恰好高于...
moduleA
will look like this. Pay attention that this will inherit from module-parent
(parent) which is exactly one level above...
<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/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.test.module</groupId>
<artifactId>module-parent</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<artifactId>moduleA</artifactId>
<packaging>..</packaging>
<....other dependencies..>
</project>
如果使用这种结构,则可以简单地转到project-root
级别并执行:
If you use this kind of structure you can simply go to the project-root
level and do:
mvn clean install
此外,您还可以使用以下内容:
Furthermore afterwards you can use things like this:
mvn -pl moduleA ...
...仅构建模块A(但保持在project-root
级别...).
...to build only moduleA (but stay at the project-root
level...).
module-parent
可能看起来是浪费的或多余的,但是如果您获得更多模块,则可以通过dependencyManagement
定义其补充依赖项,或者可以通过pluginManagement
更改插件配置,这些配置仅在此子区域中使用. (moduleA,moduleB,...).如果您的项目变大,您将并行获得更多的module-parents
.. c21,其中包含应用程序的不同部分……以及使用此结构可以实现的不同目的.
module-parent
might look like wasted or superfluous in this example, but if you get more modules you could define their supplemental dependencies via dependencyManagement
or may changing plugin configurations via pluginManagement
which will only be used in this sub area (moduleA, moduleB, ...). If your project becomes larger, you will get more module-parents
in parallel..which contain different parts of your applications...and different intentions which can be achieved with this structure.
还有一件事要提;我已经将groupId
从org.test
更改为module-parent
中的org.test.module
.如果您有大量模块,这有时很有用,因为groupId
代表存储库中的文件夹结构(就像Java包在Java项目中一样)...这可以为您提供更好的概述...
One more thing is to mention; I have changed the groupId
from org.test
to org.test.module
in the module-parent
. This is sometimes useful if you have a large number of modules cause the groupId
represents the folder structure in your repository (as java packages do in a Java project)... this give you an better overview...
project-root
是用于通过dependencyManagement
等定义整体可用依赖项的位置.使用过的插件应通过pluginManagement
进行定义...或者可以使用
The project-root
is the location to define the overall usable dependencies via dependencyManagement
etc....and the used plugins which should be defined via pluginManagement
... or may be using maven-enforcer-plugin to define overall project rules...
这种结构的典型场景是Java EE项目或其他大型项目(可能有300 ...或1000个模块,是的)...
Typical scenarios for this kind of structure are Java EE projects or other large projects (may be with 300...or 1000 modules yes they exist)...
如果有更多模块,则可以使用maven的多线程功能并使用以下命令构建项目:
If you get more modules you can use the multi-thread capability of maven and build your project with:
mvn -T 4 clean install
来自project-root
,大大减少了构建时间.
from the project-root
which reduces the build time dramatically.
这篇关于如何构造一个多模块的Maven项目以一次编译它?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!