opción javac para compilar todos los archivos java en un directorio dado de forma recursiva

127

Estoy usando el compilador javac para compilar archivos java en mi proyecto. Los archivos se distribuyen en varios paquetes de la siguiente manera: com.vistas.util, com.vistas.converter, com.vistas.LineHelper, com.current.mdcontect.

Cada uno de estos paquetes tiene varios archivos java. Estoy usando javac así:

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

(en una línea)

En lugar de dar tantas rutas, ¿cómo puedo pedirle al compilador que compile recursivamente todos los archivos java del directorio com primario?

usuario496934
fuente
2
Realmente deberías echar un vistazo a herramientas como Ant o Maven.
Laurent Pireyn
Esta publicación SO podría ser útil stackoverflow.com/questions/864630/…
Gopi

Respuestas:

220

También sugeriría usar algún tipo de herramienta de compilación ( Ant o Maven , Ant ya está sugerido y es más fácil comenzar con él) o un IDE que maneja la compilación (Eclipse usa compilación incremental con estrategia de conciliación, y ni siquiera tiene que hacerlo cuidado de presionar cualquier botón "Compilar" ).

Usando Javac

Si necesita probar algo para un proyecto más grande y no tiene ninguna herramienta de compilación adecuada cerca, siempre puede usar un pequeño truco que javacofrece: los nombres de clase para compilar se pueden especificar en un archivo. Simplemente tiene que pasar el nombre del archivo javaccon el @prefijo.

Si puede crear una lista de todos los *.javaarchivos en su proyecto, es fácil:

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

:: Windows
> dir /s /B *.java > sources.txt
> javac @sources.txt
  • La ventaja es que es una solución rápida y fácil.
  • El inconveniente es que tiene que regenerar el sources.txtarchivo cada vez que crea una nueva fuente o cambia el nombre de un archivo existente, lo cual es una tarea fácil de olvidar (propensa a errores) y agotadora.

Usando una herramienta de construcción

A la larga, es mejor usar una herramienta diseñada para crear software.

Usando hormiga

Si crea un build.xmlarchivo simple que describe cómo construir el software:

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

Puede compilar todo el software ejecutando el siguiente comando:

$ ant
  • La ventaja es que está utilizando una herramienta de compilación estándar que es fácil de ampliar.
  • El inconveniente es que debe descargar, configurar y aprender una herramienta adicional. Tenga en cuenta que la mayoría de los IDE (como NetBeans y Eclipse) ofrecen un gran soporte para escribir archivos de compilación, por lo que no tiene que descargar nada en este caso.

Usando Maven

Maven no es tan trivial de configurar y trabajar, pero aprenderlo paga bien. Aquí hay un gran tutorial para comenzar un proyecto en 5 minutos .

  • Su principal ventaja (para mí) es que también maneja las dependencias, por lo que no necesitará descargar más archivos Jar y administrarlos a mano y lo encontré más útil para construir, empaquetar y probar proyectos más grandes.
  • El inconveniente es que tiene una curva de aprendizaje empinada, y si a los complementos de Maven les gusta suprimir errores :-) Otra cosa es que muchas herramientas también funcionan con repositorios de Maven (como Sbt para Scala, Ivy para Ant, Graddle para Groovy) .

Usando un IDE

Ahora que lo que podría impulsar su productividad de desarrollo. Hay algunas alternativas de código abierto (como Eclipse y NetBeans , prefiero las primeras) e incluso comerciales (como IntelliJ ) que son bastante populares y potentes.

Pueden administrar la construcción del proyecto en segundo plano para que no tenga que lidiar con todas las cosas de la línea de comandos. Sin embargo, siempre resulta útil si sabe lo que sucede realmente en segundo plano para poder detectar errores ocasionales como a ClassNotFoundException.

Una nota adicional

Para proyectos más grandes, siempre se recomienda utilizar un IDE y una herramienta de compilación. El primero aumenta su productividad, mientras que el segundo hace posible utilizar diferentes IDEs con el proyecto (por ejemplo, Maven puede generar descriptores de proyecto Eclipse con un simple mvn eclipse:eclipsecomando). Además, tener un proyecto que se pueda probar / construir con un solo comando de línea es fácil de presentar a nuevos colegas y, por ejemplo, en un servidor de integración continua. Pedazo de pastel :-)

