Java: Wie kann ich eine gesamte Verzeichnisstruktur von Code kompilieren?

84

Der Anwendungsfall ist einfach. Ich habe die Quelldateien erhalten, die mit Eclipse erstellt wurden. Es gibt also eine tiefe Verzeichnisstruktur, in der jede Java-Klasse auf eine andere Java-Klasse im selben, untergeordneten, geschwisterlichen oder übergeordneten Ordner verweisen kann.

Wie kompiliere ich das Ganze mit javac vom Terminal aus?

Euphorie83
quelle
Welches Betriebssystem verwenden Sie aus Neugier - Windows, Linux, Mac usw.? Dies könnte helfen, die Frage zu beantworten
Zach L
1
Ich habe Java seit einigen Jahren nicht mehr über die Befehlszeile kompiliert, aber ich denke, wenn Sie nur die Datei mit Ihrem main () an javac übergeben, werden alle anderen Dateien durchsucht, die zum Kompilieren benötigt werden, da alle Ihre Abhängigkeiten vorhanden sein können entdeckt ab der Datei mit main ().
Endophage
1
Mögliches Duplikat der Javac-Option zum rekursiven Kompilieren
Msangel

Antworten:

59

Sie müssen alle Verzeichnisse kennen oder Platzhalter verwenden können.

javac dir1/*.java dir2/*.java dir3/dir4/*.java dir3/dir5/*.java dir6/*src/*.java
Manidip Sengupta
quelle
1
Ich habe es mir gedacht: Listen Sie einfach alle .java-Dateien nach javac entweder mit ihren Namen oder mit Platzhaltern auf.
Euphorie83
49
Oder einfach benutzen javac $(find . -name "*.java").
Georg Schölly
47

Mit Bash 4 können Sie einfach Globstar aktivieren

shopt -s globstar

und dann tun

javac **/*.java
Daniel Lubarov
quelle
4
oder benutze zsh mit oh-my-zsh :)
DmitrySandalov
39

Wenn Sie nur Ihre Hauptklasse ausführen möchten (ohne die .javaDateien zu kompilieren , von denen die Hauptklasse nicht abhängt), können Sie Folgendes tun:

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

oder

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

javac würde automatisch alle Abhängigkeiten auflösen und auch alle Abhängigkeiten kompilieren.

Bharat Khatri
quelle
4
Dies ist bei weitem die einfachste Lösung. Warum mögen die Leute es nicht?
Alphaaa
11
Wahrscheinlich, weil seine Einfachheit die Tatsache ignoriert, dass viele Kompilierungsjobs für Bibliotheks- oder Supportcode keine Hauptmethode haben, die mit allen erforderlichen Abhängigkeiten verknüpft ist. Es ist eine gute Antwort, aber keine, die ich jemals in einem Framework / einer öffentlichen Codebasis verwenden würde.
Ajax
4
IMHO, Frameworks oder andere öffentliche Projekte sollten eine Art Build-Management verwenden. Diese Art der Kompilierung ist nur bei kleinen privaten Projekten sinnvoll.
Svenwltr
@ Ajax, aber wenn dies der Fall ist, können Sie auch die -sourcepath .Option verwenden und dann die Hauptdatei für den gleichen Effekt
benennen
1
Wer sagt, dass es eine Hauptleitung gibt? Wer sagt, dass es keine vier Hauptleitungen gibt? Wird jede Klasse, die Sie in Ihrer Ausgabe haben möchten, auch von main referenziert (und nicht mit META-INF / services oder einer anderen Technik zum Laden von Diensten)? Wenn Sie nur eine Hauptversion testen, ist diese Methode in Ordnung. Sie kann jedoch nicht die vollständige Aufgabe "Alle Java-Dateien in einem bestimmten Verzeichnis kompilieren" ausführen. Ein ordnungsgemäßes Build-System ist die Nummer 1, CLI-Tools wie find . -type f -name "*.java" | xargs javac die Nummer 2 und diese Methode nur, wenn es einen einzigen Einstiegspunkt für die Hauptmethode gibt, der die gesamte App umfasst.
Ajax
12

Ich würde Jons Vorschlag annehmen und Ant verwenden, da dies eine ziemlich komplexe Aufgabe ist.

Wenn Sie jedoch entschlossen sind, alles in einer Zeile im Terminal abzurufen, können Sie unter Linux den Befehl find verwenden . Ich empfehle dies jedoch überhaupt nicht, da es keine Garantie gibt, dass beispielsweise Foo.java nach Bar.java kompiliert wird, obwohl es Fooverwendet wird Bar. Ein Beispiel wäre:

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

