Компилятор Maven для компиляции всех файлов, а не модифицированных


Даже если я изменяю только один из своих классов, Maven всегда перекомпилирует их все. Я использую эту конфигурацию плагина:

<plugins>
    <plugin>
      <groupId>org.apache.maven.plugins</groupId>
      <artifactId>maven-compiler-plugin</artifactId>
      <version>3.1</version>
      <configuration>
        <staleMillis>1</slateMillis>
        <useIncrementalCompilation>true</useIncrementalCompilation>
      </configuration>
    </plugin>
</plugins>

Это происходит с mvn compile, mvn package и mvn install.

Конечно, это не проблема, если у вас есть 10-15 файлов. Однако у меня есть более тысячи исходных файлов, и это занимает много времени.

Делает плагин компилятора Мэйвен имеет некоторые скрытые настройки, чтобы перекомпилировать только измененные файлы? Есть ли обходные пути?

3 14

3 ответа:

Https://issues.apache.org/jira/browse/MCOMPILER-209

Используйте его с болгарской нотацией (да нет)

<useIncrementalCompilation>false</useIncrementalCompilation> означает истинный и наоборот

Резюме

В то время как Вы можете сказать Maven "перекомпилировать только измененные файлы", это приведет к неправильным результатам. Поведение по умолчанию-это не ошибка, а преднамеренное проектное решение.


Что useIncrementalCompilation на самом деле делает

Документация по этой теме, мягко говоря, не оптимальна. Вот что действительно происходит (на основе AbstractCompilerMojo source from maven-compiler-plugin 3.3):
  • useIncrementalCompilation установить в false (Нет рекомендуется )
    • при этом будут компилироваться только исходные файлы, которые являются более новыми, чем соответствующие им файлы классов, т. е. которые были изменены с момента последнего процесса компиляции. Как отмечает @Ivan в комментарии к другому ответу, это не будет перекомпилировать другие классы, которые используют измененный класс, потенциально оставляя их со ссылками на методы, которые больше не существуют, что приводит к ошибкам во время выполнения.
  • useIncrementalCompilation установить в true (default )
    • для обработки проблема, описанная выше, в этом режиме плагин компилятора будет определять, является ли
      • любые JAR-файлы, от которых зависит текущий модуль, были изменены в текущем запуске сборки, или
      • любой исходный файл был добавлен, удален или изменен с момента последней компиляции.
    • Если это так, то плагин компилятора намеренно перекомпилирует все исходники, печатая Changes detected - recompiling the module!

Таким образом, в общем, useIncrementalCompilation всегда следует оставлять по умолчанию true.


Почему он не делает что-то другое

Понятно, что можно спросить: почему плагин не определяет, какие классы затронуты изменениями, и перекомпилирует только эти классы? Так вот, в комментариик MCOMPILER-205 разработчик Maven Роберт Шолте пишет:

Причина в том, что компилятор java по умолчанию довольно быстр, вероятно, намного быстрее, чем анализ каждого файла, что с ним делать.

Таким образом, решение было просто перекомпилируйте все. Однако, как Роберт также пишет в этом комментарии, это, вероятно, не нужно, если проект использует компилятор Eclipse, который делает этот анализ. Но для сегодняшних пользователей Maven это спорный вопрос, поскольку maven-compiler-plugin еще не меняет свое поведение, основанное на выборе компилятора.

Вероятно, плохие новости: см. bug MCOMPILER-205.