Opzione javac per compilare ricorsivamente tutti i file java in una determinata directory


127

Sto usando il compilatore javac per compilare file java nel mio progetto. I file sono distribuiti su diversi pacchetti in questo modo: com.vistas.util, com.vistas.converter, com.vistas.LineHelper, com.current.mdcontect.

Ognuno di questi pacchetti ha diversi file java. Sto usando javac in questo modo:

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

(in una riga)

Invece di fornire così tanti percorsi, come posso chiedere al compilatore di compilare ricorsivamente tutti i file java dalla directory com padre?


2
Dovresti davvero dare un'occhiata a strumenti come Ant o Maven.
Laurent Pireyn,

Questo post SO potrebbe essere utile stackoverflow.com/questions/864630/…
Gopi

Risposte:


220

Vorrei anche suggerire di utilizzare un qualche tipo di strumento di compilazione ( Ant o Maven , Ant è già suggerito ed è più facile iniziare) o un IDE che gestisce la compilazione (Eclipse utilizza la compilazione incrementale con la strategia di riconciliazione e non è nemmeno necessario cura di premere qualsiasi pulsante "Compila" ).

Usando Javac

Se devi provare qualcosa per un progetto più grande e non hai strumenti di compilazione adeguati nelle vicinanze, puoi sempre usare un piccolo trucco che javacoffre: i nomi delle classi da compilare possono essere specificati in un file. Devi semplicemente passare il nome del file javaccon il @prefisso.

Se riesci a creare un elenco di tutti i *.javafile nel tuo progetto, è facile:

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

:: Windows
> dir /s /B *.java > sources.txt
> javac @sources.txt
  • Il vantaggio è che è una soluzione semplice e veloce.
  • Lo svantaggio è che devi rigenerare il sources.txtfile ogni volta che crei una nuova fonte o rinomini un file esistente che è un compito facile da dimenticare (quindi soggetto a errori) e noioso.

Utilizzando uno strumento di creazione

A lungo termine è meglio usare uno strumento progettato per creare software.

Utilizzando Ant

Se si crea un build.xmlfile semplice che descrive come compilare il software:

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

è possibile compilare l'intero software eseguendo il comando seguente:

$ ant
  • Il vantaggio è che stai usando uno strumento di costruzione standard che è facile da estendere.
  • Lo svantaggio è che devi scaricare, configurare e apprendere uno strumento aggiuntivo. Nota che la maggior parte degli IDE (come NetBeans ed Eclipse) offre un ottimo supporto per la scrittura di file di build, quindi in questo caso non devi scaricare nulla.

Usando Maven

Maven non è così banale da configurare e con cui lavorare, ma impararlo paga bene. Ecco un ottimo tutorial per iniziare un progetto in 5 minuti .

  • Il vantaggio principale (per me) è che gestisce anche le dipendenze, quindi non sarà necessario scaricare altri file Jar e gestirli manualmente e l'ho trovato più utile per costruire, impacchettare e testare progetti più grandi.
  • Lo svantaggio è che ha una ripida curva di apprendimento e se ai plugin Maven piace sopprimere gli errori :-) Un'altra cosa è che molti strumenti funzionano anche con i repository Maven (come Sbt per Scala, Ivy per Ant, Graddle per Groovy) .

Utilizzando un IDE

Ora che cosa potrebbe aumentare la produttività dello sviluppo. Ci sono alcune alternative open source (come Eclipse e NetBeans , preferisco la prima) e anche quelle commerciali (come IntelliJ ) che sono piuttosto popolari e potenti.

Possono gestire l'edificio del progetto in background in modo da non dover affrontare tutte le cose della riga di comando. Tuttavia, è sempre utile se sai cosa succede effettivamente in background in modo da poter dare la caccia a errori occasionali come aClassNotFoundException .

Una nota aggiuntiva

Per progetti più grandi, si consiglia sempre di utilizzare un IDE e uno strumento di creazione. Il primo aumenta la produttività, mentre il secondo consente di utilizzare diversi IDE con il progetto (ad esempio, Maven può generare descrittori di progetti Eclipse con un semplice mvn eclipse:eclipsecomando). Inoltre, avere un progetto che può essere testato / costruito con un comando a linea singola è facile da presentare ai nuovi colleghi e ad esempio in un server di integrazione continua. Pezzo di torta :-)


