繁体   English   中英

在 Maven 构建中使用 Eclipse Java 编译器 (ecj)

[英]Using Eclipse Java Compiler (ecj) in maven builds

Eclipse 使用它自己的编译器 (ECJ) 来编译 Java 代码。 调试用 Eclipse 编译的程序更容易,因为可以立即应用简单的代码更改(通过热代码替换)。

另一方面,Maven 使用(默认情况下)oracle JDK,它生成不同的字节码,防止在 Eclipse 调试会话中进行热代码替换。

因此,如果我打算调试程序,我想在我的 Maven 版本中使用 Eclipse ECJ 编译器。 对我来说,一个方便的方法是“ecj”配置文件:

  • 编译发布

    $ mvn package
  • 使用启用的热代码替换编译快照

    $ mvn -P ecj package

此外,可以在settings.xml甚至 Eclipse 项目属性中指定配置文件激活。

我的问题是:

  1. 这是正确的方法吗?
  2. 如何配置?
  3. 可以为此使用maven工具链吗?

可以更改maven-compiler-plugin使用的默认 javac 编译器。 Eclipse 编译器捆绑在工件plexus-compiler-eclipse中,它是通过将 maven-compiler-plugin 的compilerId属性设置为eclipse来声明的。

如果您想为自定义配置文件激活此更改,您可以进行以下配置:

<profile>
  <id>ecj</id>
  <build>
    <plugins>
      <plugin>
        <artifactId>maven-compiler-plugin</artifactId>
        <version>3.6.0</version>
        <configuration>
          <compilerId>eclipse</compilerId>
        </configuration>
        <dependencies>
          <dependency>
            <groupId>org.codehaus.plexus</groupId>
            <artifactId>plexus-compiler-eclipse</artifactId>
            <version>2.8.1</version>
          </dependency>
        </dependencies>
      </plugin>
    </plugins>
  </build>
</profile>

该插件在plexus-compiler GitHub 存储库中维护。 版本 2.8.1 使用 JDT 的 3.11.1.v20150902-1521 ,尽管您可以通过在 Plexus 编译器依赖项之后添加对org.eclipse.tycho:org.eclipse.jdt.core的依赖项来使用自己的版本。

与标准 javac 编译器相比,Eclipse Java 编译器 (ecj) 有很多优势。 它速度很快,并且可以配置更多警告和错误,从而提高代码质量。 编译器中最有趣的事情之一是在编译器中添加了null 类型:通过使用 @Nullable 和 @NotNull 注释来注释您的代码,您可以强制 Eclipse 编译器在编译时而不是运行时检查 null 访问。 当严格应用时,这会教您以更安全的方式编写代码(通过防止空值),并在测试或生产期间防止 NPE 异常。

在 Maven 中使用 Eclipse 编译器并不太难,但是网上有很多错误信息和旧信息,造成很多混乱。 我希望这有助于解决问题。

要使 Maven 使用 ecj 编译器,您需要使用 plexus-compiler-eclipse 插件,仅此而已。 典型的配置如下:

<pluginManagement>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-dependency-plugin</artifactId>
        </plugin>

        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.7.0</version>
            <configuration>
                <compilerId>eclipse</compilerId>
                <source>${source.jdk.version}</source>
                <target>${target.jdk.version}</target>
                <!-- Passing arguments is a trainwreck, see https://issues.apache.org/jira/browse/MCOMPILER-123 -->
                <compilerArguments>
                    <properties>${project.basedir}/.settings/org.eclipse.jdt.core.prefs</properties>
                </compilerArguments>
                <showWarnings>true</showWarnings>
                <showDeprecation>true</showDeprecation>
            </configuration>

            <dependencies>
                <dependency>
                    <groupId>org.codehaus.plexus</groupId>
                    <artifactId>plexus-compiler-eclipse</artifactId>
                    <version>2.8.3</version>
                </dependency>

                <dependency>
                    <groupId>org.eclipse.jdt</groupId>
                    <artifactId>ecj</artifactId>
                    <version>3.13.101</version>
                </dependency>
            </dependencies>
        </plugin>
</pluginManagement>

将此部分放在您的父/根 pom 的 pluginManagement 或构建部分中。

现在让我们解释不同的部分;)

maven-compiler-plugin 需要是最新版本。 source 和 target 参数定义了用于源代码和字节码的 java 版本,通常是相同的。

将参数传递给编译器完全是一场灾难。 请参阅下面的单独部分。 在这个例子中,我使用了属性设置,它允许我提供关于编译时我想要的错误和警告的详细设置。 通过在参数中使用 ${project.basedir} 变量,我为每个项目设置了这些设置:每个项目都需要有一个 .settings/org.eclipse.jdt.core.prefs 文件(很可能是Eclipse IDE 保留其编译器设置)。

对 plexus-codehaus-eclipse 的依赖定义了知道如何运行 Eclipse 编译器的插件。 2.8.3 版本是撰写本文时的最新版本,但此版本存在一些问题。 版本 2.8.4 应该带有一个重写的编译器接口,它修复了很多问题,但这个版本在撰写本文时仍在工作中。 您可以在此处找到有关插件的详细信息,以便在新版本/代码更改时跟踪进度。