Wenn noch nicht alle Klassen kompiliert wurden, wenn es ein Haupt-Harness oder eine Treiberklasse gibt (im Grunde die, die Ihre Hauptmethode enthält), sollte das individuelle Kompilieren dieser Hauptklasse den größten Teil des Projekts kompilieren, auch wenn sie sich seitdem in verschiedenen Ordnern befinden Javac wird nach besten Kräften versuchen, Abhängigkeitsprobleme zu lösen.

Zach L.
quelle
1
Unter Windows kann man verwenden, find_gnu . -type f -name "*.java" | xargs javacsobald die gnu-Version von find.exe in find_gnu.exe umbenannt wurde. Ich habe meine gnu find.exe von msysgit bekommen.
n611x007
Oder auf einem reinen Windows-Stapel: for /f "usebackq" %f in (``dir /s /b *.java``) do javac %f(Verwenden Sie einfache Anführungszeichen in, dir /s /baber ich kann keine Möglichkeit finden, es richtig zu formatieren.)
Matthieu
Ich denke, die findLösung ist problematisch, weil sie jede Java-Klasse separat kompiliert, was sie sehr langsam macht.
AlikElzin-Kilaka
12

Folgendes ist die Methode, die ich gefunden habe:

1) Erstellen Sie eine Liste von Dateien mit relativen Pfaden in einer Datei (z. B. FilesList.txt) wie folgt (entweder durch Leerzeichen oder durch Zeilen getrennt):

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

2) Verwenden Sie den Befehl:

javac @FilesList.txt -d classes

Dadurch werden alle Dateien kompiliert und die Klassendateien im Klassenverzeichnis abgelegt.

Die einfache Möglichkeit, FilesList.txt zu erstellen, ist folgende: Wechseln Sie in Ihr Quellstammverzeichnis.

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

Dies wird jedoch den absoluten Pfad füllen. Verwenden Sie einen Texteditor "Alle ersetzen", um den Pfad zum Quellverzeichnis (einschließlich \ am Ende) durch "" (dh leere Zeichenfolge) und Speichern.

Ameya Gokhale
quelle
Dies ist der "native" Weg, da Javac eine "Batch" -Datei unterstützt
Lovespring
Der Ansatz "dir * .java / s / b> FilesList.txt" funktioniert nicht, wenn ein Pfad Leerzeichen enthält. javac wird sich über FilesList.txt beschweren
aderesh
10

Die bereits vorhandenen Antworten scheinen sich nur mit den * .java-Dateien selbst zu befassen und nicht mit der einfachen Verwendung von Bibliotheksdateien, die möglicherweise für den Build benötigt werden.

Eine nette einzeilige Situation, die rekursiv alle * .java-Dateien abruft sowie * .jar-Dateien enthält, die zum Erstellen erforderlich sind, ist:

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

Hier ist die bin-Datei das Ziel von Klassendateien, lib (und möglicherweise das aktuelle Arbeitsverzeichnis) enthalten die Bibliotheksdateien und alle Java-Dateien im src-Verzeichnis und darunter werden kompiliert.

Demongolem
quelle
Ich habe ein Problem beim Kompilieren eines von swagger generierten Client-Quellcodes
Eenvincible
9

Sie müssten so etwas wie Ant verwenden, um dies hierarchisch zu tun:

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

Sie müssen ein Build-Skript mit einem Ziel namens compile erstellen, das Folgendes enthält:

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

Dann können Sie alle Dateien kompilieren, indem Sie Folgendes ausführen:

 ant compile

Alternativ importieren Sie Ihr Projekt in Eclipse und es kompiliert automatisch alle Quelldateien für dieses Projekt.

Jon
quelle
Leider ist dies auf einem Server durchzuführen, der ant nicht unterstützt.
Euphorie83
2

Es gibt eine Möglichkeit, dies ohne Verwendung eines Pipe-Zeichens zu tun. Dies ist praktisch, wenn Sie einen Prozess aus einer anderen Programmiersprache abspalten, um dies zu tun:

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

Wenn Sie in Bash sind und / oder nichts dagegen haben, eine Pfeife zu verwenden, können Sie Folgendes tun:

find $JAVA_SRC_DIR -name '*.java' | xargs javac -d $OUTPUT_DIR
Bolinfest
quelle
2

Windows-Lösung: Angenommen, alle Dateien befinden sich im Unterverzeichnis 'src' und Sie möchten sie zu 'bin' kompilieren.

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

Wenn src eine .java-Datei direkt darunter enthält, ist dies schneller

javac src\\*.java -d bin
Mike
quelle
1
funktioniert, aber superslow - javac wird mit nur einer Datei pro Aufruf aufgerufen, also wenn Sie viele davon haben ...
St.Shadow