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

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

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


person euphoria83    schedule 21.01.2011    source источник
comment
Из любопытства, какую ОС вы используете — Windows, Linux, Mac и т. д.? Это может помочь ответить на вопрос   -  person Zach L    schedule 22.01.2011
comment
Я не компилировал java в командной строке пару лет, но я думаю, что если вы просто передадите файл, содержащий ваш main(), в javac, он найдет все другие файлы, которые ему нужно скомпилировать, поскольку все ваши зависимости могут быть обнаруживается, начиная с файла, содержащего main().   -  person Endophage    schedule 22.01.2011
comment
возможный дубликат параметра javac для рекурсивной компиляции   -  person msangel    schedule 26.12.2014


Ответы (9)


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

javac dir1/*.java dir2/*.java dir3/dir4/*.java dir3/dir5/*.java dir6/*src/*.java
person Manidip Sengupta    schedule 21.01.2011
comment
я понял: просто перечислите все файлы .java после javac, используя их имена или подстановочные знаки. - person euphoria83; 22.01.2011
comment
Или просто используйте javac $(find . -name "*.java"). - person Georg Schölly; 07.04.2016

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

shopt -s globstar

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

javac **/*.java
person Daniel Lubarov    schedule 05.11.2011
comment
или используйте zsh с oh-my-zsh :) - person DmitrySandalov; 19.09.2014

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

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

or

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

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

person Bharat Khatri    schedule 13.03.2013
comment
Это, безусловно, самое простое рабочее решение. Почему людям это не нравится? - person Alphaaa; 07.05.2013
comment
Вероятно, потому, что его простота игнорирует тот факт, что многие задания компиляции для библиотеки или кода поддержки не будут иметь основного метода, связывающего все необходимые зависимости. Это хороший ответ, но я бы никогда не использовал его ни в одном фреймворке/общедоступной кодовой базе. - person Ajax; 21.05.2013
comment
ИМХО, фреймворки или любые другие общедоступные проекты должны использовать какое-то управление сборкой. Такой вид компиляции имеет смысл только для небольших частных проектов. - person svenwltr; 07.11.2013
comment
@Ajax, но если это так, вы также можете использовать параметр -sourcepath ., а затем назвать основной файл для того же эффекта. - person coderatchet; 18.01.2016
comment
Кто сказал, что есть главная? Кто сказал, что нет четырех сетей? Является ли каждый класс, который вы хотите в своем выводе, даже ссылаться на main (и не использовать META-INF/services или другой метод загрузки службы). Если все, что вы делаете, это тестируете файл main, этот метод хорош, однако он не может полностью решить задачу компиляции всех java-файлов в данном каталоге. Правильная система сборки — № 1, инструменты cli, такие как find . -type f -name "*.java" | xargs javac, — номер 2, и этот метод только в том случае, если есть единственная точка входа основного метода, охватывающая все приложение. - person Ajax; 18.01.2016

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

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

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

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

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

Ниже приведен метод, который я нашел:

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

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

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

javac @FilesList.txt -d classes

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

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

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

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

person Ameya Gokhale    schedule 27.03.2013
comment
это более нативный способ, так как javac поддерживает пакетный файл - person lovespring; 22.01.2016
comment
dir *.java /s /b › Подход FilesList.txt не будет работать, если путь содержит пробелы. javac будет жаловаться на FilesList.txt - person aderesh; 18.01.2017

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

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

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

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

person demongolem    schedule 24.05.2014
comment
У меня проблема с компиляцией исходного кода клиента, сгенерированного swagger - person Eenvincible; 02.02.2019

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

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

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

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

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

 ant compile

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

person Jon    schedule 21.01.2011
comment
к сожалению, это нужно делать на сервере, который не поддерживает ant. - person euphoria83; 22.01.2011

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

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

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

find $JAVA_SRC_DIR -name '*.java' | xargs javac -d $OUTPUT_DIR
person bolinfest    schedule 17.11.2012

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

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

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

javac src\\*.java -d bin
person Mike    schedule 11.10.2013
comment
работает, но супермедленно - javac вызывается только с одним файлом за вызов, так что если у вас их много... - person St.Shadow; 18.07.2016