在父pom中定义Maven插件,但仅在子项目中调用插件



我有一组项目,它们在构建过程中都需要运行相同系列的Maven插件执行。我想避免在每个项目中重新声明所有这些配置,所以我让它们都继承自父pom"模板"项目,该项目只包含那些插件执行(8个不同的mojo)。但我希望在Maven构建期间,这些插件执行只在子项目上运行,而不在父项目上运行。

我尝试了四种不同的方式来实现这一点,每种方式都有我不喜欢的副作用。

  1. 在父pom的build/plugins元素中声明插件执行,并使用属性maven-plugin打开父项目中其他插件的skip属性。这不起作用,因为其中一个插件目标(maven依赖插件:构建类路径)没有skip属性。

  2. 在父pom的build/pluginManagement元素中声明插件执行。不幸的是,这需要我重新声明每个子项目的pom-like:的build/plugins元素中的八个插件中的每一个

    <plugin>
    <artifactId>maven-assembly-plugin</artifactId>
    </plugin>
    ...
    

    这太重复了,如果我需要更改模板pom中的插件,这会有问题。

  3. 在父pom中的配置文件中声明插件执行,该配置文件由nobuild.txt文件的lack激活(该文件确实存在于父pom,因此插件不会在那里执行):

    <profiles>
    <profile>
    <activation>
    <file>
    <missing>nobuild.txt</missing>
    </file>
    </activation>
    <build>
    ....
    </build>
    </profile>
    </profiles>
    

    除了missing元素中的文件路径似乎基于当前工作目录而不是项目basedir之外,这在大多数情况下都有效。这破坏了我希望能够进行的一些多模块构建。编辑:为了澄清,父"模板"项目本身就是多模块项目中的一个模块,例如,当我尝试在根上执行mvn install时,构建就会中断。项目结构看起来像:

    + job
    |- job-core
    |- job-template
    |- job1                   inherits from job-template
    |- job2                   inherits from job-template
    
  4. 设置自定义生命周期和打包。这似乎允许我将插件绑定到生命周期阶段,但不指定任何配置。

那么,有没有其他方法可以指定一组可以在多个项目中重用的Maven插件执行(在每个项目的pom中重复最少)?

这是第五种方法。我认为它有最小的缺点:没有概要文件,没有自定义生命周期,没有子POM中的声明,没有插件的"跳过"要求。

复制自https://stackoverflow.com/a/14653088/2053580--非常感谢最终用户!

<build>
<pluginManagement>
<plugins>
<plugin>
<!-- Main declaration and configuration of the plugin -->
<!-- Will be inherited by children -->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
<version>2.9.1</version>
<executions>
<execution>
<!--This must be named-->
<id>checkstyle</id>
<phase>compile</phase>
<goals>
<goal>check</goal>
</goals>
</execution>
</executions>
<!-- You may also use per-execution configuration block -->
<configuration...>
</plugin>
</plugins>
</pluginManagement>
<plugins>
<plugin>
<!-- This declaration makes sure children get plugin in their lifecycle -->
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-checkstyle-plugin</artifactId>
<!-- Configuration won't be propagated to children -->
<inherited>false</inherited>
<executions>
<execution>
<!--This matches and thus overrides execution defined above -->
<id>checkstyle</id>
<!-- Unbind from lifecycle for this POM -->
<phase>none</phase>
</execution>
</executions>
</plugin>
</plugins>
</build>

我最终编写了自己的插件,该插件利用mojo执行器来调用其他mojo。这使我能够1)集中构建配置,2)最小化每个子项目中重复的配置量。

(如果你对这一切的原因感到好奇:每个子项目都是一个将从命令行执行的作业。构建会设置一个调用程序外壳脚本,并将其附加到构建中,以便将其检查到我们的工件存储库中。部署脚本稍后会将这些脚本拖到它们将运行的机器上。)

模板项目pom:的相关部分

<project ...>
<parent> ... </parent>
<artifactId>job-template</artifactId>
<packaging>pom</packaging>
<name>job project template</name>
<build>
<pluginManagement>
<plugin>
<groupId>...</groupId>
<artifactId>job-maven-plugin</artifactId>
<executions>
<execution>
<id>generate-sources-step</id>
<goals><goal>job-generate-sources</goal></goals>
</execution>
<execution>
<id>package-step</id>
<goals><goal>job-package</goal></goals>
</execution>
... (a couple more executions) ...
</executions>
</plugin>
</pluginManagement>
</build>
</project>

