在多项目构建中,似乎有几种方法来构建父poms,我想知道是否有人对每种方法的优点/缺点有任何想法。

拥有一个父pom的最简单的方法是将它放在项目的根目录中。

myproject/
  myproject-core/
  myproject-api/
  myproject-app/
  pom.xml

pom.xml既是父项目,也描述了-core -api和-app模块

下一个方法是将父目录分离到它自己的子目录中,如

myproject/
  mypoject-parent/
    pom.xml
  myproject-core/
  myproject-api/
  myproject-app/

父pom仍然包含模块,但它们是相对的,例如../myproject-core

最后,还有一个选项,其中模块定义和父模块是分开的

myproject/
  mypoject-parent/
    pom.xml
  myproject-core/
  myproject-api/
  myproject-app/
  pom.xml

父pom包含任何“共享”配置(依赖管理,属性等),myproject/pom.xml包含模块列表。

其目的是可扩展到一个大规模的构建,因此应该可扩展到大量的项目和工件。

一些额外的问题:

哪里是定义各种共享配置的最佳位置,比如在源代码控制、部署目录、公共插件等(我假设是父目录,但我经常被这个问题所咬,它们最终在每个项目中而不是一个公共项目中)。 maven-release插件,hudson和nexus如何处理你如何设置你的多项目(这可能是一个大问题,如果有人被多项目构建是如何设置的搞清楚了,问题就更大了)?

编辑:每个子项目都有自己的pom.xml,为了简洁起见,我省略了它。


