简体   繁体   English

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

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

Eclipse uses it's own compiler (ECJ) to compile Java code. Eclipse 使用它自己的编译器 (ECJ) 来编译 Java 代码。 Debugging a program compiled with Eclipse is easier, because simple code changes can be applied instantly (by the hot code replacement).调试用 Eclipse 编译的程序更容易,因为可以立即应用简单的代码更改(通过热代码替换)。

Maven on the other hand uses (by default) oracle JDK, that generates different byte code preventing hot code replacement in a Eclipse debug session.另一方面,Maven 使用(默认情况下)oracle JDK,它生成不同的字节码,防止在 Eclipse 调试会话中进行热代码替换。

So I would like to use Eclipse ECJ compiler with my maven build, if I plan to debug the program.因此,如果我打算调试程序,我想在我的 Maven 版本中使用 Eclipse ECJ 编译器。 A convenient way for me would be a "ecj" profile:对我来说,一个方便的方法是“ecj”配置文件:

  • Compile release编译发布

    $ mvn package
  • Compile snapshot with enabled hot code replacement使用启用的热代码替换编译快照

    $ mvn -P ecj package

Also the profile activation can be specified in settings.xml or even Eclipse project properties.此外,可以在settings.xml甚至 Eclipse 项目属性中指定配置文件激活。

My questions are:我的问题是:

  1. Is this the right way to go?这是正确的方法吗?
  2. How this can be configured?如何配置?
  3. Can maven toolchain be used for this?可以为此使用maven工具链吗?

It is possible to change the default javac compiler that is used by the maven-compiler-plugin . 可以更改maven-compiler-plugin使用的默认 javac 编译器。 The Eclipse compiler is bundled in the artifact plexus-compiler-eclipse and it is declared by setting the compilerId attribute of the maven-compiler-plugin to eclipse . Eclipse 编译器捆绑在工件plexus-compiler-eclipse中,它是通过将 maven-compiler-plugin 的compilerId属性设置为eclipse来声明的。

If you want to activate this change for a custom profile , you could have the following configuration:如果您想为自定义配置文件激活此更改,您可以进行以下配置:

<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>

The plugin is maintained in the plexus-compiler GitHub repository .该插件在plexus-compiler GitHub 存储库中维护。 Version 2.8.1 uses 3.11.1.v20150902-1521 of JDT , although you could use your own version by adding a dependency on org.eclipse.tycho:org.eclipse.jdt.core after the Plexus Compiler dependency.版本 2.8.1 使用 JDT 的 3.11.1.v20150902-1521 ,尽管您可以通过在 Plexus 编译器依赖项之后添加对org.eclipse.tycho:org.eclipse.jdt.core的依赖项来使用自己的版本。

The Eclipse Java Compiler (ecj) has a lot of advantages over the standard javac compiler.与标准 javac 编译器相比,Eclipse Java 编译器 (ecj) 有很多优势。 It is fast, and it has way more warnings and errors that can be configured, improving code quality.它速度很快,并且可以配置更多警告和错误,从而提高代码质量。 One of the most interesting things in the compiler is the addition of null types inside the compiler : by annotating your code with @Nullable and @NotNull annotations you can force the Eclipse compiler to check null accesses at compile time instead of runtime.编译器中最有趣的事情之一是在编译器中添加了null 类型:通过使用 @Nullable 和 @NotNull 注释来注释您的代码,您可以强制 Eclipse 编译器在编译时而不是运行时检查 null 访问。 When applied rigorously this teaches you to code way more safe (by preventing null values) and it prevents NPE exceptions during testing or production.当严格应用时,这会教您以更安全的方式编写代码(通过防止空值),并在测试或生产期间防止 NPE 异常。

To use the Eclipse Compiler inside Maven is not too hard, but there is a lot of misinformation and old information on the Internets which causes a lot of confusion.在 Maven 中使用 Eclipse 编译器并不太难,但是网上有很多错误信息和旧信息,造成很多混乱。 I hope this helps to set things straight.我希望这有助于解决问题。

To make Maven use the ecj compiler you need to use the plexus-compiler-eclipse plugin and nothing else.要使 Maven 使用 ecj 编译器,您需要使用 plexus-compiler-eclipse 插件,仅此而已。 A typical configuration would be the following:典型的配置如下:

<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>

Put this part in either the pluginManagement or the build section of your parent/root pom.将此部分放在您的父/根 pom 的 pluginManagement 或构建部分中。

Now let's explain the different parts ;)现在让我们解释不同的部分;)

