在maven构建中使用Eclipse Java Compiler(ecj)

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

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

因此,如果我计划调试程序,我想将Eclipse ECJ编译器与我的maven构建一起使用。 对我来说一个方便的方式是“ecj”配置文件:

  • 编译发布

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

     $ mvn -P ecj package 

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

我的问题是:

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

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

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

  ecj    maven-compiler-plugin 3.6.0  eclipse    org.codehaus.plexus plexus-compiler-eclipse 2.8.1       

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

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

在Maven中使用Eclipse编译器并不是很难,但是有很多关于互联网的错误信息和旧信息会导致很多混乱。 我希望这有助于确定事情。

要使Eclipse使用ecj编译器,您需要使用plexus-compiler-eclipse插件,而不是其他任何东西。 典型配置如下:

    org.apache.maven.plugins maven-dependency-plugin   org.apache.maven.plugins maven-compiler-plugin 3.7.0  eclipse ${source.jdk.version} ${target.jdk.version}   ${project.basedir}/.settings/org.eclipse.jdt.core.prefs  true true    org.codehaus.plexus plexus-compiler-eclipse 2.8.3   org.eclipse.jdt ecj 3.13.101     

将此部分放在父/ root pom的pluginManagement或build部分中。

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

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是氧气(2017年,4.7)时,14可能是Photon(2018,4.8)。

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

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

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

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

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

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

此插件接受>标记中的以下参数:

  • filename :定义将传递给编译器的-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,您可以运行注释处理器。 例如:

  org.apache.maven.plugins maven-compiler-plugin ${maven-compiler-plugin.version}   db.annotationprocessing.EntityAnnotationProcessor    to.etc.domui property-annotations-processor 1.2-SNAPSHOT      to.etc.domui property-annotations-processor 1.2-SNAPSHOT    

这部分可能看起来不完整,因为根本没有对plexus-compiler-eclipse插件的引用,但请记住,在Maven中配置inheritance:在这种情况下,父POM包含上面的部分,这只是添加了一些配置这个POM的项目而已。

Interesting Posts