An independent parent is the best practice for sharing configuration and options across otherwise uncoupled components. Apache has a parent pom project to share legal notices and some common packaging options. If your top-level project has real work in it, such as aggregating javadoc or packaging a release, then you will have conflicts between the settings needed to do that work and the settings you want to share out via parent. A parent-only project avoids that. A common pattern (ignoring #1 for the moment) is have the projects-with-code use a parent project as their parent, and have it use the top-level as a parent. This allows core things to be shared by all, but avoids the problem described in #2. The site plugin will get very confused if the parent structure is not the same as the directory structure. If you want to build an aggregate site, you'll need to do some fiddling to get around this. Apache CXF is an example the pattern in #2.


根据我的经验和Maven最佳实践,有两种“父poms”

"company" parent pom - this pom contains your company specific information and configuration that inherit every pom and doesn't need to be copied. These informations are: repositories distribution managment sections common plugins configurations (like maven-compiler-plugin source and target versions) organization, developers, etc Preparing this parent pom need to be done with caution, because all your company poms will inherit from it, so this pom have to be mature and stable (releasing a version of parent pom should not affect to release all your company projects!) second kind of parent pom is a multimodule parent. I prefer your first solution - this is a default maven convention for multi module projects, very often represents VCS code structure

其目的是可扩展到一个大规模的构建,因此应该可扩展到大量的项目和工件。

multiliprojects有树的结构-所以你不会被箭头指向父pom的一层。尝试为您的需求找到一个合适的项目结构——一个经典的例子是如何分发多模块项目

distibution/
documentation/
myproject/
  myproject-core/
  myproject-api/
  myproject-app/
  pom.xml
pom.xml

一些额外的问题: 哪里是定义各种共享配置的最佳位置,比如在源代码控制、部署目录、公共插件等(我假设是父目录,但我经常被这个问题所咬,它们最终在每个项目中而不是一个公共项目中)。

这个配置必须明智地分成“公司”父pom和项目父pom。与你所有项目相关的东西归“公司”母公司,与当前项目相关的归项目一。

maven-release插件,hudson和nexus如何处理你如何设置你的多项目(这可能是一个大问题,如果有人被多项目构建是如何设置的搞清楚了,问题就更大了)?

公司母公司pom必须首先发布。对于多项目适用标准规则。CI服务器需要知道正确构建项目的所有信息。


在我看来,要回答这个问题,您需要从项目生命周期和版本控制的角度来考虑。换句话说,父pom是否有自己的生命周期,即它是否可以与其他模块分开发布?

如果答案是肯定的(这是大多数在问题或评论中提到的项目的情况),那么父pom需要从VCS和Maven的角度获得自己的模块,你将在VCS级别得到这样的结果:

root
|-- parent-pom
|   |-- branches
|   |-- tags
|   `-- trunk
|       `-- pom.xml
`-- projectA
    |-- branches
    |-- tags
    `-- trunk
        |-- module1
        |   `-- pom.xml
        |-- moduleN
        |   `-- pom.xml
        `-- pom.xml

这使得签出有点痛苦,一种常见的处理方法是使用svn:externals。例如,增加一个trunk目录:

root
|-- parent-pom
|   |-- branches
|   |-- tags
|   `-- trunk
|       `-- pom.xml
|-- projectA
|   |-- branches
|   |-- tags
|   `-- trunk
|       |-- module1
|       |   `-- pom.xml
|       |-- moduleN
|       |   `-- pom.xml
|       `-- pom.xml
`-- trunks

使用以下外部定义:

parent-pom http://host/svn/parent-pom/trunk
projectA http://host/svn/projectA/trunk

签出中继将导致以下局部结构(模式#2):

root/
  parent-pom/
    pom.xml
  projectA/

你甚至可以选择在trunk目录中添加一个pom.xml:

root
|-- parent-pom
|   |-- branches
|   |-- tags
|   `-- trunk
|       `-- pom.xml
|-- projectA
|   |-- branches
|   |-- tags
|   `-- trunk
|       |-- module1
|       |   `-- pom.xml
|       |-- moduleN
|       |   `-- pom.xml
|       `-- pom.xml
`-- trunks
    `-- pom.xml

这个pom.xml是一种“伪”pom:它从来没有发布过,它不包含一个真正的版本,因为这个文件从来没有发布过,它只包含一个模块列表。对于这个文件,签出将导致这样的结构(模式#3):

root/
  parent-pom/
    pom.xml
  projectA/
  pom.xml

这个“黑客”允许在检查后从根启动反应堆构建,使事情更加方便。实际上,这就是我喜欢为大型构建设置maven项目和VCS存储库的方式:它只是工作,它的可伸缩性很好,它提供了您可能需要的所有灵活性。

如果答案是否定的(回到最初的问题),那么我认为您可以接受模式#1(做可能有效的最简单的事情)。

现在,关于附加问题:

哪里是定义各种共享配置的最佳位置,比如在源代码控制、部署目录、公共插件等(我假设是父目录,但我经常被这个问题所咬,它们最终在每个项目中而不是一个公共项目中)。

老实说,我不知道如何在这里不给出一个一般性的答案(比如“使用你认为有意义的相互化事物的水平”)。不管怎样,子poms总是可以覆盖继承的设置。

maven-release插件,hudson和nexus如何处理你如何设置你的多项目(这可能是一个大问题,如果有人被多项目构建是如何设置的搞清楚了,问题就更大了)?

我使用的设置工作得很好,没什么特别值得一提的。

实际上,我想知道maven-release-plugin如何处理模式#1(特别是<parent>部分,因为在发布时你不能有快照依赖)。这听起来像是一个先有鸡还是先有蛋的问题,但我就是不记得它是否有效,也懒得测试它。


第三种方法有一个小问题。由于聚合POMs (myproject/pom.xml)通常根本没有父节点,所以它们不共享配置。这意味着所有这些聚合POMs将只有默认存储库。

如果你只使用来自Central的插件,这不是问题,但是,如果你从内部存储库中使用plugin:goal格式运行插件,这将会失败。例如,你可以有foo-maven-plugin和org的groupId。提供goal generate-foo的示例。如果你试图从项目根运行它使用命令像mvn org。例如:foo-maven-plugin:generate-foo,它将无法在聚合模块上运行(参见兼容性说明)。

有几种解决方案:

Deploy plugin to the Maven Central (not always possible). Specify repository section in all of your aggregate POMs (breaks DRY principle). Have this internal repository configured in the settings.xml (either in local settings at ~/.m2/settings.xml or in the global settings at /conf/settings.xml). Will make build fail without those settings.xml (could be OK for large in-house projects that are never supposed to be built outside of the company). Use the parent with repositories settings in your aggregate POMs (could be too many parent POMs?).