rlegendi
fuente
44
Al usarlo javac, sería mejor especificar un directorio de salida. find -name "*.java" > sources.txt && javac -d bin @sources.txt. De lo contrario, los archivos * .class se guardan en el directorio donde están las fuentes.
Maksim Dmitriev
1
Totalmente cierto. Aunque en mi opinión, si alguien acaba de comenzar a jugar javac, el concepto de CLASSPATHcómo ejecutar el código java, cómo manejar los paquetes, que debería ser la carpeta raíz para ejecutar, etc., generalmente no está claro. Por lo tanto, omití el directorio de salida. De todos modos, gracias por la sugerencia!
rlegendi
66
Para los usuarios de mac que se encuentran con esto, el findcomando es: find . -name "*.java" > sources.txt(tenga en cuenta el .)
MrDuk
@MrDuk ¿Qué significa agregar el "." ¿hacer? ¿Es para buscar dentro del directorio actual?
Brady Sheehan
@BradySheehan comenzará a buscar desde la ruta dada. "." significa comenzar desde el diccionario actual. Tenga en cuenta que tiene que especificar una ruta de descubrimiento (en OS X)
Kris
39
find . -name "*.java" -print | xargs javac 

Un poco brutal, pero funciona como el infierno. (Usar solo en programas pequeños, no es absolutamente eficiente)

Matthieu Riegler
fuente
1
Si usa esto, tenga en cuenta find ... -print0y, en xargs -0 ...cambio, no rompa los espacios en los nombres de archivo
sapht
29

Si su shell lo admite, ¿funcionaría algo así?

javac com/**/*.java 

Si su shell no es compatible **, entonces tal vez

javac com/*/*/*.java

funciona (para todos los paquetes con 3 componentes - adaptar para más o menos).

phtrivier
fuente
He intentado usar esto en el símbolo del sistema en Windows 10. ¿Alguien puede confirmar si funciona en Windows 10 o si lo estoy haciendo mal
Dan
26

En el caso habitual en el que desea compilar todo su proyecto, simplemente puede proporcionar javac con su clase principal y dejar que compile todas las dependencias requeridas:

javac -sourcepath . path/to/Main.java

freaker
fuente
Método muy simple, no se basa en archivos adicionales
linquize
Este es el mejor y el más simple para las personas que no tienen mucho tiempo para aprender Ant (como yo)
Hamza Abbad
Desafortunadamente es flojo. Si no toca Main.java, lo que probablemente no haría después de crear su segundo archivo, nada más se compila.
Tom Hawtin - tackline el
Aquí tampoco funciona bien. Algunas dependencias no se vuelven a compilar a pesar de haber cambiado. @ TomHawtin-tackline Traté de tocar antes en la página principal pero nada. Tal vez se requiere tocar todo. Aunque un poco incómodo.
mmm
4

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

(Prefiero no usar xargs porque puede dividirlos y ejecutar javac varias veces, cada uno con un subconjunto de archivos java, algunos de los cuales pueden importar otros no especificados en la misma línea de comando javac)

Si tiene un punto de entrada App.java, lo mejor es la forma de freaker con -sourcepath. Compila todos los demás archivos java que necesita, siguiendo las dependencias de importación. p.ej:

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

También puede especificar una clase de archivo de destino-dir: -d target/.

Curtis Yallop
fuente
3

Le aconsejaría que aprenda a usar la hormiga , que es muy adecuada para esta tarea y es muy fácil de entender y está bien documentada.

Simplemente tendría que definir un objetivo como este en el archivo build.xml:

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

Solo estoy usando make con un simple makefile que se ve así:

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 las fuentes de una en una y solo se vuelve a compilar si es necesario.

Edward Doolittle
fuente
1

El comando javac no sigue un proceso de compilación recursivo, por lo que debe especificar cada directorio al ejecutar el comando o proporcionar un archivo de texto con los directorios que desea incluir:

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

He estado usando esto en un proyecto Xcode JNI para construir recursivamente mis clases de prueba:

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