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 хочет работать.