3

我正在使用 maven 3.0.3 和 Java7。

我有一个 AnnotationProcessor,它应该解析src/main/java( not src/test/java ) 中的带注释的 java 文件并为 JUnit-Tests 生成 Helper-Classes。这些 Helper-Class 应该存储在其中,target/generated-test-sources/test-annotations因为它们使用仅在测试范围内可用的库。(注意:只要此依赖项不在测试范围内,一切都会正常工作,但一旦构建失败。它肯定只需要在测试范围内/在单元测试和测试类的编译期间。)

我尝试了几种配置,但没有任何运气:

  1. 我将其配置为maven-compiler-plugincompile:compile. 生成的 HelperClass 将存储在generated-sources/annotations. 没有如愿generated-test-sources/test-annotations。结果是,不会使用 Test-Scoped 依赖项。由于编译错误“找不到符号”,构建失败。失败

  2. 我使用了上面的配置,重新定义了生成的SourcesDirectory:

    <generatedSourcesDirectory>
       ${project.build.directory}/generated-test-sources/test-annotations
    </generatedSourcesDirectory>
    

    生成的类将按generated-test-sources/test-annotations预期存储,但构建仍然失败,因为它尝试按上述方式编译该文件并错过了测试范围的依赖项。失败

  3. **/generated-test-sources/test-annotations/**/*.java为了防止编译器在此阶段编译,我尝试使用上述配置并排除:

    <excludes>
       <exclude>**/generated-test-sources/test-annotations/**/*.java</exclude>
    </excludes>
    

    没运气。与上面相同的编译器错误。失败

  4. 我将其配置为maven-compiler-plugintest-compile:testCompile. HelperClass 理论上可能是在 中生成的generated-test-sources/test-annotations,但 AnnotationProcessor 不会偶然发现位于 中的带注释的类,而src/main/java不是在 中src/test/java,这是 AFAIK 期间的编译范围test-compile:testCompile。因此找不到 Annotated 类,不会生成 HelperClass,因此无法存储在generated-test-sources. 失败

  5. 试图在compile:testCompileand期间运行它test-compile:compile,这在这两种情况下都会导致 src/main/java 的类尚未被编译 - 因此编译器错误。失败

我真正想做的是:

  1. 将编译器配置为使用 AnnotationProcessorcompile:compile生成我的 HelperClass${project.build.directory}/generated-test-sources/test-annotations 但不要让 maven 编译它
  2. 然后在test-compile:testCompile.

我没有这样做。我不确定我是否在这里遗漏了重要的 Maven 基础知识(概念),或者排除配置是否存在问题,或者其他任何问题。

非常感谢任何帮助。提前致谢。

4

4 回答 4

5

includes我用,excludes等进行了几次测试testExcludes(我发现这些测试记录得很糟糕)。看来maven只是忽略了这些配置设置。真的不敢相信,但尽管它表明包含和排除已正确配置并且使用了这些配置(mvn -X clean install),但它仍然编译排除的文件或没有编译包含的文件。(顺便说一句:我也从 CLI 对其进行了测试,因为我发现一些 IDE 仍然忽略这些设置。)在那里找到的任何解决方案,比如添加资源目录,包括、排除、定义generatedTestSourcesDirectoryduringtest-compile:testCompile以匹配generatedSourcesDirectoryofcompile:compile根本不起作用. 任何。

我找到了解决问题的方法如下:

  1. 让第一个编译步骤 ( compile:compile) 只使用 Annotation-Processors,但不编译生成的类:<proc>only</proc>. 将 定义为generatedSourcesDirectory应生成测试源的位置:${project.build.directory}/generated-test-sources/test-annotations.
  2. 用于build-helper-maven-plugin在正确的阶段和目标中添加测试源目录。test-compile:testCompile然后将使用添加到正常源路径的生成的类源路径来执行隐式。

下面是我的配置。请注意,在我的实际问题发生之前,我需要生成其他内容,并且必须将其生成到generated-sources/annotations中,因此比解决方案所需的编译步骤多一个。

