在子模块上执行 Maven 插件目标,但不在父模块上执行

在多模块项目中,如何指定要在所有子模块中执行插件目标,而不是在父项目中执行插件目标?有 <pluginManagement>,但是它只定义了执行的配置——子模块仍然需要引用插件来执行目标:

[ ... ]然而,这只配置子元素中插件元素实际引用的插件

还有别的办法吗?

更新: 根据帕斯卡的建议,我已经试过了:

<!-- ... -->
<packaging>pom</packaging>
<modules>
<module>child</module>
</modules>


<build>
<plugins>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<executions>
<execution>
<phase>integration-test</phase>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<!-- ... -->

这仍将生成一个。Jar,即使 jar目标绑定到 integration-test阶段。

59369 次浏览

According to the Default Lifecycle Bindings, the bindings for a packaging pom are:

Default Lifecycle Bindings - Packaging pom

package       site:attach-descriptor
install       install:install
deploy        deploy:deploy

So if your parent POM has a <packaging>pom<packaging> (this should be the case as pointed out in a comment) and if you bind your plugins to other phases than those above (see the Lifecycle Reference for a comprehensive list), they won't be executed during the build of the parent POM.

(EDIT: My initial answer is just wrong. If you bind a plugin goal to a particular phase, it will be triggered during that phase, regardless of the packaging of the project. The Default Lifecycle Bindings don't have anything to do with that, they are just default lifecycle bindings. All what matters is if the phase to which the plugin is bound is part of the build lifecyle.)

As you pointed out, you can use the pluginManagement in the parent pom for the configuration of the plugin but if you really want to execute a plugin goal in children modules and not in the parent (you might have good reasons to do this but most of time, plugins won't have much effet on a module with a pom packaging that doesn't have any content), you'll have to reference plugins in the plugins element in the children.

Applied to your example, the parent pom.xml could define the following specifications:

<project>
<packaging>pom</packaging>
...
<modules>
<module>child</module>
</modules>
...
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>2.2</version>
<executions>
<execution>
<id>my-execution-id</id>
<phase>integration-test</phase>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
</plugin>
...
</plugins>
</pluginManagement>
</build>
...
</project>

And in every child pom.xml, only the following is required:

<project>
...
<build>
...
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
</plugin>
</plugins>
...
</build>
</project>

The described solution with plugin management is certainly correct, but in certain cases it does not fit. Suppose you would like to run several jar:jar goals in the child module each configured with its own settings (configuration) per execution. Or in general, when you don't want to force child poms to explicitly trigger the plugin(s).

In this case the solution that worked for me was to define the executions in the parent pom under a specific profile, and have it activated only in child poms for example by checking for existence of some file or property:

<profile>
<id>generate-dc</id>
<activation>
<file>
<exists>src/main/assembly/some.xml</exists>
</file>
</activation>

Then plugins won't be executed in the parent, but will be executed in all children if those contain the file, or set some property.

I had a similar requirement to run some plugins in the child but not the parent POM. i achieved this by stating <skip>true</skip> in the parent POM.

The parent pom entry is below:

<plugin>
<groupId>eviware</groupId>
<artifactId>maven-soapui-plugin</artifactId>
<version>4.0.0</version>
<inherited>false</inherited>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.8.2</version>
</dependency>
</dependencies>
<configuration>
<skip>true</skip>
</configuration>
</plugin>

The child project pom entry is below

<plugins>
<plugin>
<groupId>eviware</groupId>
<artifactId>maven-soapui-plugin</artifactId>
<version>4.0.0</version>
<configuration>
<settingsFile>site-service-web/src/test/soapui/soapui-settings.xml</settingsFile>
<projectFile>site-service-web/src/test/soapui/PodifiSite-soapui-project.xml</projectFile>
<outputFolder>site-service-web/target/surefire-reports</outputFolder>
<junitReport>true</junitReport>
<exportwAll>true</exportwAll>
<printReport>true</printReport>
</configuration>
</plugin>
</plugins>

I tried the answer from Pascal but it did not work for me. The plugins referenced in the child pom did not execute, I'm assuming because they did not have a build phase binding.

The post here describes a solution that works by binding the plugins to execution ids and build phases: How to override default binding to phase of a Maven plugin

I'd recommend that to anyone else trying to get this working.

Use <inherited>false</inherited> under the plugins section in the parent project.

Plese refer to this page for more information.

This below config worked for me. Add the plugin in both the parent and child pom.

Parent :

<build>
<plugins>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<inherited>true</inherited>
<executions>
<execution>
<phase>integration-test</phase>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
<configuration>
<skip>true</skip>
</configuration>
</plugin>
</plugins>
</build>

Child

<build>
<plugins>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<inherited>false</inherited>
<executions>
<execution>
<phase>integration-test</phase>
<goals>
<goal>jar</goal>
</goals>
</execution>
</executions>
<configuration>
<skip>false</skip>
</configuration>
</plugin>
</plugins>
</build>