Использование Eclipse Java Compiler (ecj) в сборках Maven

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 Toolchain быть использован для этого?

2 ответа

Решение

Можно изменить значение по умолчанию javac Компилятор, который используется maven-compiler-plugin, Компилятор Eclipse входит в состав артефакта plexus-compiler-eclipse и это объявлено установкой eclipse к compilerId атрибут maven-compiler-plugin,

Если вы хотите активировать это изменение для пользовательского профиля, вы можете иметь следующую конфигурацию:

<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 использует 3.11.1.v20150902-1521 JDT, хотя вы можете использовать свою собственную версию, добавив зависимость от org.eclipse.tycho:org.eclipse.jdt.core после зависимости компилятора Plexus.

The Eclipse Java Compiler (ecj) has a lot of advantages over the standard javac compiler. 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. When applied rigorously this teaches you to code way more safe (by preventing null values) and it prevents NPE exceptions during testing or production.

Использовать Eclipse Compiler внутри Maven не так уж сложно, но в Интернете есть много дезинформации и устаревшей информации, которая вызывает много путаницы. Я надеюсь, что это помогает все исправить.

Чтобы заставить Eclipse использовать 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>

Поместите эту часть либо в pluginManagement, либо в раздел сборки вашего родительского / корневого модуля.

Теперь давайте объясним различные части;)

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.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, вероятно, будет фотоном (2018, 4.8).

Версии плагина plexus-compiler-eclipse: до версии 2.8.4

Версии до 2.8.4 модуля plexus-compiler-plugin использовали внутренний API для запуска компилятора Eclipse. Это приводит к тому, что многие вещи работают не так хорошо, как, например, этот внутренний API, не интерпретирующий обычные параметры командной строки компилятора ecj. Это делает его довольно сложным в использовании, а некоторые вещи не поддерживаются. Ниже приведен список ограничений:

  • Обработка аннотаций не реализована. Любая конфигурация игнорируется.

  • Добавить определенные параметры с помощью тега сложно, так как есть много проблем с реализацией:

  • Компилятор mojo, кажется, добавляет черты ко всем параметрам, введенным здесь. Однако для внутреннего API, используемого этой версией плагина, нужны параметры без черточек. Таким образом, плагин удаляет их снова. Поскольку эти параметры на самом деле не являются параметрами ecj командной строки, трудно понять, какие из них использовать: смотрите детали в классе Compiler.java и классах CompilerOptions.java в исходном коде Eclipse.

  • Плагин принимает там некоторые параметры, но они интерпретируются самим плагином и затем "переводятся" во внутренний API.

Этот плагин принимает следующие параметры в теге >:

  • filename: определяет файл свойств, который будет передан параметру -properties компилятора. Примеры формата этого файла можно найти, посмотрев файл.settings/org.eclipse.jdt.core.prefs в проекте Eclipse: этот файл хранит конфигурацию компилятора. Он содержит настройки для предупреждений, ошибок и информационных сообщений, а также настройки соответствия компилятору.

  • любой. Когда это допустимо, плагин будет игнорировать любую ошибку, сгенерированную компилятором, и сообщать о них как о предупреждениях. Конечно, компиляция все равно не удалась, поэтому в зависимости от ошибки, файл.class мог быть записан / обновлен или нет. Это обрабатывается самим плагином: он просто заменяет все ошибки предупреждениями и сообщает миру, что компиляция сработала.

С 2.8.4

Версия 2.8.4 плагина plexus-compiler-eclipse была в основном переписана. Теперь он использует открытый API компилятора ECJ, который более или менее является самим компилятором ECJ. Это, например, означает, что все, что может делать ECJ (например, обработка аннотаций), теперь может делать и плагин, а параметры, введенные в теге, теперь передаются компилятору, что означает, что вы должны иметь возможность использовать страницу справки ecj, чтобы выяснить интересную информацию. параметры для добавления.

Как и в предыдущей версии, эта версия также требует, чтобы вы удалили '-' из всех имен параметров; тире автоматически добавляется перед тем, как имя параметра добавляется в командную строку ecj.

Эта версия поддерживает обработку аннотаций в соответствии с определением Maven; добавив необходимые части в блок компиляции, вы можете запустить процессоры аннотаций. Например:

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

Другие вопросы по тегам