4
Durante l'utilizzo javac, sarebbe meglio specificare una directory di output. find -name "*.java" > sources.txt && javac -d bin @sources.txt. In caso contrario, i file * .class vengono salvati nella directory in cui si trovano le origini.
Maksim Dmitriev,

1
Assolutamente vero. Anche se secondo me, se qualcuno ha appena iniziato a giocare con javac, il concetto di CLASSPATH, come eseguire il codice con java, come gestire i pacchetti, che dovrebbe essere la cartella principale per l'esecuzione, ecc. Di solito non è chiaro. Così ho omesso la directory di output. Comunque, grazie per il suggerimento!
rlegendi,

6
Per gli utenti mac che si imbattono in questo, il findcomando è: find . -name "*.java" > sources.txt(nota il .)
MrDuk

@MrDuk Cosa significa aggiungere il "." fare? È per la ricerca nella directory corrente?
Brady Sheehan,

@BradySheehan inizierà la ricerca dal percorso indicato. "" significa iniziare dal dizionario corrente. Si noti che è necessario specificare un percorso per trovare (in OS X)
Kris

39
find . -name "*.java" -print | xargs javac 

Un po 'brutale, ma funziona come l'inferno. (Utilizzare solo su piccoli programmi, non è assolutamente efficiente)


1
Se lo usi, considera find ... -print0e xargs -0 ...invece di non spezzare gli spazi nei nomi dei file
sapht

29

Se la tua shell lo supporta, qualcosa di simile funzionerebbe?

javac com/**/*.java 

Se la tua shell non supporta **, allora forse

javac com/*/*/*.java

funziona (per tutti i pacchetti con 3 componenti - adattarsi per più o meno).


Ho tentato di utilizzare questo nel prompt dei comandi su Windows 10. Qualcuno può confermare se funziona su Windows 10 o se lo sto facendo male per favore
Dan

26

Nel solito caso in cui desideri compilare l'intero progetto, puoi semplicemente fornire a javac la tua classe principale e lasciare che compili tutte le dipendenze richieste:

javac -sourcepath . path/to/Main.java


Metodo molto semplice, non si basa su file extra
linquize il

Questo è il migliore e il più semplice per le persone che non hanno molto tempo per imparare la formica (come me)
Hamza Abbad

Purtroppo è pigro. Se non tocchi Main.java, cosa che probabilmente non avresti fatto dopo aver creato il tuo secondo file, nient'altro diventa compilatore.
Tom Hawtin - tackline

Anche qui non funziona bene. Alcune dipendenze non vengono ricompilate nonostante siano state modificate. @ TomHawtin-tackline Ho provato prima a toccare il main ma niente. Forse è necessario toccare tutto. Un po 'imbarazzante però.
mmm

4

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

(Preferisco non usare xargs perché può dividerli ed eseguire javac più volte, ognuno con un sottoinsieme di file java, alcuni dei quali possono importare altri non specificati nella stessa riga di comando javac)

Se si dispone di un punto di accesso App.java, il modo migliore per gli appassionati di -sourcepath. Compila tutti gli altri file java di cui ha bisogno, seguendo le dipendenze di importazione. per esempio:

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

È inoltre possibile specificare un target di classe file dir: -d target/.


3

Ti consiglierei di imparare a usare la formica , che è molto adatta per questo compito ed è molto facile da capire e ben documentata.

Dovresti solo definire una destinazione come questa nel file build.xml:

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

2

Sto solo usando make con un semplice makefile che assomiglia a questo:

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

all : $(classes)

clean :
        rm -f $(classes)

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

Compila le fonti una alla volta e ricompila solo se necessario.


1

Il comando javac non segue un processo di compilazione ricorsivo, quindi è necessario specificare ciascuna directory durante l'esecuzione del comando o fornire un file di testo con le directory che si desidera includere:

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

0

Ho usato questo in un progetto XNI JNI per costruire ricorsivamente le mie classi di test:

find ${PROJECT_DIR} -name "*.java" -print | xargs javac -g -classpath ${BUILT_PRODUCTS_DIR} -d ${BUILT_PRODUCTS_DIR}
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.