Uploaded image for project: 'Maven'
  1. Maven
  2. MNG-7163

Aggregating Mojo re-executes goals for child modules that are already executed

    XMLWordPrintableJSON

Details

    • Bug
    • Status: Open
    • Major
    • Resolution: Unresolved
    • None
    • None
    • Plugins and Lifecycle
    • None
    • Maven 4.0.0-alpha-1-SNAPSHOT

    Description

      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.

      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.
      .
      ├── module-a
      │   ├── pom.xml
      │   └── src
      ├── module-b
      │   ├── pom.xml
      │   └── src
      └── pom.xml
      

      Invoking mvn clean package will cause the following to happen:

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

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

      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.

      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:

      Edge case(s)

      If the order of goals would've been mvn package clean, the execution plan would look like this:

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

      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.

      Attachments

        1. mng7163.zip
          4 kB
          Maarten Mulders

        Issue Links

          Activity

            People

              Unassigned Unassigned
              mthmulders Maarten Mulders
              Votes:
              0 Vote for this issue
              Watchers:
              3 Start watching this issue

              Dates

                Created:
                Updated: