Maven Compiler Plugin
  1. Maven Compiler Plugin
  2. MCOMPILER-135

Passing multiple parameters to Java 6 annotation processors with javac does not work

    Details

    • Type: Bug Bug
    • Status: Closed Closed
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: 2.3.1
    • Fix Version/s: 2.4
    • Labels:
      None
    • Environment:
      JDK 1.6, Maven 2.2.1, Maven-Compiler-Plugin 2.3.1, Windows
    • Number of attachments :
      3

      Description

      I have an annotation processor that supports multiple parameters and I have found that there is no way to set more than one of them at any given time from the Maven Compiler Plugin,

      Here's my setup.

       
      <plugin>
          <inherited>true</inherited>
          <groupId>org.apache.maven.plugins</groupId>
          <artifactId>maven-compiler-plugin</artifactId>
          <version>2.3.1</version>
          <configuration>
              <source>1.6</source>
              <target>1.6</target>
              <compilerArgument>-AaddResDir=src/main/webapp -Averbose=true</compilerArgument>
          </configuration>
      </plugin>
      

      Javac needs the parameters added as separate Strings

      [ ... , "-AaddResDir=src/main/webapp", "-Averbose=true"]

      but the Compiler Plugin generates this code:

      [ ... , "-AaddResDir=src/main/webapp -Averbose=true"]

      which Javac will parse as

      key:"addResDir" value="src/main/webapp -Averbose=true"

      The map version "<compilerArguments>" is of no help either, because this

      <Averbose>true</Averbose>
      <AaddResDir>src/main/webapp</AResDir>

      will generate the output

      [... , "-Averbose", "true", "-AaddResDir", "src/main/webapp"]

      while this

      <Averbose=true />
      <AaddResDir=src/main/webapp />

      is not well-formed XML.

      Stepping through the compiler argument generation with the debugger I have not found a way to post-process the arguments, so please add a way to support multiple APT parameters because this is a major show-stopper.

      1. AbstractCompilerMojo.java.2.patch
        2 kB
        Sean Patrick Floyd
      2. AbstractCompilerMojo.java.3.patch
        3 kB
        Sean Patrick Floyd
      3. AbstractCompilerMojo.java.patch
        1 kB
        Sean Patrick Floyd

        Issue Links

          Activity

          Hide
          Sean Patrick Floyd added a comment -

          Here is a Patch for org.apache.maven.plugin.AbstractCompilerMojo that enables the following code:

          <compilerArguments>
              <AaddResDir>src/main/webapp</AaddResDir>
              <Averbose>true</Averbose>
          </compilerArguments>

          There should probably be a check whether source version is at least 1.6 and compiler id is javac, though.

          Show
          Sean Patrick Floyd added a comment - Here is a Patch for org.apache.maven.plugin.AbstractCompilerMojo that enables the following code: <compilerArguments> <AaddResDir>src/main/webapp</AaddResDir> <Averbose> true </Averbose> </compilerArguments> There should probably be a check whether source version is at least 1.6 and compiler id is javac, though.
          Hide
          Pascal Thivent added a comment - - edited

          Looks similar to MCOMPILER-130 (but the map syntax won't help indeed).

          Show
          Pascal Thivent added a comment - - edited Looks similar to MCOMPILER-130 (but the map syntax won't help indeed).
          Hide
          Per Hedman added a comment -

          I believe that this workaround could work, add this to the configuration:
          <fork>true</fork>
          and change this:
          <compilerArgument>-AaddResDir=src/main/webapp" "-Averbose=true</compilerArgument>
          but I can't confirm right now. I only have 1.5 at home.

          It's related to MCOMPILER-130

          Show
          Per Hedman added a comment - I believe that this workaround could work, add this to the configuration: <fork>true</fork> and change this: <compilerArgument>-AaddResDir=src/main/webapp" "-Averbose=true</compilerArgument> but I can't confirm right now. I only have 1.5 at home. It's related to MCOMPILER-130
          Hide
          Sean Patrick Floyd added a comment - - edited

          Per: yes, I thought of that also, but it would be an ugly option. For one thing: it would not allow me to debug the annotation processor using mvndebug compile (not without lots of additional configuration anyway)

          Show
          Sean Patrick Floyd added a comment - - edited Per: yes, I thought of that also, but it would be an ugly option. For one thing: it would not allow me to debug the annotation processor using mvndebug compile (not without lots of additional configuration anyway)
          Hide
          Sean Patrick Floyd added a comment -

          Here is a second patch that introduces a new map-based parameter

          <annotationProcessorArguments>
              <key1>value</key1>
              <key2>value2</key2>
          </annotationProcessorArguments>

          .

          This would probably be better as it couldn't break existing functionality

          Show
          Sean Patrick Floyd added a comment - Here is a second patch that introduces a new map-based parameter <annotationProcessorArguments> <key1>value</key1> <key2>value2</key2> </annotationProcessorArguments> . This would probably be better as it couldn't break existing functionality
          Hide
          Per Hedman added a comment - - edited

          That could work very well. I would like to propose a version that looks something like this:

          <compilerArgumentMap>
           <key1>value1</key1>
           <key2>value2</key2>
          <compilerArgumentMap>
          

          would even work with other compilers than javac, and is none-version specific.

          Show
          Per Hedman added a comment - - edited That could work very well. I would like to propose a version that looks something like this: <compilerArgumentMap> <key1> value1 </key1> <key2> value2 </key2> <compilerArgumentMap> would even work with other compilers than javac, and is none-version specific.
          Hide
          Sean Patrick Floyd added a comment - - edited

          Per: That functionality already exists:

          <compilerArguments>
           <key1>value1</key1>
           <key2>value2</key2>
          <compilerArguments>

          But as I wrote above, this is internally mapped to

          ["-key1", "value1", "-key2", "value2"]

          instead of

          ["-key1=value1", "-key2=value2"]

          , which is the format needed for apt parameters. Most other compiler arguments need the other syntax, though.

          So there's basically two ways to handle this: either check the existing map for parameters starting with a capital A (and risk breaking functionality where some compiler relies on a parameter starting with a capital A) or add a new variable that's dedicated to apt parameters (I have submitted two patches to cover these two approaches)

          Show
          Sean Patrick Floyd added a comment - - edited Per: That functionality already exists: <compilerArguments> <key1>value1</key1> <key2>value2</key2> <compilerArguments> But as I wrote above, this is internally mapped to [ "-key1" , "value1" , "-key2" , "value2" ] instead of [ "-key1=value1" , "-key2=value2" ] , which is the format needed for apt parameters. Most other compiler arguments need the other syntax, though. So there's basically two ways to handle this: either check the existing map for parameters starting with a capital A (and risk breaking functionality where some compiler relies on a parameter starting with a capital A) or add a new variable that's dedicated to apt parameters (I have submitted two patches to cover these two approaches)
          Hide
          Per Hedman added a comment - - edited

          Missed that, then maybe:

          <compilerArgumentKeyValue>
          <key1>value1</key1>
          <key2>value2</key2>
          <compilerArgumentKeyValue>
          

          that could internally map it to:

          "-key1=value1", "-key2=value2"
          

          That wouldn't break any old functionality and still not be specific to the annotation processor...

          Show
          Per Hedman added a comment - - edited Missed that, then maybe: <compilerArgumentKeyValue> <key1> value1 </key1> <key2> value2 </key2> <compilerArgumentKeyValue> that could internally map it to: "-key1=value1" , "-key2=value2" That wouldn't break any old functionality and still not be specific to the annotation processor...
          Hide
          Milos Kleint added a comment -

          from the usability point of view it's confusing to have both <compilerArguments> and <compilerArgumentKeyValue> as plugin parameters.. I would be inclined to define annotation processing specific parameter, than it's more clear which one to use in the given scenario..

          Show
          Milos Kleint added a comment - from the usability point of view it's confusing to have both <compilerArguments> and <compilerArgumentKeyValue> as plugin parameters.. I would be inclined to define annotation processing specific parameter, than it's more clear which one to use in the given scenario..
          Hide
          Sean Patrick Floyd added a comment -

          Milos, exactly. And Per: what's wrong with having annotation processing specific parameters? We already have the following two:

          http://maven.apache.org/plugins/maven-compiler-plugin/compile-mojo.html#annotationProcessors
          http://maven.apache.org/plugins/maven-compiler-plugin/compile-mojo.html#proc

          And I think it makes sense to separate different types of functionality

          Show
          Sean Patrick Floyd added a comment - Milos, exactly. And Per: what's wrong with having annotation processing specific parameters? We already have the following two: http://maven.apache.org/plugins/maven-compiler-plugin/compile-mojo.html#annotationProcessors http://maven.apache.org/plugins/maven-compiler-plugin/compile-mojo.html#proc And I think it makes sense to separate different types of functionality
          Hide
          Per Hedman added a comment -

          The KeyValue version could fix other problems with the compiler-plugin, MCOMPILER-130, and still not be annotation specific, or even compiler-specific. IMHO

          Show
          Per Hedman added a comment - The KeyValue version could fix other problems with the compiler-plugin, MCOMPILER-130 , and still not be annotation specific, or even compiler-specific. IMHO
          Hide
          Sean Patrick Floyd added a comment -

          Per, for MCOMPILER-130, the existing functionality works (using the map version). It's probably just a question of updating documentation. For my problem no workaround exists (apart from using fork). And introducing a new map that would solve both of our problems would be a strange hack, because the parameters need to be assembled in different ways. The plugin would need to know about the -A notation anyway, so why not make it explicit?

          Of course it would be more elegant to send a map to the individual compilers and let them assemble the parameters themselves, but that would require a complete re-write.

          Show
          Sean Patrick Floyd added a comment - Per, for MCOMPILER-130 , the existing functionality works (using the map version). It's probably just a question of updating documentation. For my problem no workaround exists (apart from using fork). And introducing a new map that would solve both of our problems would be a strange hack, because the parameters need to be assembled in different ways. The plugin would need to know about the -A notation anyway, so why not make it explicit? Of course it would be more elegant to send a map to the individual compilers and let them assemble the parameters themselves, but that would require a complete re-write.
          Hide
          Per Hedman added a comment -

          The plugin would need to know about the -A notation anyway, so why not make it explicit?

          Sean Patrick, why does the plugin need to know the -A notation? Isn't it just an argument like "-verbose=true", but with "-Averbose=true" that's sent to the compiler, or what am I missing?

          Is this the correct forum for these kinds of questions? Or should this be discussed in another venue? newbie codehaus:er

          Show
          Per Hedman added a comment - The plugin would need to know about the -A notation anyway, so why not make it explicit ? Sean Patrick, why does the plugin need to know the -A notation? Isn't it just an argument like "-verbose=true", but with "-Averbose=true" that's sent to the compiler, or what am I missing? Is this the correct forum for these kinds of questions? Or should this be discussed in another venue? newbie codehaus:er
          Hide
          Sean Patrick Floyd added a comment -

          Per: have a look at

          javac -help
          Usage: javac <options> <source files>
          where possible options include:
            -g                         Generate all debugging info
            -g:none                    Generate no debugging info
            -g:{lines,vars,source}     Generate only some debugging info
            -nowarn                    Generate no warnings
            -verbose                   Output messages about what the compiler is doing
            -deprecation               Output source locations where deprecated APIs are used
            -classpath <path>          Specify where to find user class files and annotation processors
            -cp <path>                 Specify where to find user class files and annotation processors
            -sourcepath <path>         Specify where to find input source files
            -bootclasspath <path>      Override location of bootstrap class files
            -extdirs <dirs>            Override location of installed extensions
            -endorseddirs <dirs>       Override location of endorsed standards path
            -proc:{none,only}          Control whether annotation processing and/or compilation is done.
            -processor <class1>[,<class2>,<class3>...]Names of the annotation processors to run; bypasses default discovery process
            -processorpath <path>      Specify where to find annotation processors
            -d <directory>             Specify where to place generated class files
            -s <directory>             Specify where to place generated source files
            -implicit:{none,class}     Specify whether or not to generate class files for implicitly referenced files
            -encoding <encoding>       Specify character encoding used by source files
            -source <release>          Provide source compatibility with specified release
            -target <release>          Generate class files for specific VM version
            -version                   Version information
            -help                      Print a synopsis of standard options
            -Akey[=value]              Options to pass to annotation processors
            -X                         Print a synopsis of nonstandard options
            -J<flag>                   Pass <flag> directly to the runtime system
          

          You can see that almost all parameters are either of the form "-parameter" or "-parameter value" (your example "-verbose=true" throws an error, the usage is "-verbose"). There are only a few exceptions to this rule, and -Akey=value is one of them. Some of the other exceptions are already handled (like proc:).

          Show
          Sean Patrick Floyd added a comment - Per: have a look at javac -help Usage: javac <options> <source files> where possible options include: -g Generate all debugging info -g:none Generate no debugging info -g:{lines,vars,source} Generate only some debugging info -nowarn Generate no warnings -verbose Output messages about what the compiler is doing -deprecation Output source locations where deprecated APIs are used -classpath <path> Specify where to find user class files and annotation processors -cp <path> Specify where to find user class files and annotation processors -sourcepath <path> Specify where to find input source files -bootclasspath <path> Override location of bootstrap class files -extdirs <dirs> Override location of installed extensions -endorseddirs <dirs> Override location of endorsed standards path -proc:{none,only} Control whether annotation processing and/or compilation is done. -processor <class1>[,<class2>,<class3>...]Names of the annotation processors to run; bypasses default discovery process -processorpath <path> Specify where to find annotation processors -d <directory> Specify where to place generated class files -s <directory> Specify where to place generated source files -implicit:{none,class} Specify whether or not to generate class files for implicitly referenced files -encoding <encoding> Specify character encoding used by source files -source <release> Provide source compatibility with specified release -target <release> Generate class files for specific VM version -version Version information -help Print a synopsis of standard options -Akey[=value] Options to pass to annotation processors -X Print a synopsis of nonstandard options -J<flag> Pass <flag> directly to the runtime system You can see that almost all parameters are either of the form "-parameter" or "-parameter value" (your example "-verbose=true" throws an error, the usage is "-verbose"). There are only a few exceptions to this rule, and -Akey=value is one of them. Some of the other exceptions are already handled (like proc: ).
          Hide
          Per Hedman added a comment -

          Sean Patrick: I understand what you mean, but I was thinking of

          javac -X
          
          -Xlint                     Enable recommended warnings
            -Xlint:{all,deprecation,unchecked,fallthrough,path,serial,finally,-deprecation,-unchecked,-fallthrough,-path,-serial,-finally}Enable or disable specific warnings
            -Xbootclasspath/p:<path>   Prepend to the bootstrap class path
            -Xbootclasspath/a:<path>   Append to the bootstrap class path
            -Xbootclasspath:<path>     Override location of bootstrap class files
            -Djava.ext.dirs=<dirs>     Override location of installed extensions
            -Djava.endorsed.dirs=<dirs>Override location of endorsed standards path
            -Xmaxerrs <number>         Set the maximum number of errors to print
            -Xmaxwarns <number>        Set the maximum number of warnings to print
            -Xstdout <filename>        Redirect standard output
          

          And then you could get support for more exotic arguments for the compiler, and not just the javac compiler arguments.

          Show
          Per Hedman added a comment - Sean Patrick: I understand what you mean, but I was thinking of javac -X -Xlint Enable recommended warnings -Xlint:{all,deprecation,unchecked,fallthrough,path,serial, finally ,-deprecation,-unchecked,-fallthrough,-path,-serial,- finally }Enable or disable specific warnings -Xbootclasspath/p:<path> Prepend to the bootstrap class path -Xbootclasspath/a:<path> Append to the bootstrap class path -Xbootclasspath:<path> Override location of bootstrap class files -Djava.ext.dirs=<dirs> Override location of installed extensions -Djava.endorsed.dirs=<dirs>Override location of endorsed standards path -Xmaxerrs <number> Set the maximum number of errors to print -Xmaxwarns <number> Set the maximum number of warnings to print -Xstdout <filename> Redirect standard output And then you could get support for more exotic arguments for the compiler, and not just the javac compiler arguments.
          Hide
          Sean Patrick Floyd added a comment -

          OK now I see what you mean. What a mess. Maybe it would be best to introduce an array parameter, as an array is what's passed to the compiler anyway. That way we could catch all kinds of arguments. Something like this:

          <arguments>
              <argument>-Xmaxerrs</argument>
              <argument>100</argument>
              <argument>-Akey1=value1</argument>
              <argument>-Akey2=value2</argument>
          </arguments>
          

          (Inspired by exec:java)

          Show
          Sean Patrick Floyd added a comment - OK now I see what you mean. What a mess. Maybe it would be best to introduce an array parameter, as an array is what's passed to the compiler anyway. That way we could catch all kinds of arguments. Something like this: <arguments> <argument>-Xmaxerrs</argument> <argument>100</argument> <argument>-Akey1=value1</argument> <argument>-Akey2=value2</argument> </arguments> (Inspired by exec:java )
          Hide
          Sean Patrick Floyd added a comment -

          This third patch uses a Properties object.

          Usage:

          <additionalCompilerArguments>
              <property> <name>-Akey=value</name> </property>
              <property> <name>-verbose</name> </property>
              <property> <name>-Xmaxerrs</name> <value>1000</value> </property>
          </additionalCompilerArguments> 
          

          This is the most flexible approach and it should be able to support almost all kinds of parameters.

          Show
          Sean Patrick Floyd added a comment - This third patch uses a Properties object. Usage: <additionalCompilerArguments> <property> <name>-Akey=value</name> </property> <property> <name>-verbose</name> </property> <property> <name>-Xmaxerrs</name> <value>1000</value> </property> </additionalCompilerArguments> This is the most flexible approach and it should be able to support almost all kinds of parameters.
          Hide
          Per Hedman added a comment -

          This third patch seems flexible and interesting. I will run some basic scenarios through the patch and see if there is anything that we have missed...

          Show
          Per Hedman added a comment - This third patch seems flexible and interesting. I will run some basic scenarios through the patch and see if there is anything that we have missed...
          Hide
          Jesse Glick added a comment -

          By the way, -Akey=value notation is one of the standard options (not -X...) that all command-line Java compilers (as of JSR 269) are expected to interpret, not just javac, so it is quite appropriate for a mojo supporting multiple compilers to have dedicated knowledge of this syntax.

          Show
          Jesse Glick added a comment - By the way, -Akey=value notation is one of the standard options (not -X... ) that all command-line Java compilers (as of JSR 269) are expected to interpret, not just javac, so it is quite appropriate for a mojo supporting multiple compilers to have dedicated knowledge of this syntax.
          Hide
          Robert Scholte added a comment -

          Fixed in rev. 1162905 with an integration-test.
          After reading all comments I believe it is not necessary to add a new parameter. It is just another compilerArgument, where the key and value are separated by an '='-sign.

          Show
          Robert Scholte added a comment - Fixed in rev. 1162905 with an integration-test. After reading all comments I believe it is not necessary to add a new parameter. It is just another compilerArgument, where the key and value are separated by an '='-sign.

            People

            • Assignee:
              Robert Scholte
              Reporter:
              Sean Patrick Floyd
            • Votes:
              4 Vote for this issue
              Watchers:
              6 Start watching this issue

              Dates

              • Created:
                Updated:
                Resolved: