首页 文章

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

提问于
浏览
28

我有一组项目,他们都需要在构建期间运行相同系列的Maven插件执行 . 我想避免在每个项目中重新声明所有这些配置,因此我将它们全部继承自父pom“模板”项目,该项目仅包含那些插件执行(8种不同的mojos) . 但我希望这些插件执行只在子项目上运行,而不是在Maven构建期间在父项目上运行 .

我试图完成这四种不同的方式,每种方式都有我不喜欢的副作用 .

  • 在父pom的 build/plugins 元素中声明插件执行,并在父项目中使用properties-maven-plugin到turn on the skip properties on other plugins . 这没有 skip 属性 .

  • 在父pom的 build/pluginManagement 元素中声明插件执行 . 不幸的是,这需要我重新声明每个子项目的pom中的8个插件中的每个插件:

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

这太重复了,如果我需要更改模板pom中的插件,则会出现问题 .

  • 在父pom中的配置文件中声明插件执行,该配置文件由于缺少 nobuild.txt 文件(父pom中存在,因此插件不在那里执行)而激活:
<profiles>
    <profile>
        <activation>
            <file>
                <missing>nobuild.txt</missing>
            </file>
        </activation>
        <build>
            ....
        </build>
    </profile>
</profiles>

这在大多数情况下都有效,除了 missing 元素中的文件路径似乎基于当前工作目录而不是基于项目的基础 . 这打破了我希望能够做的一些多模块构建 . Edit: 澄清一下,父"template"项目实际上本身就是一个多模块项目中的模块,当我尝试例如在根上执行 mvn install 时,构建就会中断 . 项目结构如下:

+ job
|- job-core
|- job-template
|- job1                   inherits from job-template
|- job2                   inherits from job-template

那么,是否有另一种方法可以指定一堆Maven插件执行,这些执行可以在多个项目中重复使用(每个项目的poms中重复次数最少)?

5 回答

  • 1

    我最终编写了自己的插件,利用mojo-executor调用其他mojos . 这允许我1)集中构建配置和2)最小化在每个子项目中重复的配置量 .

    (如果您对所有这些的原因感到好奇:每个子项目都是一个将从命令行执行的作业 . 该构建设置一个调用者shell脚本并将其附加到构建中,以便将其检入我们的工件中存储库 . 稍后,部署脚本会将这些脚本下载到它们将运行的计算机上 . )

    模板项目的相关部分是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-plugin项目(job-maven-plugin) . 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>
    

    从模板项目中可以看出,我的插件中有多个mojos(每个阶段需要一些东西发生) . 例如,作业包mojo绑定到包阶段,并使用mojo-executor库运行另外两个mojos(只附加一些构建工件):

    /**
     * @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
            );
        }
    }
    

    然后,在子项目中,我只需要引用一次插件 . 在我看来,这比重复每个子项目中的每个幕后插件(不可接受地增加poms之间的耦合)更为可取 . 如果我想在将来向构建过程添加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>
    

    此外,整个multimodule目录结构现在看起来像这样:

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

    在我看来,这个解决方案并不是完全最优的,因为我现在将插件配置嵌入到一系列mojos而不是pom中,但它符合我的目标,即集中配置并最大限度地减少子项目poms之间的重复 .

    (最后一点说明:我刚刚发现maven-aggregate-plugin似乎允许在pom中对多个插件执行进行分组 . 这可能以稍微更理想的方式解决了问题,但我没心情重做最后一个几个小时的工作 . 虽然可能对别人有益 . )

  • 5

    我个人会寻求解决方案2.重复是最小的,你应该尽量避免使用配置文件,以避免必须开始记录哪些项目需要激活哪些配置文件 .

    只需做一个 mvn (clean) install 就可以正确构建一个项目 .

  • 0

    这是我在寻找同一问题的解决方案时发现的另一个选项here . 我在这里发布它是因为这已经是一个很好的选项集合 - 希望它可以帮助其他人不花费数小时来解决这个问题:

    鉴于插件可以选择跳过执行,可以在父pom(section)中打开该选项,并将“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>
    

    虽然我在第一次阅读时对此解决方案持怀疑态度,但它对我有用 - 至少对于汇编插件而言 .

  • 10

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

    这与@Timi建议的 <inherited>false</inherited> 方法一起非常好用

  • 2

    这是第五种方式 . 我认为它有最小的缺点:没有配置文件,没有自定义生命周期,在子POM中没有声明,没有插件的“跳过”要求 .

    https://stackoverflow.com/a/14653088/2053580复制 - 非常感谢end-user

    <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>
    

相关问题