Ant: использование набора файлов с задачей javac

Я хочу использовать FileSet, чтобы точно указать, какие файлы я хочу скомпилировать с помощью задачи Javac. Я не хочу никакого скрытого поведения. Однако мои попытки провалились. Вот что у меня так далеко:

FileSet, который содержит все мои исходные файлы.

<fileset id="srcfiles" dir="${srcdir}">
    <include name="**/*.java"/>
</fileset>

И цель, которая пытается передать его в Javac.

<target name="build">
    <javac srcdir=".">
        <fileset refid="srcfiles"/>
    </javac>
</target>

Это дает мне эту ошибку: javac doesn't support the nested "fileset" element.

Прочитав документацию по Ant, я попытался изменить внутренний тег fileset в sourcepath, Это сработало в том смысле, что файлы были скомпилированы, но все равно выдало ошибку: srcfiles doesn't denote a path, Я думаю, что источник был скомпилирован только из-за неявных правил.

Как я могу явно указать javac, какие отдельные файлы я хочу скомпилировать? Или это просто не так, как муравей должен работать? Я пришел из C++, где идентификация исходных файлов является важной частью процесса сборки. Однако, учитывая требования Java к именованию файлов и структуре каталогов, возможно, неявное **/*.java шаблонное правило охватывает все варианты использования.

3 ответа

Решение

Руководство по муравьям для javac гласит:

Если вы хотите скомпилировать только явно указанные файлы и отключить механизм поиска по умолчанию в javac, то вы можете сбросить атрибут sourcepath:

<javac sourcepath="" srcdir="${src}"
       destdir="${build}" >
    <include name="**/*.java"/>
    <exclude name="**/Example.java"/>
</javac>

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

Чего ты хочешь? Скомпилировать весь код *.java из одного каталога? Или просто скомпилировать один файл?

Если вы хотите скомпилировать весь исходный код Java? Затем вы должны определить, где находится ваш файл исходного кода, а затем вы должны определить, где находится ваш каталог сборки. Этот каталог сборки предназначен для файла *.class после компиляции кода Java.

Самый простой способ: сначала вы должны создать один файл build.properties. В этом файле вы можете указать, где находится каталог с исходным кодом, где находится каталог сборки и т. Д. Это простой пример файла build.properties.

# Source Code Properties ---------------------------
project.dir=.
src.dir=${folder.project}/src
dist.dir=${folder.project}/dist
build.dir=${folder.project}/build
test.dir=${folder.project}/testing

И затем, в вашем файле build.xml вы можете скомпилировать свой код Java следующим образом:

<!-- define build.properties file -->
<property file="build.properties" />

<target name="compile" description="Compile all java code from src dir">
    <javac  srcdir="${src.dir}" 
            destdir="${build.dir}" 
     />
</target>

С помощью этой задачи ant вы можете скомпилировать весь свой Java-код в каталоге src для создания каталога.

Мышление в терминах C/C++ в этом случае бесполезно. В C/C++ у вас обычно есть Makefile, где вы перечисляете все свои файлы для компиляции и каждый *.c или же *.cc Файл - с точки зрения компилятора - не зависит друг от друга.

Для Java все наоборот: если компилятору Java будет предоставлен только один файл, а этот класс ссылается на что - то другое, то компилятор хочет видеть это "else" в двоичной форме. Компилятор попробует три вещи:

  • Это "еще" в какой-то библиотеке в classpath - если так, то эта вещь используется, потому что она уже скомпилирована
  • Это 'else' в пути назначения компилятора - возможно, он уже скомпилирован из исходного кода, поэтому просто возьмите его
  • Это что-то еще, где исходный файл может быть найден в исходном пути компилятора - если это так, то сначала скомпилируйте его, а затем вернитесь к реальной задаче.

Это немного упрощено, но уже показывает большинство моментов, в которых C/C++ отличается:

  • Исходные файлы не являются независимыми друг от друга.
  • Компилятор может захотеть скомпилировать больше вещей, чем вы можете догадаться как новичок.
  • Большая часть этих автоматических вещей работает только потому, что / если компилятор может угадать соответствие между .class файлы и .java файлы.
  • В Java не так много аргументов для компилятора. И все эти настройки применяются к каждому исходному файлу. В C/C++, с другой стороны, вы можете иметь несколько килобайт define аргументы, настройки оптимизации и так далее - возможно, разные для каждого исходного файла.
  • Разработчик Java не хочет микроуправлять компилятором Java - он хочет скомпилировать все файлы в исходном каталоге.
  • Разработчик Java не хочет определять точные и формальные зависимости между исходными файлами - машина лучше справляется с такой задачей.

Все это сводится к тому, как работают Ant, Maven и любая приличная система сборки в Java: Компилируйте полные исходные каталоги. Так что да, именно так Ant хочет работать.

Другие вопросы по тегам