Por que ninguém está usando o make for Java?

162

Quase todos os projetos Java que eu vi usam Maven ou Ant. São ferramentas excelentes e acho que qualquer projeto pode usá-las. Mas o que aconteceu para fazer ? É usado para uma variedade de projetos não Java e pode lidar facilmente com Java. Claro que você precisa baixar o make.exe se usar o Windows, mas o Ant e o Maven também não vêm com o JDK.

Existe alguma falha fundamental no make quando usado com Java? É apenas porque Ant e Maven são escritos em Java?

Usuário1
fonte
37
Se você move coisas e faz mais do que apenas chamar o compilador (e mesmo assim), as coisas específicas da plataforma ficam muito difíceis de lidar make. E ter um makefile que só funciona em um sistema não é muito bom para uma linguagem de plataforma cruzada.
Joey
Além disso, Gradle é um novo player no espaço Java, assim como Gant (em menor grau). Maven ou Ant é uma falsa dicotomia.
Michael Easter
@ Michael Easter, a falsa dicotomia seria Maven / Ant vs. Make. A verdadeira dicotomia, se eu estiver lendo direito, seria Gradle / Maven / Gant / Ant vs. Make. Mas é meio difícil de dizer :)
Dan Rosenstark

Respostas:

192

O problema fundamental do Make e Java é que o Make funciona com a premissa de que você especificou uma dependência e, em seguida, uma regra para resolvê-la.

Com C básico, que normalmente "para converter um arquivo main.c em um arquivo main.o, execute" cc main.c ".

Você pode fazer isso em java, mas aprende rapidamente algo.

Principalmente que o compilador javac é lento para iniciar.

A diferença entre:

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

e

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

é noite e dia.

Exacerbe isso com centenas de classes, e isso se torna insustentável.

Então você combina isso com o fato de que o java tende a ser organizado como grupos de arquivos em diretórios, vs C e outros que tendem a uma estrutura mais plana. O Make não tem muito suporte direto para trabalhar com hierarquias de arquivos.

O Make também não é muito bom para determinar quais arquivos estão desatualizados, no nível da coleção.

Com o Ant, ele examinará e resumirá todos os arquivos desatualizados e os compilará de uma só vez. Make simplesmente chamará o compilador java em cada arquivo individual. Fazer o make NÃO fazer isso exige ferramentas externas suficientes para realmente mostrar que o make não está preparado para a tarefa.

É por isso que alternativas como Ant e Maven surgiram.

Will Hartung
fonte
6
Portanto, para usar o make em um grande projeto Java, seria necessário manter uma lista de todos os arquivos .java alterados e chamar javac no final? Isso soa menos do que ideal para mim. Essa é a melhor resposta que eu já vi até agora.
precisa
32
Eu amo isto. Essencial você está dizendo que Ant era necessário para abordar o fato de que o javac é muito lento.
Cmcginty
25
Não. Javac não é lento se você o usar como foi projetado para ser usado. É lento se você o usar para compilar um arquivo de cada vez.
Stephen C
7
@ Casey javac não é muito lento. A JVM está muito lenta para iniciar.
Thorbjørn Ravn Andersen
7
O GNU Make pelo menos possui a $?variável automática que se expande para "todos os pré-requisitos mais recentes que o destino". Há também o recurso de regras de padrão com vários destinos que executariam a receita apenas uma vez para atualizar todos os .classarquivos. Combine isso com algum uso inteligente de arquivo / funções de texto como $(wildcard), $(shell), $(eval)e você pode ensinar seu makefile para descobrir alvos de construção espalhados por todo o seu layout de diretório.
precisa saber é o seguinte
33

O venerável makeprograma lida com linguagens compiladas separadamente como C e C ++ razoavelmente bem. Você compila um módulo, ele usa #includepara extrair o texto de outros arquivos de inclusão e grava um único arquivo de objeto como saída. O compilador é basicamente um sistema de cada vez, com uma etapa de vinculação separada para vincular os arquivos de objeto a um binário executável.

No entanto, em Java, o compilador precisa realmente compilar outras classes com as quais você importa import. Embora fosse possível escrever algo que gerasse todas as dependências necessárias do código-fonte Java, para makecriar classes na ordem correta, uma de cada vez, isso ainda não trataria casos como dependências circulares.

