javac option pour compiler tous les fichiers java sous un répertoire donné de manière récursive

127

J'utilise le compilateur javac pour compiler des fichiers java dans mon projet. Les fichiers sont répartis sur plusieurs paquets comme ceci: com.vistas.util, com.vistas.converter, com.vistas.LineHelper, com.current.mdcontect.

Chacun de ces packages contient plusieurs fichiers java. J'utilise javac comme ceci:

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

(en une ligne)

Au lieu de donner autant de chemins, comment puis-je demander au compilateur de compiler récursivement tous les fichiers java du répertoire com parent?

user496934
la source
2
Vous devriez vraiment jeter un oeil à des outils tels que Ant ou Maven.
Laurent Pireyn
Cet article de SO pourrait être utile stackoverflow.com/questions/864630/…
Gopi

Réponses:

220

Je suggérerais également d'utiliser une sorte d'outil de construction ( Ant ou Maven , Ant est déjà suggéré et est plus facile à démarrer) ou un IDE qui gère la compilation (Eclipse utilise une compilation incrémentielle avec une stratégie de réconciliation, et vous n'avez même pas à soin d'appuyer sur les boutons "Compiler" ).

Utilisation de Javac

Si vous avez besoin d'essayer quelque chose pour un projet plus grand et que vous n'avez pas d'outils de construction appropriés à proximité, vous pouvez toujours utiliser une petite astuce qui javacoffre: les noms de classe à compiler peuvent être spécifiés dans un fichier. Vous devez simplement passer le nom du fichier javacavec le @préfixe.

Si vous pouvez créer une liste de tous les *.javafichiers de votre projet, c'est simple:

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

:: Windows
> dir /s /B *.java > sources.txt
> javac @sources.txt
  • L'avantage est qu'il s'agit d'une solution simple et rapide.
  • L'inconvénient est que vous devez régénérer le sources.txtfichier chaque fois que vous créez une nouvelle source ou que vous renommez un fichier existant, ce qui est une tâche facile à oublier (donc sujette aux erreurs) et fastidieuse.

Utiliser un outil de construction

Sur le long terme, il est préférable d'utiliser un outil conçu pour créer des logiciels.

Utiliser Ant

Si vous créez un build.xmlfichier simple décrivant comment créer le logiciel:

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

vous pouvez compiler l'ensemble du logiciel en exécutant la commande suivante:

$ ant
  • L'avantage est que vous utilisez un outil de construction standard facile à étendre.
  • L'inconvénient est que vous devez télécharger, configurer et apprendre un outil supplémentaire. Notez que la plupart des IDE (comme NetBeans et Eclipse) offrent un excellent support pour l'écriture de fichiers de construction afin que vous n'ayez rien à télécharger dans ce cas.

Utiliser Maven

Maven n'est pas si simple à mettre en place et avec lequel travailler, mais l'apprendre paie bien. Voici un excellent tutoriel pour démarrer un projet en 5 minutes .

  • Son principal avantage (pour moi) est qu'il gère également les dépendances, vous n'aurez donc plus besoin de télécharger plus de fichiers Jar et de les gérer à la main et je l'ai trouvé plus utile pour créer, empaqueter et tester des projets plus importants.
  • L'inconvénient est qu'il a une courbe d'apprentissage abrupte, et si les plugins Maven aiment supprimer les erreurs :-) Une autre chose est que beaucoup d'outils fonctionnent également avec les référentiels Maven (comme Sbt pour Scala, Ivy pour Ant, Graddle pour Groovy) .

Utilisation d'un IDE

Voilà ce qui pourrait booster votre productivité de développement. Il existe quelques alternatives open source (comme Eclipse et NetBeans , je préfère la première) et même des alternatives commerciales (comme IntelliJ ) qui sont assez populaires et puissantes.

Ils peuvent gérer la construction du projet en arrière-plan afin que vous n'ayez pas à vous occuper de toutes les commandes en ligne. Cependant, cela est toujours pratique si vous savez ce qui se passe réellement en arrière-plan afin de pouvoir traquer des erreurs occasionnelles comme un ClassNotFoundException.

Une note supplémentaire

Pour les projets plus importants, il est toujours conseillé d'utiliser un IDE et un outil de construction. Le premier augmente votre productivité, tandis que le second permet d'utiliser différents IDE avec le projet (par exemple, Maven peut générer des descripteurs de projet Eclipse avec une simple mvn eclipse:eclipsecommande). De plus, avoir un projet qui peut être testé / construit avec une seule ligne de commande est facile à introduire à de nouveaux collègues et dans un serveur d'intégration continue par exemple. Part de gâteau :-)

