Hello,

Thanks Thomas for your extensive answer. But you seemed to focus only on
the first problem (which I had identified as potentially _not_ a bug).

What about the fact that m-compiler-p ignores the error returned by Javac
and allows the build to continue ?

Right now, I have a successful build (it's a demo, there is no test
defined) and there is just nothing working. I would be far more
comprehensive if the javac error was reported, the build failed and a quick
google search would pop the workaround (either proc:none or use
@AutoService) for that specific error.

WDYT ?

Thanks,

Sébastien Lesaint

2015-02-21 13:14 GMT+01:00 Thomas Broyer <t.bro...@gmail.com>:

> On Fri Feb 20 2015 at 21:11:14 Sébastien Lesaint <
> sebastien.lesa...@gmail.com> wrote:
>
> > Hello,
> >
> > I have been into annotation processing a lot for the past year and a half
> > and I am now going back to the basics so that I can share knowledge I
> > gathered.
> >
> > Doing so, I stumbled upon, again, a problem I had meet very early, for
> > which I had googled the solution, but this time I went deeper to figure
> out
> > what was really wrong.
> >
> > # the symptoms
> >
> > When writing an annotation processor and creating the associated
> > service-discovery file
> > "`META-INF/services/javax.annotation.processing.Processor" in a Maven
> > module, one needs to disable annotation processing completely (using
> > the <proc>none</proc> configuration option of the maven-compiler-plugin)
> > otherwise the module compilation succeeds but not a single .class file is
> > created.
> >
> > # how I investigated
> >
> > I compiled the module with the -X option, extracted the javac command
> line
> > and ran it by hand. I got the following compilation error:
> > error: Bad service configuration file, or exception thrown while
> > constructing Processor object: javax.annotation.processing.Processor:
> > Provider com.foo.BarProcessor not found
> >
> > The thing is, the com.foo.BarProcessor is the very processor I am
> compiling
> > (and the single .java file of the module).
> >
> > # what I found
> >
> > I went through the maven logs, spent some time thinking about it and
> > believe that we are facing one, maybe two bugs in the
> > maven-compiler-plugin:
> >
> > 1. Maven copies resources from the "src/main/resources" directory to the
> > "target/classes" directory
> > 2. the maven-compiler-plugin builds up a javac command line that
> specifies
> > the "target/classes" directory as a member on the classpath with the
> > argument "-classpath" (is that a bug ? there may be a good reason to do
> so
> > but in a basic jar module setup I can see any)
> >
>
> This is because of m-compiler-p's attempt at incremental compilation. It
> looks at all source files and if one doesn't have a corresponding *.class
> file or is newer then it adds it to the list of source files to recompile.
> Because those will likely reference other classes that might not have
> changed, target/classes is included in the classpath so that the
> already-compiled classes can be found.
>
> That said, incremental compilation is (was) kind-of broken, as it doesn't
> track class dependencies and won't recompile those classes that reference
> the classes that have changed. See
> https://cwiki.apache.org/confluence/display/MAVEN/Incremental+Builds for
> an
> example.
> If you ask me, m-compiler-p should just check whether "something" needs to
> be recompiled (which in itself is already error-prone, for many reasons
> [1]) and recompile everything.
> Actually, m-compiler-p 3.1+ should apparently behave that way by deleting
> all *.class files it had created in a previous run (unless you set
> useIncrementalCompilation=false [2]), so it shouldn't need target/classes
> to be part of the classpath, at least for this use-case of incremental
> compilation, but still includes it anyway.
> Takari has a new plugin (and lifecycle) that apparently does truly
> incremental compilation [3], by tracking class dependencies (when using JDT
> rather than javac). It'd still fail your use-case though IIUC, if it
> supported annotation processing through JDT (I haven't looked at how it
> handles incremental builds with javac).
>
> The other reason for target/classes to be in the classpath is so that
> annotation processors could find resources (let's not debate here whether
> it's a good idea or not). m-compiler-p developers can't seem to agree on
> what should be done: should m-compiler-p use -sourcepath sometimes [4] or
> always [5] ? Should target/classes be included in the sourcepath [6] ?
>
> [1] http://blog.ltgt.net/maven-is-broken-by-design/ (note: things have
> changed a bit since I wrote this; e.g. incremental build in m-compiler-p
> 3.1+, the Takari lifecycle, etc.)
> [2]
>
> https://maven.apache.org/plugins/maven-compiler-plugin/compile-mojo.html#useIncrementalCompilation
> [3] http://takari.io/2014/10/16/incremental-compilation.html
> [4] https://jira.codehaus.org/browse/MCOMPILER-26,
> https://jira.codehaus.org/browse/MCOMPILER-174
> [5] https://jira.codehaus.org/browse/MCOMPILER-98
> [6] https://jira.codehaus.org/browse/MCOMPILER-122
>
> 3. when run, javac finds a
> > "META-INF/services/javax.annotation.processing.Processor" file in the
> > classpath and looks for the specified processor "com.foo.BarProcessor "
> > 4. obviously, this processor can not be found, javac reports an error and
> > stops the compilation before it even started compiling anything (ence
> not a
> > single .class file in the target directory)
> > 5. the error ("error: Bad service configuration file, or exception thrown
> > while constructing Processor object: javax.annotation.processing.
> > Processor:
> > Provider com.foo.BarProcessorr not found") is ignored by the
> > maven-compiler-plugin that considers the compilation successful and the
> > maven build goes on (this is our big bug)
> >
> > # bonus
> >
> > Please note that this has pernicious side effects.
> >
> > Since the build is successful, the jar which is supposed to contain the
> > processor is created but only with the resources which means that it
> > contains the "META-INF/services/javax.annotation.processing.Processor"
> > file.
> >
> > Now, any module or project which has this jar file as a dependency will
> > produce 0 .class file. Their compilation classpath is "contaminated"
> with a
> > "META-INF/services/javax.annotation.processing.Processor which references
> > an non existent processor. Javac will therefor fail with the "Bad service
> > configuration file" and produces no .class file.
> >
> > # affected versions
> >
> > I tested this with Maven 3.1.1 & 3.2.5, maven-compiler-plugin 2.5, 3.1
> and
> > 3.2 and Oracle JDK 6, 7 & 8 on a ubuntu 64 bits machine. But, according
> to
> > the various posts, stackoverflow entries, etc. all around the web which
> > provide the <proc>none</proc> solution, it occurs on other setups.
> >
> > # conclusion
> >
> > I initially though I would file a bug in the maven-compiler-plugin JIRA
> but
> > it is unclear how I can create an account.
> >
>
> It's a known bug, opened for YEARS:
> https://jira.codehaus.org/browse/MCOMPILER-97
>
> Note that a workaround might be to generate the
> META-INF/services/javax.annotation.processor.Processor file using
> annotation processing ;-) using either
> com.google.auto.service:auto-service,
> org.kohsuke.metainf-services:metainf-services, or org.immutables:metainf
> (or anything similar)
>

Reply via email to