O compilador Java também pode ser mais eficiente, armazenando em cache os resultados compilados de outras classes enquanto compila outras classes que dependem dos resultados das que já foram compiladas. Esse tipo de avaliação automática de dependência não é realmente possível makesozinho.

Greg Hewgill
fonte
7
Isso parece mais uma resposta do tipo make versus javac do que uma resposta do make versus form / maven. Com base na sua resposta, por que alguém não pode simplesmente usar o make + javac (fornecendo ao javac um pacote inteiro ou "módulo" de cada vez, para que oculte dependências circulares do make)? Formiga ou maven forneceriam algum benefício sobre essa abordagem?
Laurence Gonsalves
1
@ Laurence: Você pode fornecer ao javac um pacote inteiro de uma só vez, mas ele recompilará tudo nesse pacote (já que foi isso que você disse para fazer). É verdade que o compilador java é bastante rápido, mas é ainda mais rápido se você deixar determinar quais classes são as mínimas necessárias para recompilar depois de alterar alguma coisa.
Greg Hewgill
Você está se referindo a dizer ao javac para compilar apenas sua classe "principal" e depois fazer com que ela construa automaticamente as coisas das quais depende? A última vez que verifiquei (provavelmente na versão 1.4) foi terrivelmente não confiável. -Xdepend foi um pouco melhor (mas mais lento e ainda está quebrado), e eles removeram essa bandeira no 1.3.
Laurence Gonsalves
4
Além disso, isso ainda não explica por que eu usaria Ant ou Maven ao invés de apenas javac reta ...
Laurence Gonsalves
28

A questão é baseada em uma suposição incorreta: um número não-trivial de desenvolvedores fazem uso make. Consulte Java Build Tools: Ant vs. Maven . Quanto ao motivo pelo qual um desenvolvedor não usaria make: muitos desenvolvedores nunca o usaram makeou o usaram e o odiaram com um fogo que queima mais que mil sóis. Como tal, eles usam ferramentas alternativas.

Hank Gay
fonte
10
Nós o usamos, e o fogo é mais quente que mil e um sóis.
reccles
4
@reccles: É apenas o ódio contra a engenharia de construção ou se faz? Como Ant, Maven ou outra coisa seria melhor (isto é, é uma ferramenta ruim para sua classe)?
usar o seguinte
5
O @ User1 makepossui muitos "recursos" que podem ter sentido quando foram escritos, mas agora são mais parecidos com bugs, por exemplo, você deve usar um caractere TAB, não espaços, em determinados lugares. Provavelmente esse tipo de coisa não incomoda as pessoas realmente experientes make, mas deixa o resto de nós doido.
Hank Gay
4
@HankGuy: deixe seu editor se preocupar com esse detalhe. Se o seu editor não conseguir lidar corretamente com as configurações de espaço da guia <->, obtenha um novo editor e você ficará muito mais feliz. Mas você está certo em dizer que muitos recursos são desatualizados como a maneira dependências dinâmicas são tratadas ( make dependalguém?)
D.Shawley
3
@ User1 É a escala do projeto que estamos construindo. Temos um membro da equipe em tempo integral, mantendo os arquivos make e construindo dependências. Tendo usado o maven, achei mais fácil de administrar. Agora, tendo dito que o maven também não era perfeito. Nada é mais irritante do que tentar descobrir qual configuração XML é necessária para fazer uma compilação um pouco diferente da configuração prescrita.
reccles
28

Na verdade, o make pode manipular a recompilação em um comando de todos os arquivos java desatualizados. Altere a primeira linha se não desejar compilar todos os arquivos no diretório ou desejar uma ordem específica ...

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+=$$<)
user1251840
fonte
4
Agradável! Eu estava procurando por algo assim. Não é necessário usar uma ferramenta de compilação diferente para todos os idiomas quando o clássico universal funciona bem. Obrigado!
Rsp1
17

Todas as outras respostas sobre os méritos técnicos de cada uma são verdadeiras. Ante Mavenpode ser mais adequado para Java do que make, ou, como Hank Gay aponta, eles podem não ser :)

