¿Por qué nadie usa make para Java?

162

Casi todos los proyectos de Java que he visto usan Maven o Ant. Son buenas herramientas y creo que casi cualquier proyecto puede usarlas. ¿Pero qué pasó a hacer ? Se utiliza para una variedad de proyectos que no son Java y puede manejar Java fácilmente. Seguro que tiene que descargar make.exe si usa Windows, pero Ant y Maven tampoco vienen con el JDK.

¿Hay algún defecto fundamental con make cuando se usa con Java? ¿Es solo porque Ant y Maven están escritos en Java?

Usuario1
fuente
37
Si mueve cosas y hace más que solo invocar el compilador (e incluso entonces), las cosas específicas de la plataforma se vuelven muy difíciles de manejar make. Y tener un archivo MAKE que solo funciona en un sistema no es muy bueno para un lenguaje multiplataforma.
Joey
Por otro lado, Gradle es un jugador nuevo en el espacio Java, al igual que Gant (en menor grado). Maven o Ant es una falsa dicotomía.
Michael Easter
@Michael Easter, la falsa dicotomía sería Maven / Ant vs. Make. La verdadera dicotomía, si te estoy leyendo bien, sería Gradle / Maven / Gant / Ant vs. Make. Pero es un poco difícil de decir :)
Dan Rosenstark

Respuestas:

192

El problema fundamental con Make y Java es que Make funciona bajo la premisa de que tiene que especificar una dependencia, y luego una regla para resolver esa dependencia.

Con C básico, que normalmente "para convertir un archivo main.c en un archivo main.o, ejecute" cc main.c ".

Puedes hacerlo en Java, pero rápidamente aprendes algo.

Principalmente que el compilador javac tarda en iniciarse.

La diferencia entre:

javac Main.java
javac This.java
javac That.java
javac Other.java

y

javac Main.java This.java That.java Other.java

Es noche y día.

Exacerbar eso con cientos de clases, y simplemente se vuelve insostenible.

Luego combinas eso con el hecho de que Java tiende a organizarse como grupos de archivos en directorios, vs C y otros que tienden a una estructura más plana. Make no tiene mucho soporte directo para trabajar con jerarquías de archivos.

Make tampoco es muy bueno para determinar qué archivos están desactualizados, a nivel de colección.

Con Ant, revisará y resumirá todos los archivos que están desactualizados, y luego los compilará de una vez. Make simplemente llamará al compilador de Java en cada archivo individual. Hacer que Make NO haga esto requiere suficientes herramientas externas para mostrar realmente que Make no está a la altura de la tarea.

Es por eso que surgieron alternativas como Ant y Maven.

Will Hartung
fuente
66
Entonces, para usar make en un gran proyecto Java, ¿sería necesario mantener una lista de todos los archivos .java modificados y luego llamar a javac al final? Eso suena menos que ideal para mí. Esa es la mejor respuesta que he visto hasta ahora.
Usuario1
32
Me encanta esto. Esencial, está diciendo que Ant era necesaria para abordar el hecho de que Java es demasiado lento.
cmcginty
25
No. Javac no es lento si lo usa como fue diseñado para ser usado. Es lento si lo usa para compilar un archivo a la vez.
Stephen C
77
@Casey javac no es demasiado lento. La JVM es demasiado lenta para comenzar.
Thorbjørn Ravn Andersen
77
GNU Make al menos tiene la $?variable automática que se expande a "todos los requisitos previos que son más nuevos que el objetivo". También existe la función de reglas de patrón con múltiples objetivos que ejecutarían la receta solo una vez para actualizar todos los .classarchivos. Combine eso con un poco de un uso inteligente de archivo / funciones de texto como $(wildcard), $(shell), $(eval)y se puede enseñar a su makefile para descubrir tipos de generación dispersos en toda la estructura de directorios.
Tanz87
33

El venerable makeprograma maneja lenguajes compilados por separado como C y C ++ razonablemente bien. Compila un módulo, lo utiliza #includepara extraer el texto de otros archivos de inclusión y escribe un único archivo de objeto como salida. El compilador es en gran medida un sistema uno a la vez, con un paso de enlace separado para vincular los archivos de objetos en un binario ejecutable.

Sin embargo, en Java, el compilador tiene que compilar otras clases con las que importa import. Aunque sería posible escribir algo que generara todas las dependencias necesarias a partir del código fuente de Java, de modo que makese construyeran las clases en el orden correcto, una a la vez, esto todavía no manejaría casos como las dependencias circulares.

