Java: come posso compilare un'intera struttura di directory di codice?


84

Il caso d'uso è semplice. Ho ottenuto i file sorgente che sono stati creati utilizzando Eclipse. Quindi, esiste una struttura di directory profonda, in cui qualsiasi classe Java potrebbe fare riferimento a un'altra classe Java nella stessa cartella figlio, fratello o padre.

Come compilo l'intera cosa dal terminale usando javac?


Per curiosità, quale sistema operativo stai utilizzando: Windows, Linux, Mac, ecc.? Questo potrebbe aiutare a rispondere alla domanda
Zach L

1
Non ho compilato java sulla riga di comando da un paio d'anni ma penso che se passi il file contenente il tuo main () a javac, cercherà tutti gli altri file di cui ha bisogno per compilare come possono essere tutte le tue dipendenze scoperto a partire dal file contenente main ().
Endophage

Risposte:


59

Devi conoscere tutte le directory o essere in grado di utilizzare caratteri jolly ..

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

2
L'ho capito: elenca tutti i file .java dopo javac usando i loro nomi o caratteri jolly.
euphoria83

54
O semplicemente usa javac $(find . -name "*.java").
Georg Schölly


41

Se tutto ciò che vuoi fare è eseguire la tua classe principale (senza compilare i .javafile da cui non dipende la classe principale), puoi fare quanto segue:

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

o

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

javac risolverebbe automaticamente tutte le dipendenze e compilerebbe anche tutte le dipendenze.


5
Questa è di gran lunga la soluzione di lavoro più semplice. Perché alla gente non piace?
Alphaaa

12
Probabilmente perché la sua semplicità ignora il fatto che molti lavori di compilazione per la libreria o il codice di supporto non avranno un metodo principale che colleghi a tutte le dipendenze richieste. È una buona risposta, ma non la userei mai in nessun framework / codebase pubblico.
Ajax

4
IMHO, framework o altri progetti pubblici dovrebbero utilizzare un qualche tipo di gestione delle build. Questo tipo di compilazione ha senso solo su piccoli progetti privati.
svenwltr

@Ajax ma se è così, puoi anche usare l' -sourcepath .opzione e quindi nominare il file principale per lo stesso effetto
coderatchet

1
Chi dice che c'è una principale? Chi dice che non ci sono quattro condutture? Ogni classe che desideri nel tuo output è anche referenziata da main (e non usando META-INF / services o altre tecniche di caricamento dei servizi). Se tutto ciò che stai facendo è testare un main, questo metodo va bene, tuttavia, non riesce a risolvere il compito completo di "compilare tutti i file java in una data directory". Un sistema di compilazione corretto è il numero 1, gli strumenti cli come il find . -type f -name "*.java" | xargs javac numero 2 e questo metodo solo se esiste un unico punto di ingresso del metodo principale che comprende l'intera app.
Ajax

12

Vorrei prendere Jon suggerimento s' e utilizzare Formica, dal momento che questo è un compito piuttosto complesso.

Tuttavia, se sei determinato a ottenere tutto in una riga nel Terminale, su Linux potresti usare il comando find . Ma non lo consiglio affatto, poiché non vi è alcuna garanzia che, ad esempio, Foo.java verrà compilato dopo Bar.java, anche se Fooutilizza Bar. Un esempio potrebbe essere:

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

Se tutte le tue classi non sono state ancora compilate, se c'è una classe di cablaggio o driver principale (fondamentalmente quella contenente il tuo metodo principale), la compilazione di quella classe principale individualmente dovrebbe compilare la maggior parte del progetto, anche se si trovano in cartelle diverse, poiché Javac proverà al meglio delle sue capacità per risolvere i problemi di dipendenza.


1
su Windows si può usare find_gnu . -type f -name "*.java" | xargs javacuna volta che la versione GNU di find.exe è stata rinominata find_gnu.exe. Ho ricevuto il mio gnu find.exe da msysgit.
n611x007

O su batch di Windows puro: for /f "usebackq" %f in (``dir /s /b *.java``) do javac %f(usa virgolette singole in dir /s /bma non riesco a trovare un modo per formattarlo correttamente).
Matthieu

Penso che la findsoluzione sia problematica perché compila ogni classe java separatamente, rendendola molto lenta.
AlikElzin-kilaka

12

Di seguito è riportato il metodo che ho trovato:

1) Crea un elenco di file con percorsi relativi in ​​un file (ad esempio FilesList.txt) come segue (separati da spazi o righe):

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

2) Usa il comando:

javac @FilesList.txt -d classes

Questo compilerà tutti i file e metterà i file di classe nella directory delle classi.

Il modo più semplice per creare FilesList.txt è questo: vai alla directory principale di origine.

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

Ma questo popolerà il percorso assoluto. Utilizzando un editor di testo "Sostituisci tutto" il percorso fino alla directory di origine (includi \ alla fine) con "" (cioè stringa vuota) e Salva.


questo è il modo più "nativo", poiché javac supporta un file "batch"
lovespring

L'approccio "dir * .java / s / b> FilesList.txt" non funzionerà se un percorso contiene spazi. javac si lamenterà di FilesList.txt
aderesh

10

Le risposte già esistenti sembrano riguardare solo se stessi con i file * .java stessi e non come farlo facilmente con i file di libreria che potrebbero essere necessari per la compilazione.

Una bella situazione di una riga che ottiene ricorsivamente tutti i file * .java e include i file * .jar necessari per la creazione è:

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

Qui il file bin è la destinazione dei file di classe, lib (e potenzialmente la directory di lavoro corrente) contiene i file di libreria e tutti i file java nella directory src e sotto vengono compilati.



9

Dovresti usare qualcosa come Ant per farlo in modo gerarchico:

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

Avrai bisogno di creare uno script di build con un target chiamato compile contenente quanto segue:

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

Quindi sarai in grado di compilare tutti i file eseguendo:

 ant compile

In alternativa, importa il tuo progetto in Eclipse e compilerà automaticamente tutti i file sorgente per quel progetto.


sfortunatamente, questo deve essere fatto su un server che non supporta ant.
euphoria83

2

C'è un modo per farlo senza usare un carattere pipe, il che è comodo se stai biforcando un processo da un altro linguaggio di programmazione per farlo:

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

Anche se sei in Bash e / o non ti dispiace usare una pipe, puoi fare:

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

2

Soluzione Windows: supponendo che tutti i file contenuti nella sottodirectory "src" e che si desideri compilarli in "bin".

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

Se src contiene un file .java immediatamente sotto di esso, allora è più veloce

javac src\\*.java -d bin

1
funziona, ma superslow: javac viene chiamato con un solo file per chiamata, quindi se ne hai molti ...
St.Shadow
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.