同事一直在兜售maven及其魔法依赖的奇迹,但我发现它在我认为显而易见的用途上失败了。
假设我有一个带有主POM的根文件夹。
然后我有一些项目,称他们为A和B
B需要A,因此B文件夹中的POM中包含相应的依赖项
现在,回到根文件夹中,在配置文件中,我指定我要构建B。
当我执行通常的mvn clean安装时,我收到了失败,因为A没有构建。
我的朋友告诉我,我必须在根目录中的主要配置文件中指定A和B.
但是不是maven看到B的依赖管理的全部要点,转到B POM文件,它看到了对A的依赖,所以它应该自动构建A.
答案 0 :(得分:40)
使用主POM:
~/scratch/pom.xml
<?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>scratch</groupId>
<artifactId>scratch</artifactId>
<packaging>pom</packaging>
<version>1.0-SNAPSHOT</version>
<modules>
<module>nipple</module>
<module>cabbage</module>
</modules>
</project>
模块POM:
~/scratch/nipple/pom.xml
<?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">
<parent>
<artifactId>scratch</artifactId>
<groupId>scratch</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>scratch</groupId>
<artifactId>nipple</artifactId>
<version>1.0-SNAPSHOT</version>
</project>
~/scratch/cabbage/pom.xml
<?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">
<parent>
<artifactId>scratch</artifactId>
<groupId>scratch</groupId>
<version>1.0-SNAPSHOT</version>
</parent>
<modelVersion>4.0.0</modelVersion>
<groupId>scratch</groupId>
<artifactId>cabbage</artifactId>
<version>1.0-SNAPSHOT</version>
<dependencies>
<dependency>
<groupId>scratch</groupId>
<artifactId>nipple</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
</project>
清理完本地存储库后,我可以在根目录中发出mvn package
,最后建立所有模块。 (进入空洞的JAR,但已建成。)
Maven似乎在存储库或正在进行的构建中查找依赖项。当您只构建单个模块时,它不会自动遍历您的项目结构,因为您不需要在计算机上拥有父项目,更不用说当前模块上方的一个目录。 (亲子关系甚至不是双射的。)
之所以如此,可能是因为模块位置可预测的目录布局绝不是强制性的。上面例子的布局是这样的,这甚至有点普遍和可以接受:
projects
|
+--scratch
| |
| +--scratch-parent
| | |
| | +--pom.xml [The POM of scratch:scratch:1.0-SNAPSHOT]
| |
| +--nipple
| | |
| | +--pom.xml [The POM of scratch:mod1:1.0-SNAPSHOT]
| |
| +--cabbage
| | |
| | +--pom.xml [The POM of scratch:mod2:1.0-SNAPSHOT]
在这种情况下,父POM的<modules>
部分将是:
<modules>
<module>../nipple</module>
<module>../cabbage</module>
</modules>
请注意,哪个工件ID在哪个模块中没有任何说法。它只是告诉Maven这些是文件系统位置,在那里搜索与此构建相关的其他工件。
答案 1 :(得分:24)
我能想到你所期望的行为尚未实现的原因如下:
假设我正在研究A和B项目。目前A已经破解。如果依赖解析按照您的意愿发生,我将永远无法在A被修复之前构建B.所以我要么必须将我的更改回滚到A,要么首先关注修复A.无论哪种方式都可能不是我现在想要关注的。
一般来说B想要使用A的“最后好”版本,而不是最新版本。使用存储库中的依赖项意味着它们至少编译好了(希望单元测试也运行)。
答案 2 :(得分:14)
看看Maven reactor plugin,特别是reactor:make,它构建了一个模块以及它所依赖的所有模块。
答案 3 :(得分:5)
Rich是完全正确的。您所描述的通常不是预期的行为。 虽然如Deterb所述,如果父POM 知道模块,Maven反应器支持部分构建。
使用mvn install -pl B -am
构建还应(-am
)B的依赖关系(即A)。
无论如何,模块A 必须是父POM的模块。
答案 4 :(得分:4)
如果你正在使用IntelliJ,他们在Maven运行配置中有一个神奇的复选框:“解析工作空间工件”。所以不需要从父级安装或构建。
答案 5 :(得分:3)
答案只是它不是Maven的工作方式。 Maven背后的想法是为开发人员提供一个逻辑简单的系统来控制依赖关系。从存储库获取依赖关系是关键。每个例外都会削弱这种控制和简单性。在父POM中添加A作为依赖项可完全满足您的方案,而无需添加其他异常。使用批处理文件或ant脚本是解决方案的另一种方法。