所以,就是这样:

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.0</version>
            <configuration>
                <source>1.7</source>
                <target>1.7</target>
                <encoding>${project.build.sourceEncoding}</encoding>
            </configuration>
            <executions>
                <execution>
                    <!-- normal compile and generation of other classes to standard location (implicit, you shouldn't need that) -->
                    <id>default-compile</id>
                    <goals>
                        <goal>compile</goal>
                    </goals>
                </execution>
                <execution>
                    <!-- Generates Test-Helper-Class into ${project.build.directory}/generated-test-sources/test-annotations WITHOUT compiling it -->
                    <id>compile-TestHelperClass</id>
                    <goals>
                        <goal>compile</goal>
                    </goals>
                    <configuration>
                        <annotationProcessors>
                            <annotationProcessor>org.my.UnitTestGenerationProcessor</annotationProcessor>
                        </annotationProcessors>
                        <generatedSourcesDirectory>${project.build.directory}/generated-test-sources/test-annotations</generatedSourcesDirectory>
                        <!-- generated class depends on test-scope libs, so don't compile now: proc:only DISABLES compilation of generated classes-->
                        <proc>only</proc>
                    </configuration>
                </execution>
                <!-- implicit test-compile:testCompile -->
            </executions>
        </plugin>
        <plugin>
            <!-- adds source-dir during generate-test-sources:add-test-source 
                 so that the path to our generated class is now known to the 
                 compiler during test-compile:testCompile -->
            <groupId>org.codehaus.mojo</groupId>
            <artifactId>build-helper-maven-plugin</artifactId>
            <version>1.8</version>
            <executions>
                <execution>
                    <id>add-test-source</id>
                    <phase>generate-test-sources</phase>
                    <goals>
                        <goal>add-test-source</goal>
                    </goals>
                    <configuration>
                        <sources>
                            <source>${project.build.directory}/generated-test-sources/test-annotations</source>
                        </sources>
                    </configuration>
                </execution> 
            </executions>
        </plugin>
    </plugins>
</build>
于 2013-09-18T08:48:19.487 回答
1

我有一个类似的问题,并尝试了建议的解决方案(两次执行 maven-compiler-plugin,第一次使用proc:none和第二次使用proc:only)但遇到了以下问题:

1)运行mvn clean install:在运行注释处理器之前,两个执行(proc:noneproc:only)都将编译源代码并生成类文件:

[INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ foo ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 6 source files to <mumble>\foo\target\classes
[INFO] 
[INFO] --- maven-compiler-plugin:3.1:compile (process-annotations) @ foo ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 6 source files to <mumble>\foo\target\classes
[MyAnnotationProcessor] processing ...

2)mvn install在上一次安装之后运行:两次执行 (proc:noneproc:only) 都确定类文件是最新的并且什么都不做,并且注释处理器没有运行:

[INFO] --- maven-compiler-plugin:3.1:compile (default-compile) @ foo ---
[INFO] Nothing to compile - all classes are up to date
[INFO] 
[INFO] --- maven-compiler-plugin:3.1:compile (process-annotations) @ foo ---
[INFO] Nothing to compile - all classes are up to date

所以在第一种情况下,java 文件被编译了两次(我的一个模块有数千个文件,这会显着影响构建时间)。而在第二种情况下,什么也没有发生,因为类文件已经存在。这是使用版本 3.1 和 3.0 的maven-compiler-plugin.

对于maven-compiler-plugin2.5.1 版本,第二次执行 ( proc:only) 将始终确定类文件是最新的并且不运行注释处理器,无论我是在运行mvn clean install还是mvn install,所以第二次执行是没有意义的。

插件配置如下:

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-compiler-plugin</artifactId>
  <version>3.1</version>
  <configuration>
    <source>1.7</source>
    <target>1.7</target>
  </configuration>
  <executions>
    <execution>
      <id>default-compile</id>
      <configuration>
        <proc>none</proc>
      </configuration>
    </execution>
    <execution>
      <id>process-annotations</id>
      <goals><goal>compile</goal></goals>
      <configuration>
        <proc>only</proc>
        <annotationProcessors>
          <annotationProcessor>MyAnnotationProcessor</annotationProcessor>
        </annotationProcessors>
      </configuration>
    </execution>
  </plugin>

所以proc:onlyoption 似乎在 3.0 和 3.1 版本中编译源代码(使其与 相同proc:both,这会影响性能)或在 2.5.1 版本中不采取任何操作(使其与 相同proc:none,这会影响功能)。

不知道如何解决这个问题......

编辑#1

详细输出包括以下内容:

