javac Option zum rekursiven Kompilieren aller Java-Dateien in einem bestimmten Verzeichnis

127

Ich verwende den Javac-Compiler, um Java-Dateien in meinem Projekt zu kompilieren. Die Dateien werden mehrere Pakete wie folgt verteilt: com.vistas.util, com.vistas.converter, com.vistas.LineHelper, com.current.mdcontect.

Jedes dieser Pakete enthält mehrere Java-Dateien. Ich benutze Javac wie folgt:

javac com/vistas/util/*.java com/vistas/converter/*.java
      com.vistas.LineHelper/*.java com/current/mdcontect/*.java

(in einer Zeile)

Wie kann ich den Compiler bitten, alle Java-Dateien aus dem übergeordneten com-Verzeichnis rekursiv zu kompilieren, anstatt so viele Pfade anzugeben?

user496934
quelle
2
Sie sollten sich unbedingt Tools wie Ant oder Maven ansehen.
Laurent Pireyn
Dieser SO-Beitrag könnte nützlich sein stackoverflow.com/questions/864630/…
Gopi

Antworten:

220

Ich würde auch vorschlagen, eine Art Build-Tool ( Ant oder Maven , Ant wird bereits vorgeschlagen und ist einfacher zu beginnen) oder eine IDE zu verwenden, die die Kompilierung verwaltet (Eclipse verwendet die inkrementelle Kompilierung mit Abgleichsstrategie, und Sie müssen nicht einmal Pflege alle drücken „Compile“ Tasten).

Verwenden von Javac

Wenn Sie etwas für ein größeres Projekt ausprobieren müssen und keine geeigneten Build-Tools in der Nähe haben, können Sie immer einen kleinen Trick verwenden, javacder Folgendes bietet: Die zu kompilierenden Klassennamen können in einer Datei angegeben werden. Sie müssen lediglich den Namen der Datei javacmit dem @Präfix übergeben.

Wenn Sie eine Liste aller *.javaDateien in Ihrem Projekt erstellen können , ist dies ganz einfach:

# Linux / MacOS
$ find -name "*.java" > sources.txt
$ javac @sources.txt

:: Windows
> dir /s /B *.java > sources.txt
> javac @sources.txt
  • Der Vorteil ist, dass dies eine schnelle und einfache Lösung ist.
  • Der Nachteil ist, dass Sie die sources.txtDatei jedes Mal neu generieren müssen, wenn Sie eine neue Quelle erstellen oder eine vorhandene Datei umbenennen. Dies ist eine leicht zu vergessende (daher fehleranfällige) und mühsame Aufgabe.

Verwenden eines Build-Tools

Auf lange Sicht ist es besser, ein Tool zu verwenden, das zum Erstellen von Software entwickelt wurde.

Mit Ant

Wenn Sie eine einfache build.xmlDatei erstellen , in der beschrieben wird, wie die Software erstellt wird:

<project default="compile">
    <target name="compile">
        <mkdir dir="bin"/>
        <javac srcdir="src" destdir="bin"/>
    </target>
</project>

Sie können die gesamte Software kompilieren, indem Sie den folgenden Befehl ausführen:

$ ant
  • Der Vorteil ist, dass Sie ein Standard-Build-Tool verwenden, das einfach zu erweitern ist.
  • Der Nachteil ist, dass Sie ein zusätzliches Tool herunterladen, einrichten und erlernen müssen. Beachten Sie, dass die meisten IDEs (wie NetBeans und Eclipse) eine hervorragende Unterstützung für das Schreiben von Build-Dateien bieten, sodass Sie in diesem Fall nichts herunterladen müssen.

Mit Maven

Maven ist nicht so trivial einzurichten und zu bearbeiten, aber es lohnt sich zu lernen. Hier ist ein großartiges Tutorial, um ein Projekt innerhalb von 5 Minuten zu starten .

  • Der Hauptvorteil (für mich) besteht darin, dass auch Abhängigkeiten behandelt werden, sodass Sie keine Jar-Dateien mehr herunterladen und von Hand verwalten müssen. Ich fand es nützlicher, größere Projekte zu erstellen, zu verpacken und zu testen.
  • Der Nachteil ist, dass es eine steile Lernkurve hat und wenn Maven-Plugins Fehler gerne unterdrücken :-) Eine andere Sache ist, dass eine ganze Reihe von Tools auch mit Maven-Repositories funktionieren (wie Sbt für Scala, Ivy für Ant, Graddle für Groovy). .

Verwenden einer IDE

Nun, was könnte Ihre Entwicklungsproduktivität steigern. Es gibt einige Open-Source-Alternativen (wie Eclipse und NetBeans , ich bevorzuge die ersteren) und sogar kommerzielle (wie IntelliJ ), die sehr beliebt und leistungsstark sind.

Sie können das Projektgebäude im Hintergrund verwalten, sodass Sie sich nicht um alle Befehlszeilen kümmern müssen. Es ist jedoch immer praktisch, wenn Sie wissen, was tatsächlich im Hintergrund passiert, damit Sie gelegentliche Fehler wie a aufspüren können ClassNotFoundException.

Ein zusätzlicher Hinweis

Bei größeren Projekten wird immer empfohlen, eine IDE und ein Build-Tool zu verwenden. Ersteres steigert Ihre Produktivität, während letzteres die Verwendung verschiedener IDEs für das Projekt ermöglicht (z. B. kann Maven mit einem einfachen mvn eclipse:eclipseBefehl Eclipse-Projektdeskriptoren generieren ). Darüber hinaus ist es einfach, ein Projekt, das mit einem einzeiligen Befehl getestet / erstellt werden kann, neuen Kollegen und beispielsweise einem Server für die kontinuierliche Integration vorzustellen. Stück Kuchen :-)

rlegendi
quelle
4
Bei der Verwendung javacist es besser, ein Ausgabeverzeichnis anzugeben. find -name "*.java" > sources.txt && javac -d bin @sources.txt. Andernfalls werden * .class-Dateien in dem Verzeichnis gespeichert, in dem sich die Quellen befinden.
Maksim Dmitriev
1
Absolut wahr. Obwohl meiner Meinung nach, wenn jemand gerade angefangen hat, damit herumzuspielen javac, das Konzept CLASSPATH, wie Code ausgeführt wird java, wie mit Paketen umgegangen wird, die der Stammordner für die Ausführung sein sollten usw., normalerweise nicht klar ist. Daher habe ich das Ausgabeverzeichnis weggelassen. Trotzdem danke für den Vorschlag!
Rlegendi
6
Für Mac-Benutzer, die darauf findfind . -name "*.java" > sources.txt.
stoßen
@ MrDuk Was bedeutet das Hinzufügen des "." machen? Ist es für die Suche im aktuellen Verzeichnis?
Brady Sheehan
@BradySheehan beginnt mit der Suche auf dem angegebenen Pfad. "." bedeutet vom aktuellen Wörterbuch ausgehen. Beachten Sie, dass Sie haben einen Weg für find (in OS X) angeben
Kris
39
find . -name "*.java" -print | xargs javac 

Ein bisschen brutal, funktioniert aber höllisch. (Nur für kleine Programme verwenden, es ist absolut nicht effizient)

Matthieu Riegler
quelle
1
Wenn Sie dies verwenden, berücksichtigen Sie find ... -print0und xargs -0 ...stattdessen nicht Leerzeichen in Dateinamen zu brechen
sapht
29

Wenn Ihre Shell dies unterstützt, würde so etwas funktionieren?

javac com/**/*.java 

