【问题标题】:Maven build with AnnotationProcessor that parses files in src/main/java and generates sources to generated-test-sources/test-annotationsMaven 使用 AnnotationProcessor 构建,它解析 src/main/java 中的文件并生成源到 generate-test-sources/test-annotations
【发布时间】:2013-09-22 02:41:31
【问题描述】:

我正在使用 maven 3.0.3 和 Java7。

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

我尝试了几种配置都没有运气:

  1. 我将maven-compiler-plugin 配置为在compile:compile 期间使用AnnotationProcessor。生成的 HelperClass 将存储在 generated-sources/annotations 中。 不是generated-test-sources/test-annotations 中根据需要。结果是,不会使用测试范围的依赖项。由于编译错误“找不到符号”,构建失败。 失败

  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-plugin 配置为在test-compile:testCompile 期间使用AnnotationProcessor。 HelperClass 理论上可能是在generated-test-sources/test-annotations 中生成的,但AnnotationProcessor 不会偶然发现位于src/main/java 中的注释类,而不是src/test/java 中的注释类,这是AFAIK 在test-compile:testCompile 期间的编译范围。因此找不到 Annotated 类,不会生成 HelperClass,因此无法将其存储在 generated-test-sources 中。 失败

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

我真正想做的是:

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

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

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

【问题讨论】:

    标签: java unit-testing maven annotations code-generation


    【解决方案1】:

    我对@9​​87654321@、excludestestExcludes 等进行了几次测试(我发现这些测试记录很差)。看来maven只是忽略了这些配置设置。不敢相信,但尽管它显示包含和排除已正确配置并且使用了这些配置(mvn -X clean install),但它仍然编译排除文件或未编译包含文件。 (顺便说一句:我也从 CLI 对其进行了测试,因为我发现一些 IDE 仍然忽略这些设置。) 在那里找到的任何解决方案,例如添加资源目录,包括(不包括)在test-compile:testCompile 期间定义generatedTestSourcesDirectory 以匹配compile:compilegeneratedSourcesDirectory 根本不起作用。 随便。

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

    1. 让第一个编译步骤(compile:compile)只使用注释处理器,但不编译生成的类:&lt;proc&gt;only&lt;/proc&gt;。将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>
    

    【讨论】:

    • id compile-TestHelperClass 应该重命名为generate-TestHelperClass,因为评论说WITHOUT compiling
    • 我只想补充一点,maven-compiler-plugin 的 compile-TestHelperClass 执行应该绑定到 generate-test-sources 阶段以将其放置在适当的位置。
    【解决方案2】:

    我有类似的问题,并尝试了建议的解决方案(两次执行 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 文件被编译了两次(我的一个模块有数千个文件,这会显着影响构建时间)。在第二种情况下,什么也没有发生,因为类文件已经存在。这是使用 maven-compiler-plugin 的 3.1 和 3.0 版本。

    对于maven-compiler-plugin 2.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:only 选项似乎在版本 3.0 和 3.1 中编译源代码(使其与 proc:both 相同,这会影响性能)或在版本 2.5.1 中不采取任何操作(使其与 @ 相同) 987654339@,这会影响功能)。

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

    编辑#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] 条目......也许它只是记录它但实际上加载了类文件?

    【讨论】:

      【解决方案3】:

      老实说,maven-compiler-plugin 通常很烂。我使用的第三方插件似乎总是对我正常工作。我只是将&lt;proc&gt;none&lt;/proc&gt; 用于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>
      

      【讨论】:

        【解决方案4】:

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

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

        build>plugins>plugin>configuration>compilerArgument>-proc:none

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

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

        【讨论】:

        • 我的 AnnotationProcessors 通常可以工作。我的问题是:在compile:compile 期间,生成的类所需的测试范围依赖项对编译器(试图编译生成的类)不可见,并且在test-compile:testCompile 期间,不会为带注释的类调用 AnnotationProcessor位于 src/main/java 中(不在 src/main/test 中)
        猜你喜欢
        • 2020-05-30
        • 1970-01-01
        • 2023-04-09
        • 2020-03-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-03-22
        • 1970-01-01
        相关资源
        最近更新 更多