似乎有几种方法可以在多项目构建中构建父 pom,我想知道是否有人对每种方式的优点/缺点有任何想法。
拥有父 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 包含任何“共享”配置(dependencyManagement、属性等),而 myproject/pom.xml 包含模块列表。
目的是可扩展到大规模构建,因此应该可扩展到大量项目和工件。
几个额外的问题:
在源代码控制、部署目录、通用插件等中定义各种共享配置的最佳位置在哪里(我假设是父级,但我经常被这个咬伤,它们最终出现在每个项目中而不是一个普通的)。
maven-release 插件、hudson 和 nexus 如何处理你如何设置你的多项目(可能是一个巨大的问题,如果有人在多项目构建的设置方式中被抓住,那就更重要了)?
编辑:每个子项目都有自己的 pom.xml,我把它省略了以保持简洁。
在我看来,要回答这个问题,你需要从项目生命周期和版本控制的角度来思考。换句话说,父 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
。例如,添加一个 trunks
目录:
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
检出 trunks
会产生以下本地结构(模式 #2):
root/
parent-pom/
pom.xml
projectA/
或者,您甚至可以在 trunks
目录中添加一个 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
这种“hack”允许在结帐后从根启动反应堆构建,并使事情变得更加方便。实际上,这就是我喜欢为大型构建设置 maven 项目和 VCS 存储库的方式:它可以正常工作,可以很好地扩展,它提供了您可能需要的所有灵活性。
如果答案是否定的(回到最初的问题),那么我认为你可以接受模式#1(做最简单的可能可行的事情)。
现在,关于奖金问题:
在源代码控制、部署目录、通用插件等中定义各种共享配置的最佳位置在哪里(我假设是父级,但我经常被这个咬伤,它们最终出现在每个项目中而不是一个普通的)。
老实说,我不知道如何在这里不给出一般性的答案(例如“使用您认为使事物相互化有意义的水平”)。无论如何,子 pom 总是可以覆盖继承的设置。
maven-release 插件、hudson 和 nexus 如何处理你如何设置你的多项目(可能是一个巨大的问题,如果有人在多项目构建的设置方式中被抓住,那就更重要了)?
我使用的设置效果很好,没有什么特别要提的。
实际上,我想知道 maven-release-plugin 如何处理模式 #1(尤其是 <parent>
部分,因为您在发布时不能拥有 SNAPSHOT 依赖项)。这听起来像是先有鸡还是先有蛋的问题,但我只是不记得它是否有效并且懒得测试它。
根据我的经验和 Maven 最佳实践,有两种“父 pom”
“公司”父 pom - 这个 pom 包含您公司的特定信息和配置,这些信息和配置继承了每个 pom,不需要复制。这些信息是: 存储库 分发管理部分 常用插件配置(如 maven-compiler-plugin 源和目标版本) 组织、开发人员等 准备这个父 pom 需要小心,因为您公司的所有 pom 都将从它继承,所以这个 pom 必须成熟稳定(发布一个父 pom 版本不应该影响发布您公司所有的项目!)
存储库
分销管理科
常用插件配置(如 maven-compiler-plugin 源和目标版本)
组织、开发人员等
第二种父 pom 是多模块父。我更喜欢您的第一个解决方案 - 这是多模块项目的默认 maven 约定,通常代表 VCS 代码结构
目的是可扩展到大规模构建,因此应该可扩展到大量项目和工件。
Mutliprojects 具有树的结构 - 所以你不会被向下箭头到父 pom 的一级。尝试找到适合您需求的项目结构 - 一个经典示例是如何分发多模块项目
distibution/
documentation/
myproject/
myproject-core/
myproject-api/
myproject-app/
pom.xml
pom.xml
一些额外的问题:在源代码控制、部署目录、常用插件等中定义各种共享配置的最佳位置在哪里。(我假设是父级,但我经常被这个咬到,他们最终在每个项目中,而不是在一个共同的项目中)。
此配置必须明智地拆分为“公司”父 pom 和项目父 pom。与您的所有项目相关的事情都转到“公司”父级,而与当前项目相关的事情转到项目一个。
maven-release 插件、hudson 和 nexus 如何处理你如何设置你的多项目(可能是一个巨大的问题,如果有人在多项目构建的设置方式中被抓住,那就更重要了)?
必须先发布公司父 pom。对于多项目标准规则适用。 CI 服务器需要了解所有信息才能正确构建项目。
独立父级是在其他非耦合组件之间共享配置和选项的最佳实践。 Apache 有一个父 pom 项目来共享法律声明和一些常见的打包选项。如果您的顶级项目中有实际工作,例如聚合 javadoc 或打包发布,那么您将在完成该工作所需的设置与您希望通过父级共享的设置之间产生冲突。仅父项目可以避免这种情况。一个常见的模式(暂时忽略#1)是让项目代码使用父项目作为其父项目,并让它使用顶级作为父项目。这允许所有人共享核心内容,但避免了#2中描述的问题。如果父结构与目录结构不同,站点插件会变得非常混乱。如果你想建立一个聚合网站,你需要做一些摆弄来解决这个问题。 Apache CXF 是 #2 中的模式示例。
第三种方法有一个小问题。由于聚合 POM (myproject/pom.xml) 通常根本没有父级,因此它们不共享配置。这意味着所有这些聚合 POM 将只有默认存储库。
如果您只使用来自 Central 的插件,这不是问题,但是,如果您使用内部存储库中的 plugin:goal 格式运行插件,这将失败。例如,您可以让 foo-maven-plugin
的 groupId 为 org.example
提供目标 generate-foo
。如果您尝试使用 mvn org.example:foo-maven-plugin:generate-foo
之类的命令从项目根目录运行它,它将无法在聚合模块上运行(请参阅 compatibility note)。
几种解决方案是可能的:
将插件部署到 Maven 中心(并非总是可能)。在所有聚合 POM 中指定存储库部分(违反 DRY 原则)。在 settings.xml 中配置此内部存储库(在 ~/.m2/settings.xml 的本地设置中或 /conf/settings.xml 的全局设置中)。没有这些 settings.xml 将使构建失败(对于不应该在公司外部构建的大型内部项目可能没问题)。在您的聚合 POM 中使用具有存储库设置的父级(可能是太多的父级 POM?)。