Запуск ANT с разными JDK через EXEC (обходной путь APT/WSGEN)
Я надеюсь, что это найдет мастера сборки ANT, у которого есть некоторый опыт запуска ANT с разными версиями JDK одновременно!
Я унаследовал довольно старый набор библиотек и файлов сборки ANT, которые в настоящее время работают под управлением Java 6/7. Пытаясь модернизировать эту систему для использования Java 8 или любых будущих обновлений JDK, я работал над способом рефакторинга этих файлов сборки для работы с Java 8.
Текущая система сборки имеет следующую характеристику:
- Ant 1.7.0 и Java 1.7.0_55
- Использование устаревшего инструмента APT через задачи ANT APT
- Использование wsgen (библиотеки, связанные с jaxws) через задачи ANT WSGEN (например, classname="com.sun.tools.ws.ant.WsGen")
- Эффективно файлы компоновки смешивают генерацию кода и компиляцию для создания желаемого результата.
Инструмент APT устарел в Java 1.7, нужно перейти на использование JAVAC в версии 1.8 и выше!
Пытаясь заменить использование APT на JAVAC, я обнаружил, что инструмент не только удален, но и многочисленные пакеты / классы / интерфейсы, связанные с инструментом APT. Я видел эту тему, обсуждаемую здесь в нескольких вопросах и ответах, однако большинство предложенных решений не были начальными.
Единственное предложение, которое я нашел, которое обещало, было отделить генерацию кода (использование APT) от компиляции (JAVAC) для размещения в разных файлах сборки ANT. После разделения файла сборки на "основной" файл сборки и "кодовый" файл сборки, это, кажется, работает нормально.
Пример:
<property name="apt.output.file" value="codegen.apt.${java.version}.log" /> <!-- A different log file will exist when I run the "main" ant build file using Java 7 vs 8 for comparison purposes. -->
<exec executable="${exec.ant.cmd}" osfamily="unix" failonerror="true" output="${apt.output.file}" >
<arg line="${ant.apt.cmd.line.options}" />
<env key="JAVA_HOME" value="${exec.java.home}"/> <!-- Java 1.7 -->
<env key="ANT_HOME" value="${ant.home.path}"/> <!-- Ant 1.7.0 -->
<env key="PATH" value="${exec.java.home}/bin" /> <!-- Reset PATH to be certain -->
<!-- The various properties are defined in the build file, and would be fairly unsurprising. -->
</exec>
Теперь, когда фрагменты "codegen" были автономными, это позволяет мне:
- Запустите "основной" файл сборки ANT с Java 8.
- Для частей "codegen" используйте EXEC, как указано выше, чтобы указать версию ANT/JAVA для генерации кода *.java.
Хорошая новость для тех из вас, кто находится в подобных ситуациях, заключается в том, что для APT это работает нормально. Я изменил свой JAVA_HOME & PATH так, чтобы он указывал на Java 8, и, похоже, он работает нормально (при условии, что APT ограничен только генерацией исходного кода *.java, без компиляции).
Теперь вот беда, и я надеюсь, что у кого-то есть опыт. Я обнаружил, что инструмент APT также использовался для создания файла сборки ANT (wsgen-build.xml). Указанный файл определяет задачу WSGEN и затем использует ее несколько раз:
<project name="some-wsgen-fragment" default="wsgenall">
<target name="wsgenall">
<taskdef name="wsgen" classname="com.sun.tools.ws.ant.WsGen" >
<classpath>
<pathelement path="${jaxws.home}/lib/jaxws-tools.jar" />
</classpath>
</taskdef>
<echo message="wsgen for SomeWebServiceImpl" />
<wsgen destdir="${classes.server.gen.dir}" sourcedestdir="${something.gen.dir}" sei="com.something.or.other.SomeWebServiceImpl">
<classpath>
<pathelement path="${classes.server.gen.dir}" />
<path refid="classpath.all" />
</classpath>
</wsgen>
... Repeated usages of wsgen exactly as above, with different classes
Подобно задачам APT, "основной" файл сборки вызывает EXEC для запуска "старого" ANT с соответствующими параметрами для вызова этого сгенерированного файла сборки в той же среде, в которой он работает.
Под Java 1.7 и ANT 1.7.0 это работает нормально.
Когда я меняю Java на 1.8, я меняю JDK для JAVA_HOME и java.target на 1.8, я получаю следующую загадочную ошибку:
[echo] wsgen for SomeWebServiceImpl
Finding class com.something.or.other.SomeWebServiceImpl
[antcall] Exiting codegen-buildfile.xml.
BUILD FAILED
codegen-buildfile.xml:58: The following error occurred while executing this line:
wsgen-build.xml:9: Requires JDK 5.0 or later. Please download it from http://java.sun.com/j2se/1.5/
at org.apache.tools.ant.ProjectHelper.addLocationToBuildException(ProjectHelper.java:541)
at org.apache.tools.ant.taskdefs.Ant.execute(Ant.java:418)
at org.apache.tools.ant.taskdefs.CallTarget.execute(CallTarget.java:105)
Вопрос для меня "ощущается" следующим образом:
Почему ANT, работающий на Java 8, мешает ANT, работающему на Java 7, и как это можно исправить?
Некоторые вопросы и ответы, которые привели меня к этому вопросу:
Вы пытались использовать ANT -v -d для выяснения этого? Да, я создаю файл журнала на основе ${java.version}, используемого для "основного" файла сборки. Я создаю файл для Java 8 и один для Java 7, и различаю два. Нет никакой разницы между средой / свойством / настройками (Java 7 против Java 8), пока я не обнаружу ошибку, указанную выше. Есть небольшие изменения в загружаемых классах заказов, но это так.
Когда вы переключаетесь между Java 7 и Java 8, убедитесь, что изменения не влияют на ваши задачи EXEC? Разница между файлами журналов, как указано выше, подтверждает это, но когда я вызываю EXEC, свойства в первом примере выше жестко закодированы с помощью тегов ENV, используемых для обеспечения того, что переменные среды также являются одинаковыми, независимо от используемой версии Java. в "основном" файле сборки.
Конечно, есть какая-то разница между переменными окружения, вызывающая эту проблему? Я регистрирую несколько переменных, пытающихся диагностировать проблему. Пока что файл компоновки ANT "codegen" имеет все то же самое, независимо от того, запускается ли "основной" ANT в Java 7 или 8: ANT_HOME, JAVA_HOME, PATH, ant.version, java.version, java.vm.version, java.class.path, java.ext.dirs. Подробный журнал ANT также подтверждает это, между ними нет проблем со свойством / средой /classpath.
Я не могу сказать из вашего примера EXEC, но вы используете полные пути? Возможно, переменная PATH является проблемой? Хотя это и не показано, я указываю полные пути к ANT и JAVA, поскольку мне нужно точно указать ANT/JDK, чтобы убедиться, что я использую нужные версии.
Как вы вызываете сгенерированный файл сборки с помощью задач wsgen (wsgen-build.xml), в которых возникла проблема? "Основной" файл сборки вызывает EXEC для файла сборки "codegen", как в примере выше. Единственным отличием является другая цель сборки, одна цель используется для APT, другая используется для части WSGEN. В указанной цели WSGEN в файле сборки "codegen" в настоящее время импортируется файл wsgen-build.xml, и цель вызывается через ANTCALL. Я также пытался использовать только задачу ANT, оба имеют одинаковый результат.
Можете ли вы запустить свои команды EXEC из командной оболочки? Да, если я запускаю шаг в командной строке, он либо работает, либо нет, в зависимости от того, установлен ли Java 7 или 8 как JAVA_HOME и который появляется первым в PATH. Например, если я обновляю JAVA_HOME на Java 8, я получаю следующую ошибку: java.lang.NoClassDefFoundError: com/sun/mirror/apt/AnnotationProcessorFactory. Это правильно, так как этот класс больше не существует в Java 8 (но существует в 7).
Вы пытались использовать скрипт или командный файл вместо EXEC в исполняемом файле ANT? Да, такая же ошибка в результате. Я попытался сделать это с помощью простого файла.bat, в котором были заданы необходимые переменные среды, и вызвал команду из оболочки.
На какой ОС вы работали, пробовали ли вы другую машину / ОС, чтобы увидеть, зависит ли это от конкретной среды? У меня есть среда Win7 и RHEL 7, эта проблема возникает в обоих случаях, и я использую атрибут osfamily для условного определения команды EXEC для каждой платформы.
Ant 1.7.0 довольно старый, вы пробовали обновленный Ant? Та же проблема возникает при использовании Ant 1.9.4. Ant 1.9.4 работает только для "основного" файла сборки, файл сборки "codegen" будет использовать 1.7.0, так как я явно устанавливаю это через задачи EXEC. Я попробовал 1.9.4 даже для файла сборки ant "codegen", но в ошибке не было никакой разницы.
Если вам удалось прочитать все это целиком, моя шляпа перед вами, сэр или мадам! Спасибо за любые идеи и советы!