【问题标题】:Maven project version inheritance - do I have to specify the parent version?Maven 项目版本继承 - 我必须指定父版本吗?
【发布时间】:2012-05-21 20:41:23
【问题描述】:

我有两个项目:父项目:A,子项目:B

A/pom.xml:

<groupId>com.dummy.bla</groupId>
<artifactId>parent</artifactId>
<version>0.1-SNAPSHOT</version>
<packaging>pom</packaging>

在 B/pom.xml 中,我有:

    <parent>
        <groupId>com.dummy.bla</groupId>
        <artifactId>parent</artifactId>
        <version>0.1-SNAPSHOT</version>     
    </parent>

    <groupId>com.dummy.bla.sub</groupId>
    <artifactId>kid</artifactId>

我希望 B 从父级继承版本,所以在我的情况下,我需要放置 0.1-SNAPSHOT 的唯一位置是 A/pom.xml。但是,如果我从父部分下的B/pom.xml 中删除&lt;version&gt;0.1-SNAPSHOT&lt;/version&gt;,maven 会抱怨缺少父版本。

有没有办法我可以只使用 ${project.version} 或类似的东西来避免在两个 poms 中使用 01.-SNAPSHOT

【问题讨论】:

标签: inheritance maven


【解决方案1】:

从 Maven 3.5.0 开始,您可以使用 ${revision} 占位符。此处记录了使用情况:Maven CI Friendly Versions

简而言之,父 pom 看起来像这样(引自 Apache 文档):

<project>
  <modelVersion>4.0.0</modelVersion>
  <parent>
    <groupId>org.apache</groupId>
    <artifactId>apache</artifactId>
    <version>18</version>
  </parent>
  <groupId>org.apache.maven.ci</groupId>
  <artifactId>ci-parent</artifactId>
  <name>First CI Friendly</name>
  <version>${revision}</version>
  ...
  <properties>
    <revision>1.0.0-SNAPSHOT</revision>
  </properties>
  <modules>
    <module>child1</module>
    ..
  </modules>
</project>

和孩子这样的pom

<project>
  <modelVersion>4.0.0</modelVersion>
  <parent>
    <groupId>org.apache.maven.ci</groupId>
    <artifactId>ci-parent</artifactId>
    <version>${revision}</version>
  </parent>
  <groupId>org.apache.maven.ci</groupId>
  <artifactId>ci-child</artifactId>
   ...
</project>

您还必须使用Flatten Maven Plugin 生成包含用于部署的专用版本号的 pom 文档。 HowTo 记录在链接的文档中。

@khmarbaise 还写了一篇关于此功能的精彩帖子:Maven: POM Files Without a Version in It?