No entanto, você perguntou se importa que Ant e Maven sejam escritos em Java. Embora no StackOverflow não consideremos tais pensamentos (fechados! Não relacionados à programação! Etc.), é claro que faz parte disso. Nos trilhos, usamos Rake, os caras C usam make e, em Java, usamos Ant e Maven. Embora seja verdade que os desenvolvedores Ant ou Maven cuidem do desenvolvedor Java talvez melhor do que outros, também há outra pergunta: em que você escreve tarefas Ant? Java. Se você é um desenvolvedor Java, é fácil.

Então, sim, parte disso é usar ferramentas escritas no idioma que você está usando ferramentas.

Dan Rosenstark
fonte
7
Ant também surgiu no momento em que a comunidade Java estava apaixonada por XML. (O que não quer dizer XML não tem um lugar.)
Laurence Gonsalves
3
@Laurence Gonsalves, que é tão verdadeiro. Mas por favor, não falamos sobre modismos aqui no SO :) Eu estava ensinando Java dev na época, e TUDO era XML. Agora ainda é XML, mas ninguém se importa.
Dan Rosenstark
1
O comentário sobre ferramentas é interessante. makeprovém do background do UNIX, de modo que as ferramentas são feitas escrevendo utilitários compactos úteis e integrando-os em pipeline. É por isso que a maior parte da costura é feita usando comandos de shell.
precisa saber é o seguinte
2
@D. Shawley, todos verdadeiros makee pequenos utilitários Unix. O GIT também é filho desse processo. Em uma nota pessoal, eu não diria que não é melhor. Mas é uma enorme mudança de paradigma para programadores Java. Ant é muito mais consoante com as maneiras de pensar em Java.
Dan Rosenstark
12

O Ant e mais tarde o Maven foram projetados para resolver algumas dores de cabeça causadas por Make(ao criar novas no processo). É apenas evolução.

... Logo depois, vários projetos Java de código aberto perceberam que o Ant poderia resolver os problemas que eles tinham com os Makefiles ....

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

Se eles resolvem alguma coisa ou apenas criam um formato extra para aprender é um tópico subjetivo. A verdade é que é praticamente a história de toda nova invenção: o criador diz que resolve muitos problemas e os usuários originais dizem que essas são virtudes.

A principal vantagem que ele tem é a possibilidade de integrar-se ao java.

Eu acho que uma história semelhante seria com, rakepor exemplo.

OscarRyz
fonte
4
Isso não é muito específico. Quais dores de cabeça causadas pela marca o Maven resolve?
Laurence Gonsalves
1
@Gonsalves: Bem, esse é um dos aspectos subjetivos de toda nova tecnologia, o criador da alternativa diz que resolve muitos problemas e os criadores da tecnologia substituída dizem que esses não são defeitos, mas virtudes e assim por diante. Eu acho que nessa situação em particular foi a integração do java e a compilação cruzada
pronta para uso
2
[Referindo-se à sua edição da resposta, não ao comentário mais recente] Isso ainda não explica quais problemas foram resolvidos, apenas que os criadores de formigas afirmam que os problemas foram resolvidos ...: - / Minha impressão foi de que o Ant foi criado originalmente para ser uma alternativa mais simples ao Make. Com o tempo, as pessoas descobriram que havia coisas que estavam faltando e, portanto, adicionaram recursos até o Ant se tornar tão complexo quanto o make, mas com o binutils embutido (make depende muito de ferramentas externas como cp, rm etc.), e claro que há a sintaxe XML.
Laurence Gonsalves
2
Sim, mas quando o melhor que o criador de uma nova alternativa pode fazer é dizer "isso resolve os problemas da antiga" sem realmente dizer quais são esses problemas que não são tão úteis para aqueles que consideram qual opção usar. O Ant resolve problemas que tenho com o make ou resolve coisas que não considero problemas ao apresentar novos problemas para mim?
Laurence Gonsalves
9

Um dos principais problemas resolvidos pelo Maven (e pelas configurações Ant habilitadas para Ivy) sobre o make é a resolução de dependência automatizada e o download dos seus jars de dependência.

Ophidian
fonte
6