rlegendi
la source
4
Lors de l'utilisation javac, il serait préférable de spécifier un répertoire de sortie. find -name "*.java" > sources.txt && javac -d bin @sources.txt. Sinon, les fichiers * .class sont enregistrés dans le répertoire où se trouvent les sources.
Maksim Dmitriev
1
Absolument vrai. Bien qu'à mon avis, si quelqu'un vient de commencer à jouer avec javac, le concept de CLASSPATH, comment exécuter du code java, comment gérer les paquets, qui devrait être le dossier racine pour l'exécution, etc. ne sont généralement pas clairs. Ainsi j'ai omis le dir de sortie. Quoi qu'il en soit, merci pour la suggestion!
rlegendi
6
Pour les utilisateurs de Mac qui rencontrent cela, la findcommande est: find . -name "*.java" > sources.txt(notez le .)
MrDuk
@MrDuk Que signifie ajouter le "." faire? S'agit-il d'une recherche dans le répertoire courant?
Brady Sheehan
@BradySheehan il commencera à rechercher à partir du chemin donné. "." signifie commencer à partir du dictionnaire actuel. Notez que vous devez spécifier un chemin pour trouver (sous OS X)
Kris
40
find . -name "*.java" -print | xargs javac 

Un peu brutal, mais ça marche comme l'enfer. (À n'utiliser que sur de petits programmes, ce n'est absolument pas efficace)

Matthieu Riegler
la source
1
Si vous utilisez ceci, considérez find ... -print0et xargs -0 ...au lieu de ne pas casser sur les espaces dans les noms de fichiers
sapht
29

Si votre shell le supporte, est-ce que quelque chose comme ça fonctionnerait?

javac com/**/*.java 

Si votre shell ne prend pas en charge **, alors peut-être

javac com/*/*/*.java

fonctionne (pour tous les packages avec 3 composants - adapter pour plus ou moins).

phtrivier
la source
J'ai essayé de l'utiliser dans l'invite de commande sur Windows 10. Quelqu'un peut-il confirmer si cela fonctionne sur Windows 10 ou si je le fais mal s'il vous plaît
Dan
26

Dans le cas habituel où vous souhaitez compiler l'ensemble de votre projet, vous pouvez simplement fournir javac avec votre classe principale et le laisser compiler toutes les dépendances requises:

javac -sourcepath . path/to/Main.java

freaker
la source
Méthode très simple, ne repose pas sur des fichiers supplémentaires
linquize
C'est le meilleur et le plus simple pour les gens qui n'ont pas beaucoup de temps pour apprendre Ant (comme moi)
Hamza Abbad
C'est paresseux malheureusement. Si vous ne touchez pas Main.java, ce que vous ne feriez probablement pas juste après la création de votre deuxième fichier, rien d'autre n'obtient le compilateur.
Tom Hawtin - tackline
Cela ne fonctionne pas bien ici non plus. Certaines dépendances ne sont pas recompilées malgré leur modification. @ TomHawtin-tackline J'ai essayé de toucher avant sur le principal mais rien. Peut-être qu'il faut toucher à tout. Un peu gênant cependant.
mmm
5

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

(Je préfère ne pas utiliser xargs car il peut les diviser et exécuter javac plusieurs fois, chacun avec un sous-ensemble de fichiers java, dont certains peuvent en importer d'autres non spécifiés sur la même ligne de commande javac)

Si vous avez un point d'entrée App.java, la méthode freaker avec -sourcepath est la meilleure. Il compile tous les autres fichiers java dont il a besoin, en suivant les dépendances d'importation. par exemple:

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

Vous pouvez également spécifier une cible de classe fichier dir: -d target/.

Curtis Yallop
la source
3

Je vous conseille d'apprendre à utiliser la fourmi , qui est très bien adaptée à cette tâche et est très facile à comprendre et bien documentée.

Il vous suffirait de définir une cible comme celle-ci dans le fichier build.xml:

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

J'utilise juste make avec un makefile simple qui ressemble à ceci:

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

all : $(classes)

clean :
        rm -f $(classes)

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

Il compile les sources une à la fois et ne recompile que si nécessaire.

Edward Doolittle
la source
1

La commande javac ne suit pas un processus de compilation récursif, vous devez donc soit spécifier chaque répertoire lors de l'exécution de la commande, soit fournir un fichier texte avec les répertoires que vous souhaitez inclure:

javac -classpath "${CLASSPATH}" @java_sources.txt
Gvalenncia
la source
0

J'ai utilisé ceci dans un projet Xcode JNI pour construire de manière récursive mes classes de test:

find ${PROJECT_DIR} -name "*.java" -print | xargs javac -g -classpath ${BUILT_PRODUCTS_DIR} -d ${BUILT_PRODUCTS_DIR}
évêquethom
la source