Подтвердить что ты не робот

Компилятор 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 файлов. Тем не менее, у меня есть более тысячи исходных файлов, и это занимает много времени.

Есть ли в плагине компилятора Maven скрытые настройки для перекомпиляции только измененных файлов? Есть ли обходные пути?

4b9b3361

Ответ 2

Резюме

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


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

Документация на эту тему, мягко говоря, не оптимальна. Вот что действительно происходит (на основе исходного кода AbstractCompilerMojo из maven-compiler-plugin 3.3):

  • useIncrementalCompilation установлен в false (не рекомендуется)
    • Это скомпилирует только исходные файлы, которые новее, чем соответствующие им файлы классов, т.е. которые были изменены с момента последнего процесса компиляции. Как отмечает @Ivan в комментарии к другому ответу, это не перекомпилирует другие классы, которые используют измененный класс, потенциально оставляя их со ссылками на методы, которые больше не существуют, что приводит к ошибкам во время выполнения.
  • useIncrementalCompilation установлен в true (по умолчанию)
    • Чтобы решить проблему, описанную выше, в этом режиме плагин компилятора определит,
      • любые файлы JAR, от которых зависит текущий модуль, были изменены в текущем прогоне сборки, или
      • любой исходный файл был добавлен, удален или изменен с момента последней компиляции.
    • В этом случае плагин компилятора намеренно перекомпилирует все исходные файлы, распечатывая Changes detected - recompiling the module!

Итак, в итоге, useIncrementalCompilation всегда следует оставить по умолчанию в useIncrementalCompilation true.


Почему это не делает что-то еще

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

Если какой-либо исходный файл был изменен или удален, все файлы будут удалены и перекомпилированы. Причина этого в том, что простая перекомпиляция всего с помощью стандартного java-компилятора довольно быстрая, вероятно, намного быстрее, чем альтернатива, которая будет выглядеть примерно так:

  1. обнаружить все измененные файлы
  2. проанализировать все исходные файлы, чтобы отобразить все отношения между классами
  3. рассчитать все затронутые файлы
  4. перекомпилировать поврежденные файлы

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

Ответ 3

Вероятно, плохая новость: см. ошибку MCOMPILER-205.

Ответ 4

Откат maven-compiler-plugin до версии 2.3.2 компилирует только измененные файлы без каких-либо дополнительных настроек.