Penso que a explicação mais provável é que vários fatores desencorajaram o uso de make dentro da comunidade Java em um período crítico (final da década de 1990):

  1. Como o Java abrange várias plataformas, os programadores de Java em geral não eram tão hábeis em ferramentas Unix quanto os programadores geralmente confinados a um ambiente Unix (por exemplo, programadores C e Perl). Observe que isso é EM GERAL. Sem dúvida, existem e foram dotados programadores Java com um profundo conhecimento do Unix.
  2. Conseqüentemente, eles eram menos adeptos ao make e não sabiam usá-lo de maneira eficaz.
  3. Embora seja possível escrever um Makefile curto e simples que compile Java com eficiência, é necessário um cuidado extra para fazê-lo de maneira independente da plataforma.
  4. Consequentemente, havia um apetite por uma ferramenta de construção intrinsecamente independente da plataforma.
  5. Foi nesse ambiente que Ant e mais tarde Maven foram criados.

Em resumo, embora o make certamente possa ser usado para projetos Java, houve um momento de oportunidade para torná-lo a ferramenta de construção Java de fato. Esse momento passou.

David A. Ventimiglia
fonte
5

Fazer scripts tendem a ser inerentemente dependentes da plataforma. Java deve ser independente de plataforma. Portanto, ter um sistema de compilação que funcione apenas em uma plataforma para uma base de origem de várias plataformas é um problema.

Brian Fox
fonte
5

Resposta curta: porque makenão é bom. Mesmo na frente C, você vê muitas alternativas surgindo.

Resposta longa: makepossui várias falhas que dificilmente são adequadas para compilar C e inadequadas para compilar Java. Você pode forçá-lo a compilar Java, se desejar, mas espere encontrar problemas, alguns dos quais não têm uma solução ou solução alternativa adequada. Aqui estão alguns:

Resolução de dependência

makeespera inerentemente que os arquivos tenham uma dependência semelhante a uma árvore, na qual um arquivo é o resultado da criação de vários outros. Isso já sai pela culatra em C ao lidar com arquivos de cabeçalho. makerequer que um makearquivo de inclusão específico seja gerado para representar a dependência de um arquivo C em seus arquivos de cabeçalho; portanto, uma alteração no último faria com que o anterior fosse reconstruído. No entanto, como o arquivo C em si não é recriado (apenas reconstruído), o make geralmente requer a especificação do destino como .PHONY. Felizmente, o GCC suporta a geração desses arquivos automaticamente.

Em Java, a dependência pode ser circular e não há ferramenta para gerar automaticamente dependências de classe no makeformato. antEm Dependvez disso, a tarefa de pode ler o arquivo de classe diretamente, determinar quais classes ele importa e excluir o arquivo de classe se alguma delas estiver desatualizada. Sem isso, qualquer dependência não trivial pode resultar em você ser forçado a usar compilações limpas repetidas, removendo qualquer vantagem de usar uma ferramenta de compilação.

Espaços em nomes de arquivos

Embora nem Java nem C incentivem o uso de espaços em seus nomes de arquivos de código-fonte, makeisso pode ser um problema, mesmo que os espaços estejam no caminho do arquivo. Considere, por exemplo, se seu código-fonte existe em C:\My Documents\My Code\program\src. Isso seria suficiente para quebrar make. Isso ocorre porque maketrata os nomes de arquivos como strings. anttrata os caminhos como objetos especiais.

Verificando arquivos para compilação

makerequer definir explicitamente quais arquivos devem ser criados para cada destino. antpermite especificar uma pasta que deve ser verificada automaticamente em busca de arquivos de origem. Pode parecer uma conveniência menor, mas considere que em Java cada nova classe requer um novo arquivo. Adicionar arquivos ao projeto pode se tornar um grande aborrecimento rápido.

E o maior problema com make:

make depende do POSIX

O lema de Java é "compilar uma vez executado em qualquer lugar". Mas restringir essa compilação a sistemas baseados em POSIX, nos quais o suporte a Java é realmente o pior, não é a intenção.

As regras de compilação makesão essencialmente pequenos bashscripts. Mesmo que exista uma porta makepara o Windows, para que funcione corretamente, ela deve ser empacotada com uma porta de bash, que inclui uma camada de emulação POSIX para o sistema de arquivos.

Isso vem em duas variedades:

  1. MSYS que tenta limitar a conversão POSIX a caminhos de arquivo e, portanto, pode ter dicas desagradáveis ​​ao executar ferramentas externas não criadas especialmente para ela.

  2. cygwinque fornece uma emulação completa do POSIX. Os programas resultantes, no entanto, tendem a ainda confiar nessa camada de emulação.

