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


84

Випадок використання простий. Я отримав вихідні файли, створені за допомогою Eclipse. Отже, існує глибока структура каталогів, де будь-який клас Java може посилатися на інший клас Java у тій самій, дочірній, братській або батьківській папці.

Як скомпілювати всю цю справу з терміналу за допомогою javac?


З цікавості яку ОС ви використовуєте - Windows, Linux, Mac тощо? Це може допомогти відповісти на запитання
Zach L

1
Я не компілював java в командному рядку протягом декількох років, але я думаю, що якщо ви просто передасте файл, що містить ваш main (), javac, він буде шукати всі інші файли, які йому потрібно скомпілювати, оскільки всі ваші залежності можуть бути виявлено, починаючи з файлу, що містить main ().
Ендофаг

Відповіді:


59

Ви повинні знати всі каталоги, або мати можливість використовувати символи підстановки ..

javac dir1/*.java dir2/*.java dir3/dir4/*.java dir3/dir5/*.java dir6/*src/*.java

2
я зрозумів: просто перелічіть усі файли .java після javac, використовуючи їх імена або символи підстановки.
euphoria83

52
Або просто використовувати javac $(find . -name "*.java").
Георг Шеллі


40

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

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

або

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

javac автоматично вирішив би всі залежності та також скомпілював усі залежності.


4
Це, безумовно, найпростіше робоче рішення. Чому людям це не подобається?
Alphaaa

11
Можливо, тому, що його простота ігнорує той факт, що багато завдань компіляції для бібліотеки або коду підтримки не матимуть основного методу, що зв’язує всі необхідні залежності. Це хороша відповідь, але не та, яку я коли-небудь використовував би в будь-якій структурі / загальнодоступній кодовій базі.
Аякс

4
ІМХО, фреймворки або будь-які інші публічні проекти повинні використовувати певний тип управління збіркою. Цей вид компіляції має сенс лише для невеликих приватних проектів.
svenwltr

@Ajax, але якщо це так, ви також можете скористатися -sourcepath .опцією, а потім назвати головний файл для того ж ефекту
coderatchet

1
Хто каже, що є головне? Хто каже, що немає чотирьох мереж? Чи на кожен клас, який ви хочете у своєму результаті, посилається main (а ​​не використання META-INF / сервісів чи іншої техніки завантаження служби). Якщо все, що ви робите, - це тестування main, цей метод непоганий, однак він не може вирішити повне завдання "скомпілювати всі файли Java у даному каталозі". Належна система збірки - це №1, інструменти cli на кшталт find . -type f -name "*.java" | xargs javac числа 2, і цей метод лише у тому випадку, якщо є одна основна точка входу в метод, яка охоплює всю програму.
Аякс

12

Я взяв би пропозицію Джона і використав Ant, оскільки це досить складне завдання.

Однак, якщо ви твердо вирішили отримати все в одному рядку в терміналі, в Linux ви можете скористатися командою find . Але я взагалі не рекомендую цього, оскільки немає жодної гарантії, що, скажімо, Foo.java буде скомпільовано після Bar.java, навіть незважаючи на Fooвикористання Bar. Прикладом може бути:

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

Якщо всі ваші класи ще не скомпільовані, якщо є один основний джгут або клас драйвера (в основному той, що містить ваш основний метод), компіляція цього основного класу повинна компілювати більшість проектів, навіть якщо вони знаходяться в різних папках, Явак намагатиметься з усіх сил вирішувати проблеми залежності.


1
у вікнах можна використовувати, find_gnu . -type f -name "*.java" | xargs javacяк тільки gnu-версію find.exe перейменовано на 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

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 та нижче компілюються.


У мене виникла проблема зі складанням вихідного коду клієнта, згенерованого
сваггером

9

Вам потрібно було б використовувати щось на зразок Ant, щоб зробити це ієрархічно:

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

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

<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
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.