Maven: частичная компиляция перед генерацией кода - PullRequest
5 голосов
/ 05 октября 2011

tl; dr-edition: У меня есть компиляция, и я знаю, что она не удастся, но мне нужно подмножество классов, которые все еще могут быть скомпилированы в моей папке target/classes после компиляции.Я настроил <failOnError>false</failOnError>, но классы не генерируются, даже фиктивный класс, который не зависит от других классов, кроме Object.Есть ли какая-либо конфигурация для достижения этой цели?


У меня есть проект на основе Maven, рабочий процесс которого состоит в основном из следующих (соответствующих) целей:

  • ...
  • init-compile

    Генератор кода (ниже) использует конфигурацию, основанную на отражениях, поэтому на первом этапе я хочу попробовать скомпилировать как можно большую часть проектатак что никакие ClassNotFoundExceptions не брошены туда.Эта компиляция настроена на <failOnError>false</failOnError>, поэтому сборка продолжается.

    К сожалению (вы можете назвать это недостатком проекта), конфигурация используется как для генерации кода (указание файла OWL и пространства имен для сопоставлений пакетов)и во время выполнения, поэтому он также содержит другие элементы, которые не нужны для генератора кода, но все еще читаются и, следовательно, необходимы для пути к классам.

  • generate-model

    На этом этапе некоторые классы моделей генерируются из OWL-онтологии, создавая код, который делает остальную часть проекта полностью компилируемой.

  • default-compile

    Теперь остальные классы должны быть скомпилированы, очевидно,

  • save-model

    Теперь экземпляры из онтологии читаются и сериализуются в файл длявремя выполнения

  • ...

Примечание: и генерировать, и сохранять модель используют maven-exec-plugin, но я искренне не думаю, что это имеет значениена все.

Question:

Когда я запускаю сборку с mvn -e -U clean package source:jar javadoc:jar install:install, она завершается с ошибкой во время цели generate-model с ошибками, которых я пытаюсь избежать.target/classes пусто, поэтому кажется, что компилятор не выплевывает подмножество классов, которые он мог / должен был бы обработать.Есть ли способ добиться этого?

Я имею в виду два обходных пути, которые мне не нравятся:

  • Редактирование файла конфигурации "AST" перед его разбором в Java-Объекты, так что анализируется только та часть, которая имеет отношение к генератору кода (необходимо настроить код, к которому у меня есть доступ, но мой проект должен считать его неизменным);
  • и настроить цель init-compile только навключите необходимые классы (слишком негибкие, потому что POM должен / может быть шаблоном для будущих приложений, использующих ту же модель).

Если вы можете представить другой способ обойти мою проблему, вы можете увидетьиз моего описания, я тоже был бы рад их услышать!

Ответы [ 2 ]

4 голосов
/ 11 октября 2011

Во-первых, позвольте мне повторить вашу проблему, чтобы убедиться, что я правильно ее понял.

  • У вас есть набор классов, функция которых в их скомпилированной форме состоит в настройке обоихгенератор кода и время выполнения.(Подмножество из них относится к генератору кода, но генерация не удастся, если не будет полной конфигурации. Поэтому мы можем рассматривать ее так, как если бы была необходима вся конфигурация.)

  • Вызатем есть набор классов, которые будут сгенерированы как исходный код.У них есть время генерации, возможно время компиляции и зависимость времени выполнения от классов конфигурации.

  • Наконец, у вас есть некоторый другой код, который зависит от времени компиляции отсгенерированные классы и зависимость времени выполнения от сгенерированных классов и классов конфигурации.

  • Однако ваши классы конфигурации не имеют каких-либо зависимостей времени компиляции от сгенерированных классов или отдругой код.Вы прямо не говорите это, но я предполагаю это, иначе у вас есть проблема циклической зависимости.

Вот мое предложение: Разделите проектв многомодульный («реакторный») проект.Ваш текущий проект будет модулем проекта реактора.Создайте новый модуль с именем «config» или аналогичный и перенесите в него ваши конфигурационные классы.Пусть основной модуль зависит от него.