El compilador de Java también puede ser más eficiente almacenando en caché los resultados compilados de otras clases mientras compila más clases que dependen de los resultados de las ya compiladas. Este tipo de evaluación automática de dependencia no es realmente posible makesolo.

Greg Hewgill
fuente
77
Esto parece más una respuesta make versus javac que una respuesta make versus ant / maven. Según su respuesta, ¿por qué alguien no puede usar make + javac (dar a javac un paquete completo o "módulo" a la vez, por lo que las dependencias circulares están ocultas de make)? ¿Hormiga o maven proporcionarían algún beneficio sobre ese enfoque?
Laurence Gonsalves
1
@ Laurence: Puede darle a javac un paquete completo de una vez, pero luego recompilará todo en ese paquete (ya que eso es lo que le dijo que hiciera). Es cierto que el compilador de Java es bastante rápido, pero es aún más rápido si le permite determinar qué clases son las mínimas necesarias para volver a compilar después de cambiar algo.
Greg Hewgill
¿Te refieres a decirle a javac que solo compile tu clase "principal", y luego hacer que construya automáticamente las cosas de las que depende? Lo último que verifiqué (es cierto, probablemente en 1.4) fue terriblemente poco confiable. -Xdepend fue un poco mejor (pero más lento y aún roto), y eliminaron esa bandera en 1.3.
Laurence Gonsalves
44
Además, esto todavía no explica por qué usaría Ant o Maven en lugar de solo javac ...
Laurence Gonsalves
28

La pregunta se basa en una suposición incorrecta: un número no trivial de desarrolladores sí lo utilizan make. Ver Java Build Tools: Ant vs. Maven . En cuanto a por qué un desarrollador no usaría make: muchos desarrolladores nunca lo han usado make, o lo usaron y lo odiaron con un fuego que arde a más de mil soles. Como tal, utilizan herramientas alternativas.

Hank Gay
fuente
10
Lo usamos, y el fuego es más caliente que mil y un soles.
Recicla
44
@reccles: ¿Es solo odio hacia la ingeniería de construcción o se hace a sí mismo? ¿Cómo sería mejor Ant, Maven u otra cosa mejor (es decir, es una mala herramienta para su clase)?
Usuario1
55
@ User1 maketiene muchas "características" que pueden tener sentido cuando se escribió, pero ahora son más como errores, por ejemplo, debe usar un carácter TAB, no espacios, en ciertos lugares. Ese tipo de cosas probablemente no molesta a las personas que realmente tienen experiencia make, pero nos vuelve locos al resto.
Hank Gay
44
@HankGuy: deja que tu editor se preocupe por ese detalle. Si su editor no puede manejar la configuración de espacio de tabulación <-> correctamente, obtenga un nuevo editor y será mucho más feliz. Pero tiene razón al decir que muchas características están desactualizadas, como la forma en que se manejan las dependencias dinámicas ( make depend¿alguien?)
D.Shawley
3
@ Usuario1 Es la escala del proyecto que estamos construyendo. Tenemos un miembro del personal a tiempo completo que mantiene los archivos make y las dependencias de compilación. Después de haber usado Maven, me pareció más manejable. Ahora que he dicho que Maven tampoco era perfecto. Nada es más irritante que tratar de descubrir qué configuración XML se necesita para hacer una compilación que es ligeramente diferente de la configuración prescrita.
Recicla
28

En realidad, make puede manejar la recompilación en un comando de todos los archivos Java obsoletos. Cambie la primera línea si no desea compilar todos los archivos en el directorio o si desea un orden específico ...

JAVA_FILES:=$(wildcard *.java)
#
# the rest is independent of the directory
#
JAVA_CLASSES:=$(patsubst %.java,%.class,$(JAVA_FILES))

.PHONY: classes
LIST:=

classes: $(JAVA_CLASSES)
        if [ ! -z "$(LIST)" ] ; then \
                javac $(LIST) ; \
        fi

$(JAVA_CLASSES) : %.class : %.java
        $(eval LIST+=$$<)
usuario1251840
fuente
44
¡Agradable! Estaba buscando algo así. No es necesario utilizar una herramienta de compilación diferente para cada idioma cuando el clásico universal funciona bien. ¡Gracias!
rsp
17

Todas las otras respuestas sobre los méritos técnicos de cada una son ciertas. AntyMaven puede ser más adecuado para Java que make, o como señala Hank Gay, puede que no :)

Sin embargo, usted preguntó si importa que Ant y Maven estén escritos en Java. Aunque en StackOverflow no consideramos tales pensamientos (¡cerrados! ¡No relacionados con la programación! Etc.), POR SUPUESTO ES PARTE DE LA COSA. En rails usamos Rake, los tipos C usan make, y en Java usamos Ant y Maven. Si bien es cierto que los desarrolladores de Ant o Maven cuidarán al desarrollador de Java tal vez mejor que otros, también hay otra pregunta: ¿en qué escribes las tareas de Ant? Java. Si eres un desarrollador de Java, es un ajuste fácil.

Entonces, sí, parte de esto es usar herramientas escritas en el idioma que está utilizando.

Dan Rosenstark
fuente
77
Ant también surgió en un momento en que la comunidad Java estaba enamorada de XML. (Lo que no quiere decir que XML no tenga un lugar).
Laurence Gonsalves
3
@ Laurence Gonsalves, eso es muy cierto. Pero por favor, no hablamos de modas aquí en SO :) Estaba enseñando desarrollo de Java en ese momento, y TODO era XML. Ahora sigue siendo XML, pero a nadie le importa.
Dan Rosenstark
1
El comentario sobre herramientas es interesante. makeproviene de un fondo de UNIX, por lo que las herramientas se realizan escribiendo utilidades compactas útiles y canalizándolas juntas. Esta es la razón por la cual la mayor parte de la costura se realiza mediante comandos de shell.
D.Shawley
2
@RE. Shawley, todo cierto con respecto makey pequeñas utilidades de Unix. GIT también es hijo de ese proceso. En una nota personal, no diría que no es mejor. Pero es un gran cambio de paradigma para los programadores de Java. Ant es mucho más acorde con las formas de pensar de Java.
Dan Rosenstark
12

Ant y más tarde Maven fueron diseñados para resolver algunos dolores de cabeza causados ​​por Make(al crear otros nuevos en el proceso) Es solo evolución.

... Poco después, varios proyectos Java de código abierto se dieron cuenta de que Ant podía resolver los problemas que tenían con Makefiles ...

De http://ant.apache.org/faq.html#history

Si resuelven algo o simplemente crean un formato adicional para aprender es un tema subjetivo. La verdad es que es más o menos la historia de cada nuevo invento: el creador dice que resuelve muchos problemas y los usuarios originales dicen que esas son virtudes.

La principal ventaja que tiene es la posibilidad de integrarse con Java.

Supongo que sería una historia similar, rakepor ejemplo.

OscarRyz
fuente
44
Eso no es muy específico. ¿Qué dolores de cabeza causados ​​por make resuelve Maven?
Laurence Gonsalves
1
@Gonsalves: Bueno, ese es uno de los aspectos subjetivos de cada nueva tecnología, el creador de la alternativa dice que resuelve muchos problemas y los creadores de la tecnología reemplazada dicen que esos no son defectos sino virtudes, etc. Creo que en esta situación particular fue la integración de Java y la compilación cruzada fuera de la caja
OscarRyz
2
[Refiriéndose a su edición de la respuesta, no a su comentario más reciente] Eso todavía no explica qué problemas se resolvieron, solo que la hormiga creadora afirma que los problemas se resolvieron ...: - / Mi impresión ha sido que Ant creó originalmente para ser una alternativa más simple a Make. Con el tiempo, la gente descubrió que había cosas que faltaban y, por lo tanto, agregaron características hasta que Ant se volvió tan complejo como make, pero con binutils incorporado (make se basa en gran medida en herramientas externas como cp, rm, etc.), y Por supuesto, está la sintaxis XML.
Laurence Gonsalves
2
Sí, pero cuando lo mejor que puede hacer el creador de una nueva alternativa es decir "esto resuelve los problemas que tenía el anterior" sin decir cuáles son esos problemas, eso no es tan útil para aquellos que consideran qué opción usar. ¿Ant resuelve los problemas que tengo con make, o resuelve cosas que no considero que sean problemas mientras me presenta nuevos problemas?
Laurence Gonsalves
9

Uno de los principales problemas resueltos por Maven (y las configuraciones Ant habilitadas para Ivy) sobre make es la resolución de dependencia automatizada y la descarga de sus jarras de dependencia.

Ofidia
fuente
6

Creo que la explicación más probable es que varios factores desalentaron el uso de make dentro de la comunidad Java en un período crítico de tiempo (a fines de la década de 1990):

  1. Debido a que Java abarca múltiples plataformas, los programadores de Java en general no eran tan expertos en herramientas Unix como los programadores generalmente confinados a un entorno Unix (por ejemplo, programadores C y Perl). Tenga en cuenta que esto es EN GENERAL. Sin lugar a dudas existen y fueron programadores de Java dotados con un profundo conocimiento de Unix.
  2. En consecuencia, eran menos expertos en make y no sabían cómo usar make de manera efectiva.
  3. Si bien es posible escribir un Makefile corto y simple que compila Java de manera eficiente, se requiere un cuidado adicional para hacerlo de una manera independiente de la plataforma.
  4. En consecuencia, había un apetito por una herramienta de construcción intrínsecamente independiente de la plataforma.
  5. Fue en este entorno que se crearon Ant y más tarde Maven.

En resumen, aunque make ciertamente puede usarse para proyectos Java, hubo un momento de oportunidad para convertirlo en la herramienta de compilación de facto de Java. Ese momento ha pasado.

David A. Ventimiglia
fuente
5

Hacer scripts tiende a ser inherentemente dependiente de la plataforma. Se supone que Java es independiente de la plataforma. Por lo tanto, tener un sistema de compilación que solo funciona en una plataforma para una base de origen multiplataforma es un problema.

Brian Fox
fuente
5

Respuesta corta: porque make no es bueno. Incluso en el frente C ves muchas alternativas apareciendo.

Respuesta larga: maketiene varias fallas que lo hacen apenas adecuado para compilar C, e inadecuado para compilar Java. Puede forzarlo a compilar Java, si lo desea, pero espere encontrarse con problemas, algunos de los cuales no tienen una solución o solución adecuada. Aquí hay algunos:

Resolución de dependencia

makeInherentemente espera que los archivos tengan una dependencia de árbol entre sí, en la que un archivo es el resultado de construir varios otros. Esto ya falla en C cuando se trata de archivos de encabezado. makerequiere makeque se genere un archivo de inclusión específico para representar la dependencia de un archivo C en sus archivos de encabezado, por lo que un cambio en este último provocaría la reconstrucción del anterior. Sin embargo, dado que el archivo C en sí no se recrea (simplemente se reconstruye), make a menudo requiere especificar el objetivo como.PHONY . Afortunadamente, GCC admite generar esos archivos automáticamente.

En Java, la dependencia puede ser circular, y no existe una herramienta para generar automáticamente las dependencias de clase en makeformato. antEn su Dependlugar, la tarea puede leer el archivo de clase directamente, determinar qué clases importa y eliminar el archivo de clase si alguno de ellos no está actualizado. Sin esto, cualquier dependencia no trivial puede hacer que te veas obligado a usar compilaciones limpias repetidas, eliminando cualquier ventaja de usar una herramienta de compilación.

Espacios en nombres de archivo

Si bien ni Java ni C fomentan el uso de espacios en sus nombres de archivo de código fuente, makeesto puede ser un problema incluso si los espacios están en la ruta del archivo. Considere, por ejemplo, si su código fuente existe en C:\My Documents\My Code\program\src. Esto sería suficiente para romper make. Esto se debe a que maketrata los nombres de archivo como cadenas. anttrata las rutas como objetos especiales.

Escaneo de archivos para construir

makerequiere establecer explícitamente qué archivos se construirán para cada destino. antpermite especificar una carpeta que se escaneará automáticamente en busca de archivos fuente. Puede parecer una conveniencia menor, pero considere que en Java cada nueva clase requiere un nuevo archivo. Agregar archivos al proyecto puede convertirse en una gran molestia rápidamente.

Y el mayor problema con make:

make depende de POSIX

El lema de Java es "compilar una vez que se ejecuta en todas partes". Pero restringir esa compilación a sistemas basados ​​en POSIX, en los que el soporte de Java es realmente el peor, no es la intención.

Las reglas de compilación makeson esencialmente pequeños bashscripts. A pesar de que hay un puerto makepara Windows, para que funcione correctamente, tiene que estar incluido con un puerto de bash, que incluye una capa de emulación POSIX para el sistema de archivos.

Esto viene en dos variedades:

  1. MSYS que intenta limitar la traducción POSIX a rutas de archivo y, por lo tanto, puede tener problemas desagradables al ejecutar herramientas externas que no están hechas especialmente para ello.

  2. cygwinque proporciona una emulación POSIX completa. Sin embargo, los programas resultantes tienden a depender aún de esa capa de emulación.

Por esa razón, en Windows, la herramienta de compilación estándar ni siquiera es make, sino MSBuildque también es una herramienta basada en XML, más cercana en principio ant.

Por el contrario, antestá construido en Java, puede ejecutarse en todas partes y contiene herramientas internas, llamadas "tareas", para manipular archivos y ejecutar comandos de forma independiente de la plataforma. Es lo suficientemente versátil como para que sea más fácil construir un programa C en Windows usando antque usando make.

Y un último menor:

Incluso los programas C no usan make nativamente

Es posible que inicialmente no se dé cuenta de esto, pero los programas C generalmente no se envían con un Makefile. Se envían con un script de configuración CMakeLists.txto bashque genera el actual Makefile. Por el contrario, la fuente de un programa Java creado utilizando antse envía con un antscript precompilado. A Makefilees un producto de otras herramientas: eso es lo makeinadecuado de ser una herramienta de construcción por sí sola. antes independiente y se ocupa de todo lo que necesita para su proceso de compilación de Java, sin requisitos ni dependencias adicionales.

Cuando se ejecuta anten cualquier plataforma, simplemente funciona (tm). No puedes conseguir eso con make. Es increíblemente dependiente de la plataforma y la configuración.

SlugFiller
fuente
4

A menos que no sea nadie, la suposición de que nadie está (mal) usando make for java está mal.

"Gestión de proyectos con GNU Make" (disponible bajo GFDL) contiene un capítulo completo dedicado a su uso makecon proyectos java.

Como contiene una lista larga (y con suerte justa) de los pros y los contras de usar make en lugar de otras herramientas, es posible que desee echar un vistazo allí. (ver: http://oreilly.com/catalog/make3/book/ )

mikyra
fuente
¿Es este un resumen exacto? make (en varios sabores) es utilizable para Java, pero con algo de dolor. Ant y Maven (¿y jmake ?) Hacen algunas cosas especiales que Java necesita / le gusta, para que los proyectos Java sean más rápidos y fáciles de construir. También se pueden usar para un proceso de compilación más independiente de la plataforma para proyectos que no sean Java, pero están más ajustados para Java.
Phil Perry
3

Ant es una mejora orientada a la configuración XML sobre Makefiles y Maven es una mejora de la herramienta de construcción de dependencia sobre Ant. Algunos proyectos usan los tres. Creo que los proyectos JDK solían usar una mezcla de archivos MAKE y hormiga.

Berlin Brown
fuente
1

Una gran razón es que tanto Ant como Maven (y la mayoría de las herramientas SCM, CI e IDE dirigidas a Java) están escritas en Java por / para desarrolladores de Java. Esto simplifica la integración en su entorno de desarrollo y permite que otras herramientas, como los servidores IDE y CI, integren partes de las bibliotecas ant / maven dentro de la infraestructura de compilación / implementación.

Chris Nava
fuente
1

Érase una vez que trabajé en un proyecto Java que usaba gmake. Mi recuerdo es confuso, pero IIRC nos costó mucho lidiar con la estructura de directorios de paquetes que javac espera. También recuerdo que construir archivos JAR era una molestia a menos que tuvieras algo trivial.


fuente
1

ApacheAnt no se parece en nada a Make. Make se trata de describir dependencias entre archivos y cómo construir archivos. Ant trata sobre dependencias entre "tareas", y es realmente más una forma de pegar scripts de compilación.

puede ayudarte AntVs

Venky Vungarala
fuente
Realmente me gustaría saber sobre las razones de los votos negativos.
hagello
0

Ant y Maven abordan el gráfico de dependencia de compilación y la administración del mismo desde una vista más 'moderna' ... Pero como dice Oscar, crearon sus propios problemas al intentar abordar los viejos problemas con make.

John Weldon
fuente
0

Nunca he usado GNU Make para proyectos Java, pero solía usar jmk . Lamentablemente no se ha actualizado desde 2002.

Tenía alguna funcionalidad específica de Java, pero era lo suficientemente pequeña como para incluirla en su tarball fuente sin aumentar significativamente su tamaño.

Hoy en día, supongo que cualquier desarrollador de Java con el que comparta código tiene Ant instalado.

finnw
fuente