Uploaded image for project: 'Maven Compiler Plugin'
  1. Maven Compiler Plugin
  2. MCOMPILER-433

mvn clean compile test compiles the source files twice

    XMLWordPrintableJSON

Details

    • Bug
    • Status: Closed
    • Major
    • Resolution: Fixed
    • 3.8.1
    • 3.11.0
    • None

    Description

      When one invokes mvn clean compile test, the default-compile execution runs twice.
      This is because org.apache.maven.lifecycle.internal.DefaultLifecycleExecutionPlanCalculator#calculateMojoExecutions() (which hasn't changed in 6 years) collects the list of mojo executions in a list, and for each phase on the command-line it adds the mojo executions for that phase and its dependencies, even if some executions already exist in the list. E.g.

      mojoExecutions = {java.util.ArrayList}  size = 8
       0 = {org.apache.maven.plugin.MojoExecution} "org.apache.maven.plugins:maven-clean-plugin:2.5:clean {execution: default-clean}"
       1 = {org.apache.maven.plugin.MojoExecution} "org.apache.maven.plugins:maven-resources-plugin:2.6:resources {execution: default-resources}"
       2 = {org.apache.maven.plugin.MojoExecution} "org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile {execution: default-compile}"
       3 = {org.apache.maven.plugin.MojoExecution} "org.apache.maven.plugins:maven-resources-plugin:2.6:resources {execution: default-resources}"
       4 = {org.apache.maven.plugin.MojoExecution} "org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile {execution: default-compile}"
       5 = {org.apache.maven.plugin.MojoExecution} "org.apache.maven.plugins:maven-resources-plugin:2.6:testResources {execution: default-testResources}"
       6 = {org.apache.maven.plugin.MojoExecution} "org.apache.maven.plugins:maven-compiler-plugin:3.8.1:testCompile {execution: default-testCompile}"
       7 = {org.apache.maven.plugin.MojoExecution} "org.apache.maven.plugins:maven-surefire-plugin:2.12.4:test {execution: default-test}"
      

       

      The second execution of maven-compiler-plugin version 3.8.0 used to check that the sources haven't changed and do nothing. But that check was wrong, because it didn't check any class files, and MCOMPILER-349 replaced it with another check that is also wrong, because it (org.apache.maven.plugin.compiler.AbstractCompilerMojo#isDependencyChanged()) checks for changes since the start of the build in all the classes on the module's classpath, including target/classes.
      This means the second execution of maven-compiler-plugin verison 3.8.1 deletes all the .class files from target/classes. It does not delete the files generated by annotation processors in target/generated-sources/annotations, but it also doesn't add them to the Javac sources parameter because org.apache.maven.plugin.compiler.AbstractCompilerMojo#getCompileSources() ignores the generated sources directory:

      compileSourceRoots = {java.util.ArrayList}  size = 3
       0 = "/home/dan/Work/maven-compiler-test/src/main/java"
       1 = "/home/dan/Work/maven-compiler-test/target/generated-sources/annotations"
       2 = "/home/dan/Work/maven-compiler-test/target/generated-sources/annotations"
      
      sources = {java.util.HashSet}  size = 2
       0 = {java.io.File} "/home/dan/Work/maven-compiler-test/src/main/java/ProtoStreamContextInitializer.java"
       1 = {java.io.File} "/home/dan/Work/maven-compiler-test/src/main/java/A.java"
      

       

      We have an annotation processor that tries to be smart and doesn't overwrite its generated Java source files if they already exists and they have the correct checksum. But because the generated file isn't written, it is not added to Javac's sources, and Javac does not compile it to a .class file. I haven't tested it, but I believe the same problem appears if the source files were generated e.g. by another Maven plugin or by an Ant script in the generate-sources phase.

       

      I believe the maven-core behaviour won't change any time soon (and in fact some users may depend on the duplicate executions). Instead org.apache.maven.plugin.compiler.AbstractCompilerMojo#isDependencyChanged() needs to be fixed to avoid recompilation when runs the second time.

      Attachments

        Issue Links

          Activity

            People

              gnodet Guillaume Nodet
              dan.berindei Dan Berindei
              Votes:
              1 Vote for this issue
              Watchers:
              1 Start watching this issue

              Dates

                Created:
                Updated:
                Resolved: