Esta página discute o que são sistemas de build, o que eles fazem e por que usar uma sistema de build e por que compiladores e scripts de build não são a melhor escolha a organização começa a escalonar. Ele é destinado a desenvolvedores que não têm muito com um sistema de build.
O que é um sistema de build?
Todos os sistemas de build têm um propósito simples: transformar o código-fonte escrito por engenheiros em binários executáveis que podem ser lidos por máquinas. Os sistemas de build não servem apenas para código criado por humanos. elas também permitem máquinas para criar builds automaticamente, seja para teste ou para lançamentos a produção. Em uma organização com milhares de engenheiros, é comum que a maioria dos builds é acionada automaticamente, e não diretamente pelos engenheiros.
Não posso só usar um compilador?
A necessidade de um sistema de build pode não ser óbvia de imediato. A maioria dos engenheiros
não usam um sistema de build enquanto aprendem a programar; a maioria começa invocando ferramentas
como gcc
ou javac
diretamente da linha de comando, ou o equivalente em uma
de desenvolvimento integrado (IDE). Contanto que todo o código-fonte esteja
no mesmo diretório, use um comando como este:
javac *.java
Isso instrui o compilador Java a pegar todos os arquivos-fonte Java no arquivo e transformá-lo em um arquivo de classe binária. No caso mais simples, tudo de que você precisa.
No entanto, assim que o código se expande, as complicações começam. javac
é inteligente
o suficiente para procurar nos subdiretórios do diretório atual
importação. No entanto, não há como encontrar o código armazenado em outras partes da
(talvez uma biblioteca compartilhada por vários projetos). Ela também só sabe
como criar código Java. Sistemas grandes geralmente envolvem peças diferentes escritas
uma variedade de linguagens de programação com redes de dependências entre essas partes,
ou seja, nenhum compilador para uma única linguagem pode criar todo o sistema.
Quando estiver lidando com código de diversas linguagens ou compilação a criação de códigos não é mais um processo de uma única etapa. Agora você deve avaliar depende das quais o código depende e construa essas peças na ordem correta, possivelmente usando um conjunto diferente de ferramentas para cada peça. Se alguma dependência mudar, será preciso repetir esse processo para evitar a dependência de binários obsoletos. Para uma base de código tamanho moderado, esse processo rapidamente se torna tedioso e propenso a erros.
O compilador também não sabe nada sobre como processar
dependências, como arquivos JAR
de terceiros em Java. Sem um sistema de build,
você pode gerenciar isso baixando a dependência da Internet, mantendo
em uma pasta lib
no disco rígido e configurando o compilador para ler
bibliotecas desse diretório. Com o tempo, vai ser difícil manter
as atualizações, versões e origem dessas dependências externas.
E os scripts de shell?
Suponha que seu projeto de hobby comece simples o suficiente para que você possa construí-lo usando apenas um compilador, mas você começa a encontrar alguns dos problemas descritos antes. Talvez você ainda ache que não precisa de um sistema de build e possa automatizar as partes tediosas usando alguns scripts de shell simples que cuidam construindo as coisas na ordem correta. Isso ajuda por um tempo, mas logo você começará a ter ainda mais problemas:
Isso se torna entediante. À medida que seu sistema fica mais complexo, você começa a gastar quase tanto tempo trabalhando nos scripts de build quanto no código real. Depuração scripts de shell é trabalhoso, com cada vez mais invasões sobrepostas se complementam.
É lento. Para garantir que você não estava confiando acidentalmente em bibliotecas desatualizadas, faça com que seu script de build crie todas as dependências em ordem sempre que executá-lo. Você pensa em adicionar lógica para detectar quais partes precisam ser reconstruído, mas isso soa muito complexo e propenso a erros para um script. Ou você pensa em especificar quais peças precisam ser reconstruídas toda vez, você volta para o primeiro quadrado.
Boas notícias: é hora de um lançamento! Melhor descobrir todos os argumentos você precisa passar para o comando jar para fazer seu build final. Não se esqueça como fazer upload e enviá-lo para o repositório central. E criar e enviar as atualizações da documentação e enviar uma notificação aos usuários. Hum, talvez isso precise de outro script...
É um desastre! Seu disco rígido falha e agora você precisa recriar todo o sistema. Você foi inteligente o suficiente para manter todos os seus arquivos de origem na versão mas e as bibliotecas que você transferiu por download? Você consegue encontrá-los? novamente e verifique se elas eram a mesma versão de quando você fez o download deles? Seus scripts provavelmente dependiam de ferramentas específicas serem instalada em locais específicos, é possível restaurar o mesmo ambiente e os scripts voltarem a funcionar? E todas as variáveis de ambiente que você define há muito tempo para fazer o compilador funcionar corretamente e depois se esqueceu dele?
Apesar dos problemas, seu projeto foi bem-sucedido o suficiente para que você seja capaz de começar a contratar mais engenheiros. Agora você percebe que não precisa para que os problemas anteriores surjam, você precisa passar pelo mesmo processo de bootstrapping toda vez que um desenvolvedor novo se juntar à equipe. E apesar de seus melhores esforços, ainda existem pequenas diferenças em cada no sistema da pessoa. Muitas vezes, o que funciona na máquina de uma pessoa não funciona em outros, e cada vez são necessárias algumas horas de caminhos de ferramentas de depuração ou para descobrir onde está a diferença.
Você decide automatizar seu sistema de build. Na teoria, tão simples quanto ter um novo computador e configurá-lo para executar o build. todas as noites usando o cron. Você ainda precisa passar pelas processo de configuração, mas agora você não tem o benefício de um cérebro humano capazes de detectar e resolver pequenos problemas. Agora, todas as manhãs, quando você percebe que o build da noite passada falhou porque ontem um desenvolvedor fez uma alteração que funcionou no sistema, mas não funcionou sistema de build. Cada vez que é uma correção simples, mas isso acontece com tanta frequência que você acabam gastando muito tempo todos os dias descobrindo e aplicando essas práticas e correções.
Os builds ficam mais lentos à medida que o projeto cresce. Um dia enquanto espera até que um build seja concluído, olhe com tristeza para a área de trabalho ociosa do seu um colega de trabalho que está de férias, e gostaria que houvesse uma maneira de aproveitar todo esse desperdício de poder computacional.
Você se deparou com um problema clássico de escalonamento. Para um único desenvolvedor que trabalha algumas centenas de linhas de código por no máximo uma ou duas semanas (que podem ter toda a experiência até agora de um desenvolvedor júnior que acabou de se formar universidade), você só precisa de um compilador. Os scripts podem demorar um pouco mais longe. Mas assim que você precisar coordenar vários desenvolvedores e nas máquinas, mesmo um script de compilação perfeito não é suficiente, porque se torna as pequenas diferenças nessas máquinas. Neste ponto, essa abordagem simples falha, e é hora de investir em um sistema de criação real.