[INFO] --- maven-compiler-plugin:3.1:compile (process-annotations) @ foo ---
[DEBUG] Configuring mojo 'org.apache.maven.plugins:maven-compiler-plugin:3.1:compile' with basic configurator -->
[DEBUG]   (f) annotationProcessors = [MyAnnotationProcessor]
[DEBUG]   (f) basedir = <mumble>\foo
[DEBUG]   (f) buildDirectory = <mumble>\foo\target
[DEBUG]   (f) classpathElements = [<mumble>\foo\target\classes, ...]
[DEBUG]   (f) compileSourceRoots = [<mumble>\foo\src\main\java]
[DEBUG]   (f) compilerId = javac
[DEBUG]   (f) debug = true
[DEBUG]   (f) failOnError = true
[DEBUG]   (f) forceJavacCompilerUse = false
[DEBUG]   (f) fork = false
[DEBUG]   (f) generatedSourcesDirectory = <mumble>\foo\target\generated-sources\annotations
[DEBUG]   (f) mojoExecution = org.apache.maven.plugins:maven-compiler-plugin:3.1:compile {execution: process-annotations}
[DEBUG]   (f) optimize = false
[DEBUG]   (f) outputDirectory = <mumble>\foo\target\classes
[DEBUG]   (f) proc = only
[DEBUG]   (f) projectArtifact = foo:jar:1.0-SNAPSHOT
[DEBUG]   (f) showDeprecation = false
[DEBUG]   (f) showWarnings = false
[DEBUG]   (f) skipMultiThreadWarning = false
[DEBUG]   (f) source = 1.7
[DEBUG]   (f) staleMillis = 0
[DEBUG]   (f) target = 1.7
[DEBUG]   (f) useIncrementalCompilation = true
[DEBUG]   (f) verbose = true
[DEBUG]   (f) mavenSession = org.apache.maven.execution.MavenSession@6fb65730
[DEBUG]   (f) session = org.apache.maven.execution.MavenSession@6fb65730
[DEBUG] -- end configuration --
[DEBUG] Using compiler 'javac'.
[DEBUG] Source directories: [<mumble>\foo\src\main\java]
[DEBUG] Classpath: [<mumble>\foo\target\classes ... ]
[DEBUG] Output directory: <mumble>\foo\target\classes
[DEBUG] CompilerReuseStrategy: reuseCreated
[DEBUG] useIncrementalCompilation enabled
[INFO] Changes detected - recompiling the module!
[DEBUG] Classpath:
[DEBUG]  <mumble>\foo\target\classes ...
[DEBUG] Source roots:
[DEBUG]  <mumble>\foo\src\main\java
[DEBUG] Command line options:
[DEBUG] -d <mumble>\foo\target\classes
    -classpath <mumble>\foo\target\classes;...;
    -sourcepath <mumble>\foo\src\main\java;
    -s <mumble>\foo\target\generated-sources\annotations
    -proc:only
    -processor MyAnnotationProcessor
    -g -verbose -nowarn -target 1.7 -source 1.7
[DEBUG] incrementalBuildHelper#beforeRebuildExecution
[INFO] Compiling 6 source files to <mumble>\foo\target\classes
[parsing started RegularFileObject[<mumble>\foo\src\main\java\Foo.java]]
[parsing completed 0ms]
...
[search path for source files: <mumble>\foo\src\main\java]
[MyAnnotationProcessor] processing ...

即使proc:only在编译器选项中有一个[parsing started RegularFileObject]条目......也许它只是记录它但实际上加载了类文件?

于 2014-10-02T13:18:58.090 回答
1

老实说,maven-compiler-plugin 通常很烂。我使用的第三方插件似乎总是对我正常工作。我只是<proc>none</proc>用于 maven-compiler-plugin,然后:

     <plugin>
        <groupId>org.bsc.maven</groupId>
        <artifactId>maven-processor-plugin</artifactId>
        <executions>
          <execution>
            <id>annogen</id>
            <phase>generate-sources</phase>
            <goals>
              <goal>process</goal>
            </goals>
            <inherited>false</inherited>
            <configuration>
              <processors>
                <processor>
                  xapi.dev.processor.AnnotationMirrorProcessor
                </processor>
              </processors>
              <outputDirectory>${project.build.directory}/generated-sources/annotations</outputDirectory>
              <appendSourceArtifacts>true</appendSourceArtifacts>
              <additionalSourceDirectories>
                <additionalSourceDirectory>
                  ${project.basedir}/../api/src/main/java
                </additionalSourceDirectory>
              </additionalSourceDirectories>
            </configuration>
          </execution>
        </executions>
      </plugin>
于 2015-10-13T01:39:21.013 回答
0

您可能想查看这篇博文:http: //deors.wordpress.com/2011/10/08/annotation-processors/

看起来您需要在 pom.xml 中设置以下内容

构建>插件>插件>配置>compilerArgument>-proc:none

我不确定这是否适用于您的特定情况,但我昨天正在处理注释,并认为这可能会对您有所帮助。

看起来这个参数可以让你在没有任何注释处理器的情况下进行编译。然后,您可以在生命周期的后期使用它们进行编译。

于 2013-09-17T15:25:58.437 回答