Если вам не нравятся многомодульные проекты, вы можете добиться того же, объявив дополнительное выполнение плагина компиляции, привязанное к фазе создания источников.(Вы не говорите, но я предполагаю, что вы делаете генерацию кода на этом этапе. Если вы объявите плагин компиляции перед плагином генератора кода в POM, Maven выполнит их в том же порядке.) Вы должны использоватьФильтр «include» подключаемого модуля для компиляции только классов конфигурации.Для этого вам необходимо иметь классы конфигурации в отдельном пакете от всех остальных, что в любом случае является хорошей практикой.

2 голосов
/ 20 декабря 2013

Существует одно очень удобное решение - используйте Eclipse Java Compiler (EJC) вместо стандартного Oracle javac!Одним из преимуществ ECJ перед javac является то, что он допускает ошибки, он пытается компилировать как можно больше и сохраняет уже сгенерированные файлы class .EJC был разработан для использования в IDE, для высокоинтерактивной работы, где частичная компиляция является обязательной, но он также может использоваться как плагин CLI или Maven.Ребята из Plexus предоставляют EJC как удобную зависимость от Maven.

Компиляторы подключаются в Maven.У вас может быть несколько компиляций (выполнений компиляции), определенных в одном POM, и вы можете использовать разные компиляторы для каждого, предоставляя разработчику широкий диапазон параметров.

Пример кода POM:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>3.1</version>
    <executions>
        <execution>
            <id>pre-compilation</id>
            <phase>generate-sources</phase>
            <goals>
                <goal>compile</goal>
            </goals>
            <configuration>
                <compilerId>eclipse</compilerId>
                <!-- IMPORTANT. Select EJC as compiler instead of javac -->
                <failOnError>false</failOnError>
                <!-- IMPORTANT. When ECJ is used errors are reported 
                only as warnings, it continues in compilation, 
                try to compile as much as possible, keeps already 
                generated classes in target/classes -->
            </configuration>
        </execution>
        <execution>
            <id>default-compile</id>
            <phase>compile</phase>
            <!-- in the end recompile everything with standard javac.
                 This time no compilation errors are expected or tolerated. -->
            <goals>
                <goal>compile</goal>
            </goals>
            <configuration>
                <useIncrementalCompilation>false</useIncrementalCompilation>
            </configuration>
        </execution>
    </executions>
    <dependencies>
        <dependency>
            <groupId>org.codehaus.plexus</groupId>
            <artifactId>plexus-compiler-eclipse</artifactId>
            <version>2.3</version>
        </dependency>
    </dependencies>
</plugin>

<!-- generate sources. This plugin executes in facet BETWEEN the compilations due to 
    'generate-sources' phase binding and relative position in POM -->
<plugin>
    <groupId>org.eclipse.xtext</groupId>
    <artifactId>xtext-maven-plugin</artifactId>
    <version>2.5.0</version>
    <executions>
        <execution>
            <id>generate-the-stuff</id>
            <phase>generate-sources</phase>
            <goals>
                <goal>generate</goal>
            </goals>
        </execution>
    </executions>
</plugin>

Кредиты дляГабриэль Аксель за свою статью http://www.gabiaxel.com/2011/10/replacing-javac-with-eclipse-compiler.html

Этот подход может решить некоторые хитрые круговые зависимости " источник до сгенерированный источник до источник ", потенциальнонеразрешимой путем разделения на отдельные модули.

Кроме того, я хотел интегрировать генерацию источников наиболее прозрачным способом.Необходимость перестановки кода, основанного на зависимостях от сгенерированных источников, окончательно сломает его.Я хочу сгруппировать мой код на основе логического проектирования, а не из-за технических сложностей.

Если ваш генератор кода работает с xtext, как в моем случае, и вы используете xtext-maven-plugin, скажем, недавно выпущенный 2.5.0Вам не нужно ничего настраивать, как в примере выше, плагин делает именно это под капотом.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...