【讨论】:

  • 我按照您的描述配置了我的项目,但是没有“Flatten Maven 插件”,它似乎可以按预期工作,这可能吗?我也遇到了 maven 3.2.1 的错误,但 maven 3.3.9+ 似乎工作正常。
  • @Max 这取决于您对“按预期工作”的定义。我猜构建会通过,但安装/部署到存储库可能不是一个好主意,因为子 pom 中没有版本号,只有一个占位符(请参阅documentation
  • 我在具有默认属性的父 pom 中使用 ${revision} (0.1-default。子 pom 也使用${revision}。我使用“mvn clean install -Drevision=0.1.${bamboo.buildNumber}”。当我扫描部署日志时,所有内容都设置为 0.1.820 和 0.1-default甚至不在日志中(820 是 buildNumber)。当我扫描生成的 jar 时,我在清单中看到“Implementation-Version:0.1.820”,并且在 pom.properties 文件中看到“version=0.1.820”。 pom文件本身有${revision}。所以我觉得没问题?
  • @Max 尝试将 pom(在 maven 存储库中)中版本为 ${revision} 的 jar 解析为另一个项目中的依赖项。我认为这行不通。
  • @Ralf 几年前我不再认为版本范围是个好主意。您无法使用它获得可重复的构建。所以我不再使用它们了。
【解决方案2】:

编辑:自 Maven 3.5.0 以来,使用${revision} 占位符有一个很好的解决方案。有关详细信息,请参阅FrVaBe's answer。对于以前的 Maven 版本,请参阅下面的原始答案。


不,没有。您始终必须指定父母的版本。幸运的是,在大多数情况下,它作为模块的版本被继承。此外,这个父版本的声明是由 Maven Release Plugin 自动碰撞的,所以 - 事实上 - 只要你使用 Maven Release Plugin 发布或只是碰撞版本,你在两个地方都有版本不是问题。

请注意,在某些情况下,这种行为实际上还不错,并且提供了您可能需要的更多灵活性。有时你想使用一些以前的父版本来继承,但这不是主流情况。

【讨论】:

  • 现在您可以为此使用${revision} 占位符。看我的回答;-)
  • 这已经过时了 - 在这里查看@FrVaBe 的答案:stackoverflow.com/a/51969067/514483
  • @FrVaBe 如果我们有不同版本的嵌套父母怎么办?我们不能在那里使用一个 ${revision} 属性,这还不够。
  • @halil 问题是关于从父级继承一个版本,目标是在两个工件中具有相同的版本。如果您有不同版本的不同父母(在继承层次结构中),您可能不会使它们都成为相同的版本。因此,我不完全理解该评论。
  • 这似乎不适用于 Maven 3.6.3 - 使用 mvn 版本:在此答案中设置 stackoverflow.com/a/31206432/57033
【解决方案3】:

Maven 并非旨在以这种方式工作,但存在一种解决方法来实现这一目标(可能有副作用,您必须尝试一下)。诀窍是告诉子项目通过其相对路径而不是其纯 maven 坐标找到其父项目,并且除了在属性中外部化版本号:

父 pom

<groupId>com.dummy.bla</groupId>
<artifactId>parent</artifactId>
<version>${global.version}</version>
<packaging>pom</packaging>

<properties>
   <!-- Unique entry point for version number management --> 
   <global.version>0.1-SNAPSHOT</global.version>
</properties>

儿童绒球

<parent>
   <groupId>com.dummy.bla</groupId>
   <artifactId>parent</artifactId>
   <version>${global.version}</version>
   <relativePath>..</relativePath>    
</parent>

<groupId>com.dummy.bla.sub</groupId>
<artifactId>kid</artifactId>

我在我的一个项目中使用了一段时间,没有具体问题,除了 maven 在构建开始时记录了很多警告,这不是很优雅。

编辑

似乎 maven 3.0.4 不再允许这样的配置了。

【讨论】:

  • 是的,我担心 maven 的设计不是这样工作的,最好坚持将版本放在 sub pom.xml 中。无论如何,maven 发布插件并不真正关心那里的版本。
  • 对于 3.0.5 工作正常。你应该把 放在最上面。
  • 它适用于 3.2.3。 的位置无关紧要。不过你会收到警告:'version' contains an expression but should be a constant.
  • 请小心。当您的项目被另一个项目引用时,这不起作用。该属性不会被解析,将按字面意思处理(即 ${my.version})。这会导致解析依赖时失败。
  • 我也已经使用它很长一段时间了,对于单个多模块项目它工作得很好(目前使用 maven 3.3.9)。但是,一旦您的项目成为另一个项目的依赖项,事情就会变得非常棘手。我真的建议采纳下面@pay 提出的建议。
【解决方案4】:

更新版本 IMO 的最简单方法:

$ mvn versions:set -DgenerateBackupPoms=false

(在您的根/父 pom 文件夹中执行此操作)。

解析您的 POM,并询问您要设置哪个版本。

【讨论】:

  • 你也可以加上-DnewVersion={versionToBeUpdated}来避免交互输入。
  • 我认为这是最好的答案,它可以在不破坏子项目的情况下自动更改版本(如果没有父 pom,您将无法引用它)。
  • 是的!这就是答案。 ?
  • 如果子和父 pom 版本最初不同,首先更新它们以匹配,mvn versions:update-child-modules 否则将跳过所有子模块 pom 版本。
【解决方案5】:

正如 Yanflea 所说,有办法解决这个问题。

在 Maven 3.5.0 中,您可以使用以下方式从父项目下传版本:

父 POM.xml

<project ...>
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.mydomain</groupId>
    <artifactId>myprojectparent</artifactId>
    <packaging>pom</packaging>
    <version>${myversion}</version>
    <name>MyProjectParent</name>

    <properties>
        <myversion>0.1-SNAPSHOT</myversion>
    </properties>

    <modules>
        <module>modulefolder</module>
    </modules>
    ...
</project>

模块 POM.xml

<project ...>
    <modelVersion>4.0.0</modelVersion>

    <parent>
        <groupId>com.mydomain</groupId>
        <artifactId>myprojectmodule</artifactId>
        <version>${myversion}</version> <!-- This still needs to be set, but you can use properties from parent -->
    </parent>

    <groupId>se.car_o_liner</groupId>
    <artifactId>vinno</artifactId>
    <packaging>war</packaging>
    <name>Vinno</name>
    <!-- Note that there's no version specified; it's inherited from parent -->
    ...
</project>

您可以随意将myversion 更改为您想要的任何非保留属性。

【讨论】:

  • 当从另一个项目中引用一个模块时,Maven 不会解析该属性。这正常吗?
  • 我相信这个问题可能值得自己输入,而不是在这样的评论中。没有看到你的代码,我只能疯狂地猜测。
  • @LeoLozes 你的问题解决了吗(来自另一个项目的引用模块)?
  • @MortezaMalvandi 是的!我的答案在底部:)
  • Maven 3.6.0 对此配置发出警告:“强烈建议修复这些问题,因为它们会威胁您构建的稳定性。” “因此,未来的 Maven 版本可能不再支持构建此类格式错误的项目。”
