Maarten Mulders created MNG-7163:
------------------------------------

             Summary: Aggregating Mojo re-executes goals for child modules that 
are already executed
                 Key: MNG-7163
                 URL: https://issues.apache.org/jira/browse/MNG-7163
             Project: Maven
          Issue Type: Bug
          Components: Plugins and Lifecycle
         Environment: Maven 4.0.0-alpha-1-SNAPSHOT
            Reporter: Maarten Mulders


h3. Background

In MNG-6566, we fixed the following scenario:
 * an invocation of Maven with for example {{compile package}},
 * while the project declares a plugin goal in its build,
 * that requires a fork of the {{compile}} goal.

In that scenario, the {{compile}} goal would run twice: once because of the 
{{package}} goal that was in the CLI invocation, once because the plugin 
requires it.
h3. Context

It turns out that this fix is not working for multi-module builds. Consider a 
project structure like this, where
 * the {{javadoc:aggregate-jar}} is bound to the {{package}} phase of the root 
module,
 * the root module declares {{module-a}} and {{module-b}} as its child modules.

{code:java}
.
├── module-a
│   ├── pom.xml
│   └── src
├── module-b
│   ├── pom.xml
│   └── src
└── pom.xml
{code}
Invoking {{mvn clean package}} will cause the following to happen:
{code:java}
>>>> module-a <<<<
clean                   @ module-a
compile                 @ module-a
jar                     @ module-a
>>>> module-b <<<<
clean                   @ module-b
compile                 @ module-b
jar                     @ module-b
>>>> parent <<<<
clean                   @ parent
javadoc:aggregate-jar   @ parent (starts forking)
> compile                       @ module-a
> compile                       @ module-b
javadoc:aggregate-jar   @ parent
{code}
(Aside: although {{clean}} may not be necessary, it's still a common thing to 
do; leaving clean out of the invocation does not fundamentally change the 
observation below)
h3. Bug

Running {{compile}} on {{module-a}} and {{module-b}} as part of the 
{{aggregate-jar}} forking is not necessary, as that has been done just before 
{{aggregate-jar}} started.

Of course, the Maven Compiler Plugin is smart enough to see that the source 
code hasn't changed since the class files were written, and it will log 
"Nothing to compile - all classes are up to date". But this is only an example, 
and other plugins may not be so smart.
h3. Considerations

For many situations, a "to be forked" goal ({{compile}}, in the above example) 
that was already executed can be safely skipped as part of the "forking" goal 
({{aggregate-jar}}, in the above example). But this may not always be the case:
h4. Edge case(s)

If the order of goals would've been {{mvn package clean}}, the execution plan 
would look like this:
{code:java}
>>>> module-a <<<<
compile                 @ module-a
jar                     @ module-a
clean                   @ module-a
>>>> module-b <<<<
compile                 @ module-b
jar                     @ module-b
clean                   @ module-b
>>>> parent <<<<
javadoc:aggregate-jar   @ parent (starts forking)
> compile                       @ module-a
> compile                       @ module-b
javadoc:aggregate-jar   @ parent
clean                   @ parent
{code}
Removing the "to be forked" goals that had already been executed would mean 
removing the second {{compile}} on both {{module-a}} and {{module-b}}. As a 
result, the {{aggregate-jar}} goal would fail (no classes present). This is of 
course an insane example, but maybe there are more situations where one of the 
goals on the child modules could alter or even destroy a prerequisite of the 
aggregating/forking mojo? I am not sure if we should account for that / support 
that.

I will attach an example project later.



--
This message was sent by Atlassian Jira
(v8.3.4#803005)

Reply via email to