Java: как я могу скомпилировать всю структуру каталогов кода?

84

Вариант использования прост. Я получил исходные файлы, созданные с помощью Eclipse. Итак, существует глубокая структура каталогов, где любой класс Java может ссылаться на другой класс Java в той же, дочерней, родственной или родительской папке.

Как мне скомпилировать все это из терминала с помощью javac?

эйфория83
источник
Из любопытства, какую ОС вы используете - Windows, Linux, Mac и т. Д.? Это может помочь ответить на вопрос
Zach L
1
Я не компилировал java в командной строке пару лет, но я думаю, что если вы просто передадите файл, содержащий ваш main (), в javac, он будет искать все другие файлы, которые ему нужно скомпилировать, поскольку все ваши зависимости могут быть обнаруживается начиная с файла, содержащего main ().
Endophage

Ответы:

59

Вы должны знать все каталоги или уметь использовать подстановочные знаки ..

javac dir1/*.java dir2/*.java dir3/dir4/*.java dir3/dir5/*.java dir6/*src/*.java
Манидип Сенгупта
источник
2
Я понял: просто перечислите все файлы .java после javac, используя их имена или подстановочные знаки.
euphoria83
54
Или просто используйте javac $(find . -name "*.java").
Георг Шелли
47

В Bash 4+ вы можете просто включить globstar

shopt -s globstar

а затем сделать

javac **/*.java
Даниил Любаров
источник
4
или используйте zsh с oh-my-zsh :)
Дмитрий Сандалов
41

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

cd <root-package-directory>
javac <complete-path-to-main-class>

или же

javac -cp <root-package-directory> <complete-path-to-main-class>

javac автоматически разрешит все зависимости, а также скомпилирует все зависимости.

Бхарат Хатри
источник
5
Это, безусловно, самое простое рабочее решение. Почему людям это не нравится?
Alphaaa
12
Вероятно, потому, что его простота игнорирует тот факт, что многие задания компиляции для кода библиотеки или поддержки не имеют основного метода, связывающегося со всеми необходимыми зависимостями. Это хороший ответ, но я бы никогда не использовал его в какой-либо структуре / общедоступной кодовой базе.
Ajax
4
IMHO, фреймворки или любые другие публичные проекты должны использовать какое-то управление сборкой. Такой вид компиляции имеет смысл только в небольших частных проектах.
svenwltr 07
@Ajax, но если это так, вы также можете использовать эту -sourcepath .опцию, а затем назвать основной файл для того же эффекта
coderatchet
1
Кто сказал, что есть главное? Кто сказал, что сети не четыре? На каждый ли класс, который вы хотите в своем выводе, ссылается main (без использования META-INF / services или другой техники загрузки службы). Если все, что вы делаете, это тестируете основную программу, этот метод хорош, однако он не может решить полную задачу «скомпилировать все java файлы в заданном каталоге». Правильная система сборки - номер 1, инструменты cli, такие find . -type f -name "*.java" | xargs javac как номер 2, и этот метод только при наличии единственной точки входа основного метода, охватывающей все приложение.
Ajax
12

Я бы взял джона и использовал Ant, поскольку это довольно сложная задача.

Однако, если вы настроены поместить все это в одну строку в Терминале, в Linux вы можете использовать команду find . Но я не рекомендую это вообще, поскольку нет гарантии, что, скажем, Foo.java будет скомпилирован после Bar.java, даже если он Fooиспользует Bar. Примером может быть:

find . -type f -name "*.java" -exec javac {} \;

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

Зак Л
источник
1
в Windows можно использовать find_gnu . -type f -name "*.java" | xargs javacпосле того, как версия find.exe для gnu будет переименована в find_gnu.exe. Я получил свой gnu find.exe из msysgit.
n611x007
Или в чистом пакете Windows: for /f "usebackq" %f in (``dir /s /b *.java``) do javac %f(используйте одинарные обратные кавычки, dir /s /bно я не могу найти способ его правильно отформатировать).
Matthieu
Я думаю, что findрешение проблемное, потому что оно компилирует каждый класс java отдельно, что делает его очень медленным.
AlikElzin-kilaka 03
12

Я нашел следующий метод:

1) Составьте список файлов с относительными путями в файле (скажем, FilesList.txt) следующим образом (либо через пробел, либо через строку):

foo/AccessTestInterface.java
foo/goo/AccessTestInterfaceImpl.java

2) Используйте команду:

javac @FilesList.txt -d classes

Это скомпилирует все файлы и поместит файлы классов в каталог классов.

Теперь простой способ создать FilesList.txt таков: перейдите в исходный корневой каталог.

dir *.java /s /b > FilesList.txt

Но это заполнит абсолютный путь. Используя текстовый редактор «Заменить все», укажите путь к исходному каталогу (включая \ в конце) на «» (т.е. пустую строку) и сохраните.

Амея Гокхале
источник
это более «родной» способ, поскольку javac поддерживает «пакетный» файл
lovespring
Подход «dir * .java / s / b> FilesList.txt» не будет работать, если путь содержит пробелы. javac будет жаловаться на FilesList.txt
aderesh
10

Уже существующие ответы, похоже, касаются только самих файлов * .java, а не того, как легко сделать это с файлами библиотеки, которые могут потребоваться для сборки.

Хорошая однострочная ситуация, которая рекурсивно получает все файлы * .java, а также включает файлы * .jar, необходимые для сборки:

javac -cp ".:lib/*" -d bin $(find ./src/* | grep .java)

Здесь bin-файл является местом назначения файлов классов, lib (и, возможно, текущий рабочий каталог) содержит файлы библиотеки, а все java-файлы в каталоге src и ниже компилируются.

демонголем
источник
У меня проблема с компиляцией исходного кода клиента, сгенерированного
Swagger
9

Чтобы сделать это иерархически, вам нужно будет использовать что-то вроде Ant:

http://ant.apache.org/manual/Tasks/javac.html

Вам нужно будет создать сценарий сборки с целью под названием compile, содержащей следующее:

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

Тогда вы сможете скомпилировать все файлы, запустив:

 ant compile

Или импортируйте свой проект в Eclipse, и он автоматически скомпилирует все исходные файлы для этого проекта.

Джон
источник
к сожалению, это нужно делать на сервере, который не поддерживает ant.
euphoria83
2

Есть способ сделать это без использования вертикальной черты, что удобно, если для этого вы создаете процесс с другого языка программирования:

find $JAVA_SRC_DIR -name '*.java' -exec javac -d $OUTPUT_DIR {} +

Хотя, если вы используете Bash и / или не возражаете против использования канала, вы можете:

find $JAVA_SRC_DIR -name '*.java' | xargs javac -d $OUTPUT_DIR
Болинфест
источник
2

Решение для Windows: предполагается, что все файлы содержатся в подкаталоге src, и вы хотите скомпилировать их в bin.

for /r src %i in (*.java) do javac %i -sourcepath src -d bin

Если src содержит файл .java непосредственно под ним, это быстрее

javac src\\*.java -d bin
Майк
источник
1
работает, но сверхмедленно - javac вызывается только с одним файлом за вызов, поэтому, если у вас их много ...
St.Shadow