Wenn Ihre Shell nicht unterstützt **, dann vielleicht

javac com/*/*/*.java

funktioniert (für alle Pakete mit 3 Komponenten - mehr oder weniger anpassen).

phtrivier
quelle
Ich habe versucht, dies in der Eingabeaufforderung unter Windows 10 zu verwenden. Kann jemand bestätigen, ob es unter Windows 10 funktioniert oder ob ich es falsch mache, bitte
Dan
26

In dem üblichen Fall, in dem Sie Ihr gesamtes Projekt kompilieren möchten, können Sie javac einfach mit Ihrer Hauptklasse versorgen und alle erforderlichen Abhängigkeiten kompilieren lassen:

javac -sourcepath . path/to/Main.java

Freaker
quelle
Sehr einfache Methode,
basiert
Dies ist die beste und einfachste für Leute, die nicht viel Zeit haben, um Ant zu lernen (wie ich)
Hamza Abbad
Es ist leider faul. Wenn Sie nicht berühren Main.java, was Sie wahrscheinlich nicht gleich nach dem Erstellen Ihrer zweiten Datei tun würden, wird nichts anderes zum Compiler.
Tom Hawtin - Tackline
Funktioniert auch hier nicht gut. Einige Abhängigkeiten werden trotz Änderung nicht neu kompiliert. @ TomHawtin-Tackline Ich habe schon mal versucht, auf der Hauptstraße zu berühren, aber nichts. Möglicherweise ist es erforderlich, alle zu berühren. Etwas umständlich.
mmm
4

javac -cp "jar_path/*" $(find . -name '*.java')

(Ich bevorzuge es, xargs nicht zu verwenden, da es sie aufteilen und javac mehrmals ausführen kann, jeweils mit einer Teilmenge von Java-Dateien, von denen einige andere importieren können, die nicht in derselben javac-Befehlszeile angegeben sind.)

Wenn Sie einen App.java-Einstiegspunkt haben, ist der Freaker-Weg mit -sourcepath am besten. Es kompiliert jede andere Java-Datei, die es benötigt, und folgt dabei den Importabhängigkeiten. z.B:

javac -cp "jar_path/*" -sourcepath src/ src/com/companyname/modulename/App.java

Sie können auch ein Verzeichnis der Zielklassendatei angeben : -d target/.

Curtis Yallop
quelle
3

Ich würde Ihnen raten, mit Ameise zu lernen , die für diese Aufgabe sehr gut geeignet und sehr leicht zu erfassen und gut dokumentiert sind.

Sie müssten lediglich ein solches Ziel in der Datei build.xml definieren:

<target name="compile">
    <javac srcdir="your/source/directory"
           destdir="your/output/directory"
           classpath="xyz.jar" />
</target>
JB Nizet
quelle
2

Ich verwende make nur mit einem einfachen Makefile, das so aussieht:

JAVAC = javac -Xlint:unchecked
sources = $(shell find . -type f -name '*.java')
classes = $(sources:.java=.class)

all : $(classes)

clean :
        rm -f $(classes)

%.class : %.java
        $(JAVAC) $<

Es kompiliert die Quellen einzeln und kompiliert sie nur bei Bedarf neu.

Edward Doolittle
quelle
1

Der Befehl javac folgt keinem rekursiven Kompilierungsprozess. Sie müssen also entweder jedes Verzeichnis angeben, wenn Sie den Befehl ausführen, oder eine Textdatei mit Verzeichnissen bereitstellen, die Sie einschließen möchten:

javac -classpath "${CLASSPATH}" @java_sources.txt
gvalenncia
quelle
0

Ich habe dies in einem Xcode JNI-Projekt verwendet, um meine Testklassen rekursiv zu erstellen:

find ${PROJECT_DIR} -name "*.java" -print | xargs javac -g -classpath ${BUILT_PRODUCTS_DIR} -d ${BUILT_PRODUCTS_DIR}
Bischofshaus
quelle