Por esse motivo, no Windows, a ferramenta de construção padrão nem sequer é make, mas sim MSBuild, que também é uma ferramenta baseada em XML, mais próxima em princípio ant.

Por outro lado, anté construído em Java, pode ser executado em qualquer lugar e contém ferramentas internas, chamadas "tarefas", para manipular arquivos e executar comandos de maneira independente da plataforma. É suficientemente versátil que você pode ter mais facilidade para criar um programa C no Windows usando do antque usando make.

E um último menor:

Mesmo programas em C não usam make nativamente

Você pode não perceber isso inicialmente, mas os programas C geralmente não são enviados com um Makefile. Eles são enviados com um CMakeLists.txt, ou um bashscript de configuração, que gera o real Makefile. Por outro lado, a fonte de um programa Java construído usando anté fornecida com um antscript pré-construído. A Makefileé um produto de outras ferramentas - é quanto makeé inadequado ser uma ferramenta de construção por si só. anté independente e lida com tudo o que você precisa para seu processo de construção Java, sem nenhum requisito ou dependência adicional.

Quando você executa antem qualquer plataforma, ele simplesmente funciona (tm). Você não pode entender isso make. É incrivelmente dependente de plataforma e configuração.

SlugFiller
fonte
4

A menos que eu não seja ninguém, a suposição de que ninguém está (mis) usando o make for java está errada.

"Gerenciando projetos com o GNU Make" (disponível em GFDL) contém um capítulo completo dedicado ao uso makecom projetos java.

Como contém uma lista longa (e espero que justa) dos prós e contras do uso do make em vez de outras ferramentas, você pode dar uma olhada lá. (consulte: http://oreilly.com/catalog/make3/book/ )

Mikyra
fonte
Este é um resumo preciso? make (em vários sabores) é utilizável para Java, mas com alguma dor. Ant e Maven (e jmake ?) Fazem algumas coisas especiais que Java precisa / gosta, para tornar os projetos Java mais rápidos e fáceis de construir. Eles também podem ser usados ​​para um processo de construção mais independente da plataforma para projetos não Java, mas são mais ajustados para Java.
Phil Perry
3

Ant é um aprimoramento orientado à configuração XML em relação a Makefiles e o Maven é uma melhoria da ferramenta de criação de dependências em relação ao Ant. Alguns projetos usam todos os três. Eu acho que os projetos JDK costumavam usar uma mistura de makefiles e formiga.

Berlin Brown
fonte
1

Um grande motivo é que o Ant e o Maven (e a maioria das ferramentas SCM, CI e IDE direcionadas a java) são gravados em java por / para desenvolvedores de java. Isso facilita a integração em seu ambiente de desenvolvimento e permite que outras ferramentas, como os servidores IDE e CI, integrem partes das bibliotecas ant / maven à infraestrutura de construção / implantação.

Chris Nava
fonte
1

Era uma vez eu trabalhei em um projeto Java que usava o gmake. Minha lembrança é nebulosa, mas no IIRC tivemos dificuldade em lidar com a estrutura de diretórios de pacotes que javac espera. Também me lembro que a criação de arquivos JAR era um aborrecimento, a menos que você tivesse algo trivial.


fonte
1

ApacheAnt não é nada como Make. Make é sobre descrever dependências entre arquivos e como criar arquivos. Ant é sobre dependências entre "tarefas" e é realmente mais uma maneira de colar scripts de compilação.

pode ajudar você a AntVsMake

Venky Vungarala
fonte
Eu realmente gostaria de saber sobre os motivos dos votos negativos.
hagello
0

Ant e Maven abordam o gráfico de dependência de construção e o gerenciamento de uma visão mais 'moderna' ... Mas, como Oscar diz, eles criaram seus próprios problemas ao tentar resolver os problemas antigos com make.

John Weldon
fonte
0

Nunca usei projetos GNU Make for Java, mas costumava usar o jmk . Infelizmente, não é atualizado desde 2002.

Ele possuía alguma funcionalidade específica para Java, mas era pequeno o suficiente para incluir no tarball de origem sem aumentar significativamente seu tamanho.

Atualmente, apenas assumo que qualquer desenvolvedor Java com o qual compartilho código tenha o Ant instalado.

finnw
fonte