不得不创建一个新的maven插件项目(job-maven插件)。Pom看起来像:

<project ...>
<parent> ... </parent>
<artifactId>job-maven-plugin</artifactId>
<packaging>maven-plugin</packaging>
<name>job maven executor plugin</name>
<dependencies>
<dependency>
<groupId>org.twdata.maven</groupId>
<artifactId>mojo-executor</artifactId>
<!-- version 1.5 supports Maven 2, while version 2.0 only supports Maven 3 -->
<version>1.5</version>
</dependency>
</dependencies>
</project>

正如你从模板项目中看到的,我的插件中有多个mojo(每个阶段需要一个)。例如,作业包mojo绑定到包阶段,并使用mojo执行器库来运行另外两个mojo(只附加一些构建工件):

/**
* @goal job-package
* @phase package
*/
public class PackageMojo extends AbstractMojo {
/**
* @parameter expression="${project}"
* @required
* @readonly
*/
protected MavenProject project;
/**
* @parameter expression="${session}"
* @required
* @readonly
*/
protected MavenSession session;
/**
* @component
* @required
*/
protected PluginManager pluginManager;
@Override
public void execute() throws MojoExecutionException, MojoFailureException {
ExecutionEnvironment environment = executionEnvironment(project, session, pluginManager);
// Attach script as a build artifact
executeMojo(
plugin(
groupId("org.codehaus.mojo"),
artifactId("build-helper-maven-plugin"),
version("1.7")
),
goal("attach-artifact"),
configuration(
element("artifacts",
element("artifact",
element("file", "${project.build.directory}/script.shl"),
element("type", "shl")
)
)
),
environment
);
// Zip up the jar and script as another build artifact
executeMojo(
plugin(
groupId("org.apache.maven.plugins"),
artifactId("maven-assembly-plugin"),
version("2.3")
),
goal("single"),
configuration(
element("descriptors",
element("descriptor", "${project.build.directory}/job/descriptor.xml")
)
),
environment
);
}
}

然后,在子项目中,我只需要引用一次插件。在我看来,这比在每个子项目中重复每个幕后插件要好得多(这会令人无法接受地增加pom之间的耦合)。如果我想在未来的构建过程中添加一个mojo执行,我只需要修改一个位置并增加一个版本号。儿童项目的pom看起来像:

<project ...>
<parent>
<groupId> ... </groupId>
<artifactId>job-template</artifactId>
<version> ... </version>
<relativePath>../job-template</relativePath>
</parent>
<artifactId>job-testjob</artifactId>
<name>test job</name>
<build>
<plugins>
<plugin>
<groupId> ... </groupId>
<artifactId>job-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>

此外,整个多模块目录结构现在看起来是这样的:

+- job
+- job-core
+- job-maven-plugin
+- job-template
+- job-testjob1               (inherits from job-template)
+- job-testjob2               (inherits from job-template)

在我看来,这个解决方案并不完全是最优的,因为我现在在一系列mojo中嵌入了插件配置,而不是pom,但它满足了我集中配置和最小化子项目pom之间重复的目标。

(最后一点注意:我刚刚发现了maven聚合插件,它似乎允许在pom中对多个插件执行进行分组。这可能以一种稍微更可取的方式解决了问题,但我没有心情重做最后几个小时的工作。这可能对其他人有益。)

就我个人而言,我会选择解决方案2。重复是最小的,如果可能的话,你应该尽量避免配置文件,以避免必须开始记录哪些配置文件需要为哪些项目激活。

一个项目应该能够通过简单地执行mvn (clean) install来正确构建。

这是我在寻找同一问题的解决方案时发现的另一个选项。我把它发布在这里是因为这已经是一个很好的选择集合了——希望它能帮助其他人不要花几个小时来解决这个问题:

假设插件可以选择跳过执行,则可以在父pom(部分)中打开该选项,并将"inherit"标志设置为false,这样它就不会传播到子插件:

<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<id>make-assembly</id>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
<inherited>true</inherited>
<configuration>
...
</configuration>
</execution>
</executions>
<!-- Skip plugin execution for parent pom but enable it for all children -->
<configuration>
<skipAssembly>true</skipAssembly>
</configuration>
<inherited>false</inherited>
</plugin>

当我第一次读到这个解决方案时,我对它持怀疑态度,但它对我有效——至少对汇编插件有效。

还有一个选项:您可以更改执行绑定到不存在的值(如never)的阶段,而不是使用"skip"属性。

这与@Timi 建议的<inherited>false</inherited>方法配合使用非常好

最新更新