另一个重要的依赖项是 org.eclipse.jdt:ecj 依赖项:它指定了要使用的 ecj 编译器的确切版本 您应该始终指定它,否则当插件决定在您发布大版本前一天使用另一个版本的编译器时,构建稳定性会受到影响;) 用于 ecj 编译器的版本号有点问题。 您可能能够从发布列表中找到版本号,然后检查这个 maven 存储库是否有类似的东西。 但是这个存储库只包含旧版本。 当您需要更新的版本时,您显然应该在这里查看这个版本 - 这是 Eclipse当前推出其版本的地方。 这个较新的存储库取消了较早版本的易于识别的版本号; 如上所示,它使用像 3.1xx 这样的版本号。 Eclipse 通常每年发布一次主要版本,并在中间发布一两个修复版本。 3.13.x 编号中的第二部分对应于 Eclipse Platform 项目中用于发布的内部版本控制。 很难通过列表获得,但至少这些是已知的:

Version    Eclipse Release      Compiler Version
3.13.0     Oxygen Release       4.7
3.13.50    Oxygen 1a            4.7.1a
3.13.100   Oxygen R2            4.7.2

版本总是以 3 开头,13 或多或少是发布的“年份”。 因此,当 13 是 Oxygen (2017, 4.7) 时,14 可能是 Photon (2018, 4.8)。

plexus-compiler-eclipse 插件的版本:2.8.4 之前

plexus-compiler-plugin 2.8.4 之前的版本使用内部 API 来启动 Eclipse 编译器。 这导致很多事情不能很好地工作,例如,这个内部 API 不解释 ecj 编译器的常用命令行参数。 这使得它很难使用,并且有些东西不受支持。 以下是限制列表:

  • 未实现注释处理。 任何配置都会被静默忽略。

  • 使用 <compilerArguments> 标签添加特定参数很困难,因为实现存在多个问题:

  • 编译器 mojo 似乎在此处输入的所有参数中添加了破折号。 但是,此版本插件使用的内部 API 需要不带破折号的参数。 所以插件再次删除它们。 由于这里的参数并不是真正的命令行 ecj 参数,因此很难知道使用哪些参数:查看 Eclipse 源代码中的 Compiler.java 类和 CompilerOptions.java 类以了解详细信息。

  • 插件确实在那里接受一些参数,但这些参数由插件本身解释,然后“翻译”到内部 api。

该插件在 <compilerArguments>> 标签中接受以下参数:

  • <properties>filename</properties>:定义一个属性文件,该文件将被传递给编译器的-properties 参数。 通过查看 Eclipse 项目中的文件 .settings/org.eclipse.jdt.core.prefs 可以找到该文件格式的示例:该文件存储编译器的配置。 它包含警告、错误和信息性消息的设置以及编译器合规性设置。

  • <errorsAsWarnings>随便</errorsAsWarnings>。 当这有效时,插件将忽略编译器生成的任何错误并将它们报告为警告。 当然编译仍然失败,因此取决于错误,.class 文件可能已被写入/更新。 这由插件本身处理:它只是将所有错误更改为警告并告诉世界编译工作。

从 2.8.4

plexus-compiler-eclipse 插件的 2.8.4 版大部分已被重写。 它现在使用 ECJ 编译器的公共 API,这或多或少是 ECJ 编译器本身。 例如,这意味着 ECJ 可以做的所有事情(如注释处理)现在插件也可以做,并且在标签中输入的参数现在被传递给编译器,这意味着您应该能够使用ecj 的帮助页面找出有趣的要添加的参数。

与以前的版本一样,此版本也要求您从所有参数名称中删除“-”; 在将参数名称添加到 ecj 命令行之前,会自动再次添加破折号。

该版本支持Maven定义的注解处理; 通过将所需部分添加到编译 blob,您可以运行注释处理器。 例如:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>${maven-compiler-plugin.version}</version>
    <configuration>
        <annotationProcessors>
            <annotationProcessor>db.annotationprocessing.EntityAnnotationProcessor</annotationProcessor>
        </annotationProcessors>
        <annotationProcessorPaths>
            <dependency>
                <groupId>to.etc.domui</groupId>
                <artifactId>property-annotations-processor</artifactId>
                <version>1.2-SNAPSHOT</version>
            </dependency>
        </annotationProcessorPaths>
    </configuration>

    <dependencies>
        <dependency>
            <groupId>to.etc.domui</groupId>
            <artifactId>property-annotations-processor</artifactId>
            <version>1.2-SNAPSHOT</version>
        </dependency>
    </dependencies>
</plugin>

这部分可能看起来不完整,因为根本没有引用 plexus-compiler-eclipse 插件,但请记住,在 Maven 中,该配置继承:在这种情况下,父 POM 包含上面的部分,这只是为仅限此 POM 的项目。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM