используйте системный classpath для задачи ant javac - PullRequest
6 голосов
/ 07 мая 2011

Я хочу, чтобы задача javac использовала jars из системного classpath, под которым я подразумеваю classpath, который устанавливается в среде оболочки до запуска ant.Этот путь к классу

CLASSPATH=D:\local\lib\java\*;.;C:\lib\java\*;C:\lib\java\db\*

в моей системе.У меня есть популярные банки, которые используются во многих проектах.Основной фрагмент, который я использую в файле сборки:

<target name="build">
    <mkdir dir="${obj}" />
    <javac srcdir="${src}" destdir="${obj}"
        includes="**/*.java"
        excludes="**/package-info.java **/deprecated/*.java"
        includeAntRuntime="no" debug="true" debuglevel="source,lines"
    >
        <compilerarg value="-Xlint"/>
    </javac>
</target>

Таким образом, ant передает только выходной каталог как classpath.

[javac] '-classpath'
[javac] 'D:\dev\tbull-projects\jsonc\obj'

(jsonc - проект, над которым я работаю,и D:\dev\tbull-projects\jsonc - рабочий каталог.) Некоторое время я просматривал документацию и сделал две попытки.Сначала добавляли атрибут classpath="${java.class.path}" в тег javac.Это передало бы чрезвычайно длинный путь к классу компилятору, перечисляя каждый отдельный jar-файл из собственной директории lib ant и, наконец, tools.jar из JDK.Не тот путь к классу, который я хотел.

Второй выстрел был настроен на

    <property name="build.sysclasspath" value="first" />

до вызова javac, и это привело меня в правильном направлении.Теперь эти строки были среди выходных:

dropping D:\dev\tbull-projects\jsonc\D:\local\lib\java\* from path as it doesn't exist
dropping D:\dev\tbull-projects\jsonc\C:\lib\java\* from path as it doesn't exist
dropping D:\dev\tbull-projects\jsonc\C:\lib\java\db\* from path as it doesn't exist
dropping D:\dev\tbull-projects\jsonc\C:\Program Files\Java\jdk1.6.0_18\jre\lib\sunrsasign.jar from path as it doesn't exist
dropping D:\dev\tbull-projects\jsonc\C:\Program Files\Java\jdk1.6.0_18\jre\classes from path as it doesn't exist

Ну, вы можете себе представить, что эти пути действительно не существуют.Я просто не понимаю, почему муравей построил их таким образом.Он бы знал, как сделать арифметику пути в Windows, не так ли?

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

Из того, что я виделв других вопросах, касающихся ant + classpath, кажется, что распространять библиотеки зависимостей с исходным кодом - это обычная мода (поэтому classpath может быть таким же, как ./libs).Но я, конечно же, не хочу, чтобы в моем git-репо были банки.Так как это можно сделать?

Ответы [ 8 ]

3 голосов
/ 07 мая 2011

Установите includeJavaRuntime = true в задании javac.

<target name="build">
    <mkdir dir="${obj}" />
    <javac srcdir="${src}" destdir="${obj}"
        includes="**/*.java"
        excludes="**/package-info.java **/deprecated/*.java"
        includeAntRuntime="no" includeJavaRuntime="true"
        debug="true" debuglevel="source,lines">
        <compilerarg value="-Xlint"/>
    </javac>
</target>
1 голос
/ 03 мая 2017

Когда javac компилирует код, он пытается найти файлы в rt.jar в файле символов с именем ct.sym (который также присутствует в каталоге lib). некоторые файлы отсутствуют в этом файле символов. Мне нужно добавить опцию компиляции, чтобы игнорировать файл символов и смотреть прямо в rt.jar.

, поэтому я использовал эту опцию -XDignore.symbol.file для ant, и я поместил это значение в тег javac. он отлично работает, если вы используете Eclipse или любой другой ide.

<compilerarg value="-XDignore.symbol.file"/> 

Итак, всякий раз, когда вы получаете ClassNotFoundException при использовании классов из rt.jar, и если класс все еще присутствует там, просто попробуйте добавить этот аргумент в компилятор java

Для ссылки на rt.jar из муравья вы можете использовать:

<fileset dir="${java.home}/lib" includes="rt.jar"/>

Оригинальные детали были найдены здесь: http://www.javaroots.com/2013/01/javac-error-using-classes-from-rtjar.html

1 голос
/ 07 мая 2011

Почему не вы установили CLASSPATH в Ant? Это идеально подходит для этого. Вы делаете ошибку, если делаете что-то еще. Он не только будет работать, но и ваш build.xml документирует требования.

0 голосов
/ 19 апреля 2016

Совершенно очевидно, что люди, стоящие за java, и (или, по крайней мере), ant, действительно, действительно не хотят видеть, что $CLASSPATH заканчивается как хранилище для пользовательских библиотек того типа, что 95% других основных языков (C / C ++, perl, python, ruby ​​и т. д. и т. д.). Так что это сложная парадигма для проглатывания, если вы привыкли к общему программированию на большинстве других основных языков.

Отклонение идет так далеко, что очевидно ant намеренно удаляет $CLASSPATH из окружающей среды, но простой способ обойти это просто использовать другую переменную.

 <property name="classpath" location="${env.JAVALIBPATH}"/>

Это будет работать без сбоев с обоими командами <javac> и <java> (classpath="${classpath}), что хорошо, потому что если вы попробуете это вместо этого:

 <property name="classpath" location="${env.CLASSPATH}"/>

Нет опции includeAntRuntime="false" для <java>, которая позволила бы этому работать. Вы просто не можете получить $CLASSPATH, и кто-то пошел на все, чтобы убедиться в этом (без, по-видимому, и yikes, добавив в тяжелый взлом JavaScript).

Конечно, это означает, что вам нужно использовать отдельную переменную env, и для вашей распределенной / производственной версии придерживайтесь Java "Извините, нет пользовательских библиотек!" парадигма. Это не большая проблема, если вы используете имя переменной, которое, если оно будет задействовано, почти наверняка будет неопределенным в целевой системе.

0 голосов
/ 23 июня 2011

Если кто-то новичок в мире java / ANT, люди, которые предлагают maven, являются идиотами, что бы ни случилось с принципом KISS?

OP, вместо использования мерзости javascript, попробуйте это

<project default="build">
<property name="src" value="src" />
<property name="obj" value="obj" />

<property name="parent.dir" value="/jakarta-tomcat/common/lib" />
<path id="project.class.path">
    <pathelement location="lib/" />
    <fileset dir="${parent.dir}" includes="**/*.jar" />
</path>

<target name="build">
    <delete dir="${obj}" />
    <mkdir dir="${obj}" />
    <javac srcdir="${src}" destdir="${obj}" includes="**/*.java" excludes="**/package-info.java **/deprecated/*.java" debug="true" debuglevel="source,lines" classpathref="project.class.path" />
</target>

0 голосов
/ 07 мая 2011

Су ... кажется, я должен ответить на вопрос сам. Передача исходного пути к классу в задачу javac может быть достигнута с помощью:

<!-- load environment into the env property -->
<property environment="env" />

<javac srcdir="${src}" destdir="${obj}"
    includes="**/*.java"
    excludes="**/package-info.java **/deprecated/*.java"
    includeAntRuntime="no" includeJavaRuntime="no"
    debug="true" debuglevel="source,lines"
>
    <!-- add -classpath option manually -->
    <compilerarg value="-classpath" />
    <compilerarg value="${env.CLASSPATH}" />
    <compilerarg value="-Xlint"/>
</javac>

Это помогает, по крайней мере, настолько, что задача javac теперь проходит правильный путь к классу. Тем не менее, он все еще не будет работать, теперь явака плюет на эти жалобы:

[javac] warning: [path] bad path element "D:\local\lib\java\*": no such file or directory
[javac] warning: [path] bad path element "C:\lib\java\*": no such file or directory
[javac] warning: [path] bad path element "C:\lib\java\db\*": no such file or directory

Это прямая ложь, эти пути очень существуют. Я использую их все время, и если я вручную создаю эквивалентный вызов javac в оболочке, это работает как шарм. Я подозреваю, что javac от ant не разрешает файлы jar в этих каталогах. Я должен изучить это.

UPDATE

Это действительно, как я и подозревал, подстановочный знак не разрешается в отдельных существующих файлах jar с помощью задачи javac. Мне удалось сделать разрешение вручную, и теперь оно работает как надо. И это решение фактически было борьбой само по себе. Поэтому я оставлю здесь решение для тех бедных душ, которые борются с той же глупостью, надеюсь, прежде чем они попросят людей, которым нечем заняться, кроме дерьма вокруг (да, Анон, говоря о тебе).

Оказывается, муравью не хватает самой базовой функциональности, которую можно ожидать от инструмента сборки. Также оказывается, что я не первый, кто это замечает. Хотя решения редки, - это очень хороший пост о Использование JavaScript, чтобы сделать Apache Ant менее болезненным , что действительно спасло мой день. Да, муравей действительно может быть написан на скрипте, который, кажется, не очень известен, хотя это не держится в секрете . Вы можете смело предположить, что Javascript уже доступен без установки дополнительных библиотек, если вы запускаете ant на Java 6.

Так ... до дела. Вот эта вещь:

<target name="expand_classpath">
    <script language="javascript"><![CDATA[
        // the original classpath
        var ocp = java.lang.System.getenv("CLASSPATH");
        //  ... split in parts
        var ocp_parts = ocp.split(project.getProperty("path.separator"));

        // where our individual jar filenames go,
        //  together with pure directories from ocp_parts
        var expanded_parts = [ ];

        for each (var part in ocp_parts) {
            if (part.endsWith('*')) {
                var dir = part.substring(0, part.length() - 1);
                var f = new java.io.File(dir);

                // don't know how to construct a java.io.FilenameFilter,
                //  therefore filter the filenames manually
                for each (var file in f.listFiles())
                    if (file.getPath().endsWith('.jar'))
                        expanded_parts.push(file.getPath());
            } else
                expanded_parts.push(part);
        }

        var expanded = expanded_parts.join(project.getProperty("path.separator"));
        project.setProperty("classpath.expanded", expanded);
    ]]></script>

    <!-- <echo message="classpath.expanded = ${classpath.expanded}" /> -->
</target>

<target name="build" depends="expand_classpath">
    <mkdir dir="${obj}" />

    <javac srcdir="${src}" destdir="${obj}"
        classpath="${classpath.expanded}"
        includes="**/*.java"
        excludes="**/package-info.java **/deprecated/*.java"
        includeAntRuntime="no" includeJavaRuntime="no"
        debug="true" debuglevel="source,lines"
    >
        <compilerarg value="-Xlint"/>
        <compilerarg value="-Xlint:-fallthrough"/>
    </javac>
</target>
0 голосов
/ 07 мая 2011

В качестве альтернативы есть Задачи Maven Ant .Это позволит вам использовать механизм зависимости Maven таким образом, который, IMO, будет чище, чем Ivy.Но это все еще не очень хорошее решение.

0 голосов
/ 07 мая 2011

Я предполагаю, что ваши "популярные" JAR-файлы - это хорошо известные проекты с открытым исходным кодом. Это означает, что они доступны в центральном хранилище Maven.

Хотя я считаю, что использование Maven - лучший ответ на этот вопрос, вы также можете взломать что-нибудь, используя задачу Ant <get>. Например, чтобы загрузить JAR JUnit (может иметь опечатки):

<property name="dependency.dir" value="${basedir}/dependencies"/>

<property name="junit.jar" value="junit-4.8.2.jar"/>
<property name="junit.url" value="http://search.maven.org/remotecontent?filepath=junit/junit/4.8.2/${junit.jar}"/>

<target name="download.dependencies">
    <mkdir dir="${dependency.dir}/>
    <get url="${junit.url}" dest="${dependency.dir}/${junit.jar}"/>
</target>

Конечно, если вы сделаете это, вам придется тщательно настраивать ваши сценарии сборки, чтобы не выполнять загрузку при каждом запуске. И вы увеличите нагрузку на репозиторий Maven Central.

...