Eclipse Java编译器(ecj)与标准javac编译器相比有很多优势。它速度很快,并且可以配置更多的警告和错误,从而提高了代码质量。编译器中最有趣的事情之一是在编译器内添加了 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的构建部分中。
现在让我们解释一下不同的部分;)
maven-compiler-plugin 需要是最新版本。源参数和目标参数定义了用于源代码和字节码的 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.1x.x。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是氧(2017,4.7)时,14可能是光子(2018,4.8)。
plexus-compiler-eclipse 插件的版本:2.8.4 之前
2.8.4 之前的 plexus-compiler-plugin 版本使用内部 API 来启动 Eclipse 编译器。这导致很多事情不能很好地工作,因为例如,这个内部API不能解释ecj编译器的常用命令行参数。这使得它很难使用,并且某些内容不受支持。以下是限制列表:
未实现批注处理。任何配置都将以静默方式忽略。
使用 <编译器参数> 标记添加特定参数很困难,因为实现存在多个问题:
编译器 mojo 似乎为此处输入的所有参数添加了短划线。但是,此版本的插件使用的内部API需要不带破折号的参数。因此,该插件再次删除它们。由于这里的参数并不是真正的命令行 ecj 参数,因此很难知道要使用哪些参数:查看编译器.java类和编译器选项.java Eclipse 源代码中的类以获取详细信息。
插件确实接受那里的一些参数,但这些参数由插件本身解释,然后“翻译”到内部api。
此插件接受<编译器参数>>标记中的以下参数:
<属性>文件名</属性>:定义将传递给编译器的 -properties 参数的属性文件。通过查看 Eclipse 项目中的文件 .settings/org.eclipse.jdt.core.prefs 可以找到此文件格式的示例:此文件存储编译器的配置。它包含警告、错误和信息性消息的设置以及编译器合规性设置。
<错误作为警告>无论什么</错误作为警告>。当这有效时,插件将忽略编译器生成的任何错误,并将其报告为警告。当然,编译仍然失败,因此根据错误,.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的项目增加了一些配置。