10

我的父母 pom 中有以下个人资料

<profile>
    <id>P1</id>
    <activation>
        <activeByDefault>true</activeByDefault>
    </activation>
</profile>

<profile>
    <id>P2</id>
    <activation>
        <file>
            <exists>${project.basedir}/src/main/whatever</exists>
        </file>
    </activation>
</profile>

为什么 P1 在子 POM 中处于活动状态而 P2 不处于活动状态?

该目录${project.basedir}/src/main/whatever,在父项目中不存在,但在子项目中存在。

4

5 回答 5

26

配置文件P2未激活,因为exists即使目录${project.basedir}/src/main/whatever存在,其标记下的路径也不会解析为现有路径。如果将属性重写${project.basedir}${basedir},它应该激活P2配置文件。

这应该意味着它${project.basedir}不会像它应该那样解析到项目基目录。不过,这help:effective-pom表明确实如此。我已经报告了这个(MNG-5516)。

另外我认为如果 P2 激活,P1 将不会激活。

那是对的。引用文档activeByDefault

此配置文件(在此示例中为 P1)将自动对所有构建处于活动状态,除非使用上述方法之一激活同一 POM 中的另一个配置文件。当在命令行或通过其激活配置激活 POM 中的配置文件时,默认情况下处于活动状态的所有配置文件都会自动停用。

继承这个词让我感到困惑,因为“配置文件继承”适用于项目聚合,但不适用于项目继承

为了清楚起见,我模拟了这种情况。Empty pom 表示除了标准的模型、组、工件和版本标签之外它是空的。

简单场景

目录结构:

simple
 \-pom.xml

内容:

<profiles>
    <profile>
        <id>P1</id>
        <activation>
            <activeByDefault>true</activeByDefault>
        </activation>
    </profile>
    <profile>
        <id>P2</id>
        <activation>
            <file>
                <exists>${basedir}/dir/</exists>
            </file>
        </activation>
    </profile>
</profiles>

如果没有dir目录mvn help:all-profiles输出:

Profile Id: P1 (Active: true , Source: pom)
Profile Id: P2 (Active: false , Source: pom)

如果有dir目录mvn help:all-profiles输出:

Profile Id: P2 (Active: true , Source: pom)
Profile Id: P1 (Active: false , Source: pom)

项目继承

目录结构:

inheritance
 |--child
 |  \-pom.xml         // child pom
 \-pom.xml           // parent pom

子 pom 为空,而父 pom 具有简单场景中的配置文件。无论从目录输出inheritance/child/dir运行的目录是否存在:mvn help:all-profileschild

Profile Id: P1 (Active: false , Source: pom)
Profile Id: P2 (Active: false , Source: pom)

mvn help:effective-pom从目录运行时,child它显示配置文件确实没有被继承。它的行为与记录的一样:

POM 中合并的元素如下:

  • 依赖关系
  • 开发者和贡献者
  • 插件列表(包括报告)
  • 具有匹配 id 的插件执行
  • 插件配置
  • 资源

这里没有提到配置文件。

项目聚合

目录结构:

aggregation
 |--module
 |  \-pom.xml         // module pom
 \-pom.xml           // aggregator pom

模块 pom 为空,而聚合器 pom 具有简单场景中的配置文件。如果没有从目录输出aggregation/module/dir运行的目录:mvn help:all-profilesmodule

Profile Id: P1 (Active: true , Source: pom)
Profile Id: P2 (Active: false , Source: pom)

如果有从目录输出aggregation/module/dir运行的目录:mvn help:all-profilesmodule

Profile Id: P2 (Active: true , Source: pom)
Profile Id: P1 (Active: false , Source: pom)

mvn help:effective-pom从目录运行时,module它显示配置文件是继承的。这没有明确记录

项目继承

如果您有多个 Maven 项目,并且它们都有相似的配置,您可以通过提取这些相似的配置并创建一个父项目来重构您的项目。因此,您所要做的就是让您的 Maven 项目继承该父项目,然后这些配置将应用于所有项目。

笔记:

  • 这不适用于配置文件,因为它已经显示。
  • 从目录运行 maven 构建inheritance将只运行父构建。

项目聚合