【解决方案6】:

你也可以使用:

$ mvn release:update-versions -DdevelopmentVersion={version}

更新 POM 中的版本号。

【讨论】:

    【解决方案7】:

    eFox 的答案适用于单个项目,但当我从另一个项目中引用模块时(pom.xml 仍然存储在我的 .m2 中,带有属性而不是版本)。

    但是,如果将它与flatten-maven-plugin 结合使用,它会起作用,因为它会生成具有正确版本的 pom,而不是属性。

    我在插件定义中更改的唯一选项是outputDirectory,默认为空,但我更喜欢将它放在target 中,这是在我的.gitignore 配置中设置的:

    <plugin>
       <groupId>org.codehaus.mojo</groupId>
       <artifactId>flatten-maven-plugin</artifactId>
       <version>1.0.1</version>
       <configuration>
          <updatePomFile>true</updatePomFile>
          <outputDirectory>target</outputDirectory>
       </configuration>
       <executions>
          <execution>
             <id>flatten</id>
             <phase>process-resources</phase>
             <goals>
                <goal>flatten</goal>
             </goals>
          </execution>
       </executions>
    </plugin>
    

    插件配置进入父pom.xml

    【讨论】:

      【解决方案8】:

      使用mvn -N versions:update-child-modules更新子pom的版本

      https://www.mojohaus.org/versions-maven-plugin/examples/update-child-modules.html

      【讨论】:

        【解决方案9】:
        <parent>
            <groupId>com.dummy.bla</groupId>
            <artifactId>parent</artifactId>
            <version>0.1-SNAPSHOT</version>     
         </parent>
        
         <groupId>com.dummy.bla.sub</groupId>
         <artifactId>kid</artifactId>
        

        你的意思是你想从B的pom的父块中删除版本,我认为你不能这样做,groupId,artifactId和version指定了父的pom坐标,你可以省略的是孩子的版本。

        【讨论】:

          猜你喜欢
          • 2020-06-27
          • 2017-02-22
          • 2020-12-28
          • 1970-01-01
          • 2011-12-23
          • 2016-04-11
          • 2010-11-03
          • 1970-01-01
          • 2020-10-18
          相关资源
          最近更新 更多