The maven-compiler-plugin needs to be of a recent version. maven-compiler-plugin 需要是最新版本。 The source and target parameters define the versions of java to use for source code and bytecode, and are usually the same. source 和 target 参数定义了用于源代码和字节码的 java 版本,通常是相同的。

Passing arguments to the compiler is an utter trainwreck.将参数传递给编译器完全是一场灾难。 See the separate section on that below here.请参阅下面的单独部分。 In this example I use the properties setting which allows me to provide detailed settings on which errors and warnings I want to have when compiling things.在这个例子中,我使用了属性设置,它允许我提供关于编译时我想要的错误和警告的详细设置。 By using the ${project.basedir} variable inside the parameter I have these settings per project: every project is required to have a .settings/org.eclipse.jdt.core.prefs file present (which is by happy chance the location where the Eclipse IDE leaves its compiler settings).通过在参数中使用 ${project.basedir} 变量,我为每个项目设置了这些设置:每个项目都需要有一个 .settings/org.eclipse.jdt.core.prefs 文件(很可能是Eclipse IDE 保留其编译器设置)。

The dependency on plexus-codehaus-eclipse defines the plugin that knows how to run the Eclipse compiler.对 plexus-codehaus-eclipse 的依赖定义了知道如何运行 Eclipse 编译器的插件。 The 2.8.3 version was the latest at the time of writing but this version has a few issues. 2.8.3 版本是撰写本文时的最新版本,但此版本存在一些问题。 Version 2.8.4 should come with a rewritten interface to the compiler which fixes a lot of issues, but this version is still in the works at the time of writing.版本 2.8.4 应该带有一个重写的编译器接口,它修复了很多问题,但这个版本在撰写本文时仍在工作中。 You can find details on the plugin here , so progress can be followed on new releases/code changes.您可以在此处找到有关插件的详细信息,以便在新版本/代码更改时跟踪进度。

The other important dependency is the org.eclipse.jdt:ecj dependency: this one specifies the exact version of the ecj compiler to use .另一个重要的依赖项是 org.eclipse.jdt:ecj 依赖项:它指定了要使用的 ecj 编译器的确切版本 You should always specify it because otherwise build stability will suffer when the plugin decides to use another version of the compiler one day before you have a big release ;) The version number to use for the ecj compiler is a bit of a problem.您应该始终指定它,否则当插件决定在您发布大版本前一天使用另一个版本的编译器时,构建稳定性会受到影响;) 用于 ecj 编译器的版本号有点问题。 You might be able to find the version number from the list of releases and then check this maven repository for something that looks like it.您可能能够从发布列表中找到版本号,然后检查这个 maven 存储库是否有类似的东西。 But this repository only contains the older versions.但是这个存储库只包含旧版本。 When you need a more recent release you should apparently look here at this one - this is where Eclipse currently pushes its versions .当您需要更新的版本时,您显然应该在这里查看这个版本 - 这是 Eclipse当前推出其版本的地方。 This newer repository does away with the easily recognizable version numbers of the earlier one;这个较新的存储库取消了较早版本的易于识别的版本号; it uses version numbers like 3.1xx as seen above.如上所示,它使用像 3.1xx 这样的版本号。 Eclipse usually has a major release once every year plus one or two fix releases in between. Eclipse 通常每年发布一次主要版本,并在中间发布一两个修复版本。 The second part in the 3.13.x number corresponds to the internal versioning used inside the Eclipse Platform project for releases. 3.13.x 编号中的第二部分对应于 Eclipse Platform 项目中用于发布的内部版本控制。 It is hard to get by a list but at least these are known:很难通过列表获得,但至少这些是已知的:

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

The version always starts with 3, the 13 is more or less the "year" of the release.版本总是以 3 开头,13 或多或少是发布的“年份”。 So when 13 is Oxygen (2017, 4.7) 14 will probably be Photon (2018, 4.8).因此,当 13 是 Oxygen (2017, 4.7) 时,14 可能是 Photon (2018, 4.8)。

Versions of the plexus-compiler-eclipse plugin: before 2.8.4 plexus-compiler-eclipse 插件的版本:2.8.4 之前

Versions before 2.8.4 of the plexus-compiler-plugin used an internal API to start the Eclipse compiler. plexus-compiler-plugin 2.8.4 之前的版本使用内部 API 来启动 Eclipse 编译器。 This causes a lot of things not to work that well, as this internal API, for instance, does not interpret the usual command line parameters of the ecj compiler.这导致很多事情不能很好地工作,例如,这个内部 API 不解释 ecj 编译器的常用命令行参数。 This makes it quite hard to use, and some things are not supported.这使得它很难使用,并且有些东西不受支持。 The following is a list of restrictions:以下是限制列表:

  • Annotations processing is not implemented.未实现注释处理。 Any configuration is silently ignored.任何配置都会被静默忽略。

  • Adding specific parameters by using the <compilerArguments> tag is hard as there are multiple problems with the implementation:使用 <compilerArguments> 标签添加特定参数很困难,因为实现存在多个问题:

  • The compiler mojo seems to add dashes to all parameters entered here.编译器 mojo 似乎在此处输入的所有参数中添加了破折号。 The internal API used by this version of the plugin, however, needs parameters without dashes.但是,此版本插件使用的内部 API 需要不带破折号的参数。 So the plugin removes them again.所以插件再次删除它们。 As the parameters here are not really command line ecj parameters it is hard to know which ones to use: look at the Compiler.java class and CompilerOptions.java classes inside Eclipse's source code for details.由于这里的参数并不是真正的命令行 ecj 参数,因此很难知道使用哪些参数:查看 Eclipse 源代码中的 Compiler.java 类和 CompilerOptions.java 类以了解详细信息。

  • The plugin DOES accept some parameters there, but these are interpreted by the plugin itself and then "translated" to the internal api.插件确实在那里接受一些参数,但这些参数由插件本身解释,然后“翻译”到内部 api。

This plugin accepts the following parameters in the <compilerArguments>> tag:该插件在 <compilerArguments>> 标签中接受以下参数:

  • <properties>filename</properties>: defines a properties file that will be passed to the -properties parameter of the compiler. <properties>filename</properties>:定义一个属性文件,该文件将被传递给编译器的-properties 参数。 Examples of this file's format can be found by looking at the file .settings/org.eclipse.jdt.core.prefs in an Eclipse project: this file stores the compiler's configuration.通过查看 Eclipse 项目中的文件 .settings/org.eclipse.jdt.core.prefs 可以找到该文件格式的示例:该文件存储编译器的配置。 It contains settings for warnings, errors and informational messages plus compiler compliance settings.它包含警告、错误和信息性消息的设置以及编译器合规性设置。

  • <errorsAsWarnings>whatever</errorsAsWarnings>. <errorsAsWarnings>随便</errorsAsWarnings>。 When this is valid the plugin will ignore any error that is generated by the compiler and report them as warnings.当这有效时,插件将忽略编译器生成的任何错误并将它们报告为警告。 Of course compilation still failed so depending on the error a .class file might have been written/updated or not.当然编译仍然失败,因此取决于错误,.class 文件可能已被写入/更新。 This gets handled by the plugin itself: it just changes all errors to warnings and tells the world that compilation worked.这由插件本身处理:它只是将所有错误更改为警告并告诉世界编译工作。

From 2.8.4从 2.8.4

Version 2.8.4 of the plexus-compiler-eclipse plugin has been mostly rewritten. plexus-compiler-eclipse 插件的 2.8.4 版大部分已被重写。 It now uses the public API of the ECJ compiler which more or less is the ECJ compiler itself.它现在使用 ECJ 编译器的公共 API,这或多或少是 ECJ 编译器本身。 This for instance means that everything that ECJ can do (like annotations processing) the plugin can now do too, and parameters entered in the tag are now passed to the compiler, which means you should be able to use ecj's help page to find out interesting parameters to add.例如,这意味着 ECJ 可以做的所有事情(如注释处理)现在插件也可以做,并且在标签中输入的参数现在被传递给编译器,这意味着您应该能够使用ecj 的帮助页面找出有趣的要添加的参数。

Like the previous version this version also requires you to remove the '-' from all parameter names;与以前的版本一样,此版本也要求您从所有参数名称中删除“-”; the dash is automagically added again before the parameter name is added to the ecj command line.在将参数名称添加到 ecj 命令行之前,会自动再次添加破折号。

This version supports annotation processing as defined by Maven;该版本支持Maven定义的注解处理; by adding the required parts to the compilation blob you can have your annotation processors run.通过将所需部分添加到编译 blob,您可以运行注释处理器。 For example:例如:

<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>

This part may seem incomplete because there is no reference to the plexus-compiler-eclipse plugin at all, but remember that in Maven that configuration inherits: the parent POM in this case contained the part above, and this just adds a bit of configuration for this POM's project only.这部分可能看起来不完整,因为根本没有引用 plexus-compiler-eclipse 插件,但请记住,在 Maven 中,该配置继承:在这种情况下,父 POM 包含上面的部分,这只是为仅限此 POM 的项目。

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

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