如果您有一组一起构建或处理的项目,您可以创建一个父项目并让该父项目将这些项目声明为其模块。通过这样做,您只需构建父级,其余的将随之而来。

笔记:

  • 从目录运行 maven 构建aggregation将运行每个模块和聚合器的构建(实际顺序由 maven 基于不同标准确定)。

结论

配置文件可以全局定义,每个用户或每个项目。由于聚合项目是一起构建的(在同一个构建中),因此必须运行某种配置文件解析来计算活动项目。所以这是令人困惑的部分:

  • 当项目被继承时,配置文件不会 从父 pom 继承到子 pom
  • 当项目被聚合时,配置文件从聚合 pom 继承到模块 pom

使用 Maven 3.1.0 对此进行了测试。和 3.0.5。

于 2013-09-19T16:04:39.010 回答
10

只是为了澄清这一点,Maven Profiles 实际上是继承的。有关另一个 SO 问题的参考,请参阅:继承 Maven 配置文件。我已经在我的项目中成功继承了配置文件,不需要额外的工作。

至于原始问题,您在存在元素中定义了一个变量。根据文档

从 Maven 2.0.9 开始,可以对标签 和 进行插值。支持的变量是 ${user.home} 等系统属性和 ${env.HOME} 等环境变量。请注意,POM 本身中定义的属性和值在这里不能用于插值,例如上面的示例激活器不能使用 ${project.build.directory} 但需要硬编码路径目标。

所以,我从中得到的是 ${project.basedir} 不能使用并且不起作用。但是,如果您将其定义为环境变量,它将起作用。

我发现的一个警告是在父 pom 中<plugin-management>应该用于配置插件。但是,对于在配置文件中,我发现<plugin-management>不能使用它来使配置文件特定的配置起作用。

于 2013-12-30T21:01:57.163 回答
6

问题不在于继承,而在于插值(即支持哪些值${...}):基于文件的配置文件激活仅支持有限的插值:请参阅http://maven.apache.org/pom.html#Activation

所以${project.basedir}不支持,但仅支持${basedir}(和系统属性)。

有关更多详细信息,您可以查看模型构建算法:http ://maven.apache.org/ref/3.2.1/maven-model-builder/

完整的模型插值发生在配置文件激活后:因此,即使您的有效 pom 显示 的插值${project.basedir},当配置文件激活发生时,也不会计算该值。

在 Maven 3.2.2 中,对此有多项增强:http://jira.codehaus.org/browse/MNG-5590 中的文档,http : //jira.codehaus.org/browse/MNG-5608中的运行时警告和更有效的 pom 结果http://jira.codehaus.org/browse/MNG-5612

于 2014-03-23T15:55:31.163 回答
1

通常,Maven 配置文件不会被继承(请参阅http://jira.codehaus.org/browse/MNG-5127了解可能有用的讨论和博客文章链接)。我已经成功地做了这样的事情:

<!-- Parent -->
<profile>
    <id>P2</id>
    <activation>
        <file>
            <exists>${project.basedir}/src/main/whatever</exists>
        </file>
    </activation>
    <!-- all the things you want to define for the child POMs -->
</profile>

<!-- Child -->
<!-- Include only the activation block, which must match parent's exactly -->
<!-- Whatever is in the parent will be inherited -->
<profile>
    <id>P2</id>
    <activation>
        <file>
            <exists>${project.basedir}/src/main/whatever</exists>
        </file>
    </activation>
</profile>

另外我认为如果 P2 激活,P1 将不会激活。这是因为<activeByDefault>对于 P1 来说是正确的。在我看来,元素名称有点误导。“默认情况下活动”意味着“始终处于活动状态”,而它实际上意味着“仅当此 POM 中没有其他配置文件处于活动状态时才活动”。

以上是使用 Maven 3.0.x 发现的。

于 2013-09-18T14:06:14.473 回答
0

从具有基于文件的激活的第二个配置文件中删除 P2。

<profiles>
    <profile>
        <id>P1</id>
        <activation>
            <activeByDefault>true</activeByDefault>
        </activation>
    </profile>
    <profile>
        <id>P2</id>
        <activation>
            <file>
                <exists>${basedir}/dir/</exists>
            </file>
        </activation>
    </profile>
</profiles>
于 2014-11-14T06:44:47.700 回答