Construindo Múltiplos Projetos com Gradle

Propaganda
Construindo Múltiplos Projetos com Gradle
Aprenda como criar uma estrutura múltiplos projetos, definir suas dependências e algumas
dicas para customizar ainda mais a construção de um projeto.
Daniel Figueiredo
([email protected]) é engenheiro de software
graduado pela Universidade Tiradentes em 2009, trabalhando
de São Paulo para a INFOX Tecnologia da Informação/SE.
Desenvolve sistemas Web desde 2008, trabalhando com
Jboss Seam, JBPM, JSF, entre outros.
Automação de projetos é um ponto essencial para o sucesso na construção de
softwares. Esta deve ser fácil, simples e até mesmo divertida de se implementar.
Não há um tamanho único, um modelo pronto, de processo que atenderá
todos os tipos de construções. Portanto o Gradle não impõe um rígido e único
processo sobre as pessoas. Contudo, ele foca em encontrar e descrever o
processo de construção-alvo, que é o mais importante, fornecendo toda a
liberdade necessária para criar uma construção declarativa, sustentável, de
forma concisa e de alta performance. Além de possibilitar a definição de
estruturas fragmentadas, como o conceito de multiproject (múltiplos projetos),
no qual cada projeto representa um módulo, uma camada da estrutura
geral fragmentada para se obter melhor coesão, baixo acoplamento, maior
organização dos serviços e funções, sendo possível acessar informações e
estipular diversos tipos de dependências entre esses projetos
ma ferramenta para construção de projetos sempre foi algo
desejável, desde o surgimento da necessidade de compartilhá-los e padronizá-los da forma mais simples possível
(apesar da complexidade de algumas arquiteturas).
Essas estruturas normalmente são separadas em módulos e devem
possuir vários requisitos, como, por exemplo: portabilidade de IDE,
facilidade para locação das dependências, empacotamentos automáticos, construção de tarefas específicas, automatização de configurações, entre outros. Atualmente existem algumas ferramentas e
utilitários que podem preencher essas diversas exigências, em uma
ordem cronológica ascendente podemos citar os mais conhecidos:
os clássicos scripts Ant, o Maven e o atual Gradle. O mais utilizado
atualmente por diversas empresas é o Maven 2 (versão atual, pois
houve uma grande mudança proveniente da primeira versão, logo,
para diferenciar sem ocorrer dúvidas e problemas foi adotada essa
nomenclatura).
Entretanto, o Maven 2 trouxe diversos questionamentos, pois para
quem já trabalha com ele, sabe que existe uma grande dependência
de plug-ins para satisfazer os requisitos, além do dispendioso tempo
de escrita em arquivos xml, que acabam ficando imensos dificultando
a manutenção, entre outros fatores. Entretanto, o objetivo deste artigo
não é fazer nenhuma crítica ao Maven, mas sim expor os pontos que
o Gradle proporciona um benefício melhor sobre o assunto.
O “coração” do Gradle é que ele coloca as declarações em um nível
superior, pois os elementos são feitos em uma Domain Specific Lan-
59
: : www.mundoj.com.br : :
guage (DSL), baseada no Groovy e podem ser montados da forma
que desejar. Esses elementos também fornecem suporte build-byconvention (suporte já na convenção) para projetos Java, Groovy,
OSGi, Web e Scala. O Gradle também permite a aplicação de diversos
princípios de design no código da construção, afinal é muito fácil
compor peças reutilizáveis de lógica, assim como definir múltiplos
projetos (multiproject), gerenciar de diversas formas as estratégias de
dependências (é possível acessar repositórios Maven, Ivy e repositórios locais) e migrar para o Gradle (pois ele se adapta a qualquer
estrutura). Gradle é um projeto de código aberto (open-source) e é
licenciado sob a ASL (veja nas referências).
Neste artigo será apresentado o exemplo que explicará como construir um projeto com o Gradle que possui subprojetos, assim como a
utilização do GUI provido pela própria ferramenta, entre outras coisas. Para melhor entendimento do conteúdo proposto, é interessante
ter em mãos a edição 44 da MundoJ, pois ela possui um artigo de
Cecília Fernandes que abordou o mesmo tema "Gradle Construtivo
e Declarativo", demonstrando como criar tasks, definir dependências
externas, gerar jars com o código-fonte da aplicação, configurar o encoding, utilizar o plug-in jetty para subir uma aplicação Web, inserir
os arquivos do Eclipse no projeto e também discorreu a respeito de
algumas vantagens e desvantagens analisadas. Sendo assim, partiremos do pressuposto que o leitor já saiba como realizar determinadas
funções com o Gradle, no entanto sempre que possível será explicado
algumas coisas novamente para facilitar a compreensão.
Criando um projeto Java
O Gradle utiliza como base um arquivo chamado build.gradle
(relativo ao pom.xml do Maven 2), que é escrito em Groovy, esse
arquivo deve ficar na raíz do projeto (por padrão) e o Gradle irá
procurá-lo dentro do diretório corrente. É neste arquivo que iremos definir as dependências do projeto, os plug-ins que serão
utilizados, as tarefas, variáveis e qualquer outra coisa que seja
necessária para a construção do mesmo.
Partindo de uma estrutura padrão para projetos Java, observe o
projeto MyModel:
Listagem 1.
build.gradle
apply plugin: 'java'
version = '1.0'
jar.baseName='my-model'
manifest.mainAttributes(
'Implementation-Title': 'My Model',
'Implementation-Version': version
)
fará com que diversas tarefas sejam adicionadas ao projeto, como
veremos a seguir. Na segunda, foi atribuído o valor '1.0' ao atributo version, esse, por padrão, já pertence ao projeto. Em seguida
(linha 3) foi definido o jar.baseName, que significa o nome padrão
que será utilizado a esse projeto caso seja empacotado como um
arquivo .jar. Após a quarta linha são declaradas as informações
do arquivo MANIFEST que será incluído no projeto sempre que
esse for construído (não se preocupe em tentar entender a origem
dos valores e atributos, o User Guide do Gradle referenciado vai
ajudá-lo perfeitamente a compreender como as instâncias dos
projetos são criadas e funcionam mais detalhadamente, enquanto
este artigo o fará entender, mesmo que resumidamente, como
utilizar e criar rapidamente uma aplicação).
Utilizando o GUI do Gradle
Para esse exemplo foi adotada a utilização do GUI do Gradle, ao
invés das linhas de comando, pois para didática fica mais fácil o
entendimento e nos permitirá uma visualização melhor das tarefas
que o projeto contém. Para abrir o GUI, basta digitar o comando:
Comando: "gradle -gui"
Figura 2. Linha de comando necessária para abrir a interface do Gradle.
Se tudo foi instalado corretamente, isso abrirá uma tela similar a
essa:
Figura 1. Estrutura do projeto MyModel.
Por padrão o Gradle espera encontrar o código-fonte de produção
em src/main/java e o de testes em src/test/java (neste artigo será utilizado o padrão para facilitar o aprendizado do conceito. Porém, é
possível informar diretórios adicionais a esse para localização dos
códigos-fontes, tanto de teste como produção, mais informações
podem ser obtidas nas referências). Sendo assim, a pasta src/main/
resources será incluída no arquivo JAR como resources e quaisquer
arquivos contidos dentro do mesmo diretório serão incluídos no
classpath usado para execução dos testes. Agora é necessário criar
o arquivo build.gradle na pasta raíz, afinal é preciso fazer com que
o Gradle reconheça o projeto:
Listagem 1: na primeira linha é informado o plug-in que iremos
utilizar, no caso 'java', porque nosso projeto é um projeto java e isso
Figura 3. GUI do Gradle exibindo o projeto MyModel e suas possíveis tarefas.
60
No entanto, para visualizar o projeto criado vá até a aba Setup -> Browse... e defina o Current Directory (diretório corrente) como a pasta
raiz, no caso MyModel. Automaticamente o Gradle já irá realizar a
busca no diretório para encontrar o arquivo build.gradle criado e se
tudo ocorrer bem, ele irá exibir a árvore de tasks do projeto. Clicar
duas vezes na tarefa fará com que ela seja executada. Sendo assim
execute a tarefa build e abra o diretório-raiz do projeto, note que uma
pasta "build" e ".gradle" foram criadas. A primeira contém o .jar do
projeto que é gerado junto com resultados dos testes e a segunda é
para armazenar cache e algumas propriedades do próprio Gradle.
Observe também que, se for executado novamente um build sem alterar nada no projeto, deverá ser exibido um log parecido com esse:
Verifique que dessa vez é utilizado o plug-in 'war', afinal é um
projeto Web e por coincidência (ou não) este projeto será empacotado nesse mesmo formato. No entanto, ainda não foram definidas as dependências. Sendo assim, adicione a seguinte linha de
código em cada arquivo build.gradle, modificando apenas a string
':NomeProjeto' pelo nome do projeto que ele realmente depende,
no caso de MyService, ":MyModel" e no de MyWeb, ":MyService"
(não se esqueça dos dois pontos antes do nome), como especificado no início do capítulo:
build.gradle
dependencies {
compile project(':NomeProjeto')
}
Listagem 2.
Executing command: ":build"
:compileJava UP-TO-DATE
:processResources UP-TO-DATE
:classes UP-TO-DATE
:jar UP-TO-DATE
[...] mais código
BUILD SUCCESSFUL
Total time: 2.751 secs
Os três projetos foram criados e a dependência entre eles foi definida, mas ainda assim o Gradle não é capaz de resolver essa
hierarquia, devido a falta de um arquivo de configuração em um
projeto root (raíz) que irá englobar todos os demais já criados
(para os familiarizados com Maven 2, isso não deve ser novidade).
Logo, crie um diretório Root e coloque os três projetos dentro:
Listagem 2: isso ocorre porque o Gradle sabe que não houve
nenhuma modificação com o código. Sendo assim, tudo já está
UP-TO-DATE atualizado, não precisando ser recompilado.
Múltiplos projetos e dependências
Após a criação do projeto MyModel, é necessário criar ao menos
mais um projeto para a construção de um esquema multprojects.
Sendo assim imagine o seguinte cenário, MyModel <- MyService
<-MyWeb, em que "<-" indica a dependência entre os projetos.
Conforme já feito anteriormente, o projeto MyService irá ser
construído na estrutura padrão de um projeto Java e o MyWeb na
estrutura padrão de um projeto JavaWeb:
Figura 4. Estrutura do projeto MyService e seu arquivo build.gradle.
Figura 6. Estrutura dos projetos dentro da raíz (Root).
Em seguida, dentro da pasta Root crie dois arquivos, respectivamente chamados: "build.gradle" e "settings.gradle", com os
respectivos códigos:
Listagem 3.
build.gradle
allprojects {
repositories {
mavenLocal()
mavenCentral()
}
}
Listagem 3: nesse arquivo "build.gradle" está definido que para
todos os projetos (allprojects { }) serão utilizados os repositórios
contidos dentro da tag "repositories { ... }", no caso, apenas o cache
local e o repositório central do Maven. Também existe a possibilidade de acrescentar outros repositórios, como a seguinte linha de
comando abaixo em negrito, que acrescenta o repositório da Jboss:
mavenRepo urls: "http://repository.jboss.com/maven2"
Agora é preciso informar quais são esses projetos que o root deve
procurar, para isso coloque no arquivo settings.gradle criado, a
seguinte linha de código:
Figura 5. Estrutura do projeto MyWeb e seu arquivo build.gradle.
Listagem 4.
setting.gradle
include "MyModel", "MyService", "MyWeb"
61
: : www.mundoj.com.br : :
Listagem 4: inclusão dos três projetos criados, o que irá permitir
que as dependências entre eles, assim como acessar "tasks" ou
informações contidas nos outros projetos.
Abra novamente o GUI do Gradle e selecione dessa vez a pasta
Root, algo similar a essa tela deve aparecer:
Listagem 6.
build.gradle
task cleanWarExploded(dependsOn: clean) {
ant.delete(dir: 'diretorioWarExploded')
}
Listagem 6: novamente é utilizada uma função ant, dessa vez para
deletar um diretório/arquivo informado, como exibido na linha
2. Note ainda que essa nova task depende da task clean. Sendo
assim, ao executá-la, o diretório build também será excluído, pois
a task clean será chamada antes que a task cleanWarExploded seja
realizada, como pode ser analisado na linha 1.
Adicionando os Projetos a uma IDE
Figura 7. GUI do Gradle exibindo a pasta Root com seus projetos.
Caso exista a necessidade de gerar um diretório exploded a partir
do WAR criado incluindo os jars dos projetos Java, analise a se
seguinte linha de comando: build.gradle
Listagem 5.
war.doLast{
ant.unzip(src:project(':MyWeb').war.archivePath, dest: new java.io.File(
'insiraOCaminhoDoDiretorio'))
}
Listagem 5: observe que foi utilizado um método ant, nesse é
necessário informar o diretório (arquivo) de origem que irá ser
extraído e um diretório destino onde será colocado os registros
obtidos na extração. O Gradle possui um padrão para as tarefas
onde se pode executar códigos em dois momentos distintos, um
antes da tarefa a ser executada e um depois. Sendo assim, sempre
que necessário inserir códigos em algum desses momentos defina
um bloco doFirst {...} ou doLast{...} dentro da task desejada. Uma
sintaxe alternativa para o código acima é:
war {
doLast{
ant.unzip(src:project(':MyWeb').war.archivePath, dest:
new java.io.File('caminhoDoDiretorio'))
}
}
Até agora foi visto como definir uma estrutura, habilitar os plugins para que os projetos sejam empacotados em jars, wars, entre
outras formas possíveis com outros plug-ins. No entanto, ainda
não é possível adicionar o projeto a uma IDE (é claro que os de
desenvolvedores mais experientes já sabem quais arquivos devem
criar para que uma IDE como Eclipse, ou NetBeans o reconheça),
mas não precisamos ter esse trabalho braçal, vejamos como (na
edição 44 já foi exibido como realizar essa função, porém aqui
é definido no projeto Root para habilitar esse plugin a todos os
projetos):
ar
1. Adicione as duas linhas de código a tag "allprojects {} "do arquivo "build.gradle" do projeto root:
Listagem 7.
allprojects {
repositories {
mavenLocal()
mavenCentral()
}
apply plugin: 'eclipse'
}
Listagem 7: novamente adicionamos funcionalidades comuns
a todos os projetos, nas linhas 6 e 7 foram acrescentados dois
plug-ins, um que fará a automatização desse projeto para o padrão
Eclipse, incluindo no .classpath as dependências declaradas. É
possível gerar os arquivos para que o projeto também seja reconhecido pelo NetBeans e IntelliJ, basta olhar a seção de plug-ins
no manual de referência, este tutorial irá utilizar o Eclipse, por ser
a IDE padrão adotada.
2. Atualize o GUI do Gradle e deverá ser possível visualizar as
novas tasks (tarefas) dentro dos projetos, execute a task de
nome "eclipse" ao menos uma vez para cada projeto (incluindo o Root). Note que arquivos serão gerados nas pastas do
projeto, como podemos ver na imagem a seguir:
Seria interessante que a task clean, utilizada para excluir a pasta
build (que é criada automaticamente quando se executa a task
build) também apagasse o diretório do war exploded. É bem sim
simples, acrescente o seguindo trecho de código ao build.gradle do
projeto MyWeb:
Figura 8. Arquivos gerados pelo plug-in do eclipse: .classpath e .project.
62
Lembre-se que, qualquer alteração nas dependências do Gradle,
será necessário atualizar (ou gerar) novamente os arquivos que
criados para reconhecimento do Eclipse, como foi feito acima.
Fatjars e avaliação de dependências
Voltando ao exemplo, imagine a necessidade de obter os dois
jars, de MyModel e MyService em um único jar, termo conhecido
como fatjar. É claro que neste caso, não faria sentido unir os dois
conteúdos, afinal eles separam duas camadas. Contudo, se esse
projeto fosse uma parte de outro maior e existissem outros projetos Service ou Model, poderia ser interessante distribuí-los em
um único jar, ao invés de MyService, YourService, OurService e
quaisquer outros que possam surgir.
Como isso pode ser feito com o Gradle? A resposta é que existem
diversas maneiras. Este artigo irá exibir uma que utiliza o compreendimento dos conceitos vistos na seção anterior. Sendo assim,
considere o seguinte trecho de código que deverá ser acrescentado
ao build.gradle do projeto MyService:
Listagem 8.
Figura 9. Projetos incluídos no workspace do Eclipse, observe que o projeto MyWeb por utilizar o plugin war já foi
criado como um projeto Web Java para o Eclipse.
O ciclo de vida
O núcleo do Gradle é uma linguagem de programação baseada em
tratar dependências, em termos mais preciso isso significa que pode
ser definida tasks e dependência entre tasks. O Gradle irá garantir
que essas tarefas sejam executadas, em ordem de suas dependências,
sendo realizada apenas uma tarefa por vez. Logo, ele irá efetuar o gráfico total de dependências antes de que alguma task seja executada.
Sendo assim, é importante conhecer as três etapas do ciclo de vida,
pois conforme a dependência definida será necessário dizer ao Gradle
algumas coisas, como será visto no exemplo a seguir. O ciclo de vida
é dividido em três partes:
1. Inicialização
Nesta etapa, o Gradle determinará quais projetos irão fazer parte
da construção e criará uma instância Project para cada um desses
projetos. Ele também irá procurar por um arquivo settings.gradle
no diretório "master", no caso deste artigo, o projeto "root".
Se não for encontrado, o Gradle será executado como um projeto
único, ao invés de um projeto multiproject, é claro que além de
encontrar o arquivo settings.gradle, é necessário que ele defina a
hierarquia, como foi feito no capítulo 4 declarando a inclusão os
projetos.
2. Configuração
Todos os scripts de construção de todos os projetos serão executados, o que irá configurar os objetos Project (criados na inicialização). Para um projeto singular, o fluxo depois a inicialização é
bem simples, os scripts são executados contra os objetos Project
que foram criados na fase de inicialização, atribuindo assim os
devidos valores.
3. Execução
Determina o subconjunto de funções, criado e configurado durante a fase de configuração, a ser executado. No caso da execução de tarefas em específico, o Gradle irá procurar as tarefas com
os nomes iguais aqueles passados nos argumentos da linha de
comando (ex: gradle task1 task2), se esses nomes existirem, as
tarefas serão executadas em uma construção separada, na ordem
informada (no caso de vários argumentos).
build.gradle
evaluationDependsOn(':MyModel')
jar {
doFirst {
ant.unzip(src: project(':MyModel').jar.archivePath,
dest: project(':MyService').buildDir.name+'\\'+jar.baseName)
}
from project(':MyService').buildDir.name+'\\'+jar.baseName+'\\'
doLast {
File f = new File(project(':MyService').buildDir.
absolutePath+'\\'+jar.baseName)
if(f.exists()) {
delete(f)
}
}
}
Listagem 8: esse trecho de código diz muita coisa. Na primeira
linha é declarado que a avaliação desse build.gradle depende do
projeto MyModel, como foi visto anteriormente no ciclo de vida,
os "build scripts" (scripts de construção, os códigos do build.gradle) são avaliados sequencialmente, o que significa que os scripts
avaliados antes não podem ver a configuração dos scripts que serão avaliados depois, uma maneira de controlar isso é definindo o
parâmetro na linha 1. Cada projeto só pode depender da avaliação
de apenas outro projeto, adicionar duas chamadas a "evaluationDependsOn('')" fará com que nenhuma seja de fato executada.
Após definir a dependência de avaliação do projeto MyService,
foram adicionadas e redefinidas algumas coisas na hora de execução do jar. Lembrando o objetivo de se obter um fatjar, no bloco
"doFirst{}" é utilizado novamente a função ant, para extrair os
dados. Desta vez é informado em um parâmetro, uma função
dos projetos que usam o plugin java, "jar.archivePath" do projeto
MyModel, como pode ser visto na linha 5 e no outro, o diretório
build do projeto MyService concatenado com o baseName do jar
definido anteriormente (capítulo 4), como pode-se observar nas
linhas 6 e 7.
Isso fará com que seja criada uma pasta 'my-service' dentro do
diretório build do projeto MyService, contendo todo o códigofonte do jar obtido no projeto MyModel. Agora é preciso informar
63
: : www.mundoj.com.br : :
que esse diretório também deve ser utilizado para a criação do jar
my-service, como pode ser visto na linha 9.
Por fim, para que nenhum diretório temporário permaneça no
disco, é realizada uma exclusão do mesmo, como pode ser analisado dentro do bloco "doLast{}", onde é instanciado um file e após
confirmada a existência do mesmo, é chamado um método do
provido pelo próprio Gradle para remover diretórios com subpastas e quaisquer outras coisas. É claro que alguns ajustes terão que
ser feitos para que o war exploded (capitulo 4) não fique com
jars centendo classes repetitivas no diretório lib, dentro de WEBINF, no arquivo build.gradle do projeto MyWeb acrescente dentro
do bloco "doLast{}" criado no bloco "war{}" após a chamada ao
método ant, o seguinte trecho:
Listagem 9.
build.gradle
war.doLast{
ant.unzip(src:project(':MyWeb').war.archivePath, dest: new java.io.File(
'insiraOCaminhoDoDiretorio'))
FileTree tree = fileTree('insiraOCaminhoDoDiretorio'+'\\WEB-INF\\lib\\')
for(File f : tree) {
if(f.getName().startsWith(project(':MyModel').jar.baseName) {
f.delete()
break;
}
}
}
Listagem 9: como pode ser verificado na linha 4, outra função
provida "fileTree()" é utilizada para obter toda a estrutura do diretório informado, afinal o objetivo é excluir o jar my-model, pois
manualmente ele já foi colocado dentro do jar my-service, mas o
Gradle não sabe disso. Sendo assim, é executado um loop para
obter todos os elementos do diretório e verificar se algum deles
começa com o nome definido como o baseName do jar no projeto
MyModel, como mostra a linha 7, se começar, esse arquivo é removido e fim do loop.
Referências
64
4JU
4JUFPmDJBMEP(SBEMFXXXHSBEMFPSH
PmD
.BOVBMEFSFGFSÐODJBEP(SBEMFIUUQXXXHSBEMFPSHEPDTVTFS
HVJEFVTFSHVJEF@TJOHMFIUNM
%4- o 1SPKFDU IUUQXXXHSBEMFPSHEPDTETMPSHHSBEMFBQJ1SP
KFDUIUNM
%4- o +BS IUUQHSBEMFPSHEPDTETMPSHHSBEMFBQJUBTLTCVO
EMJOH+BSIUNM
%4- o 8"3 IUUQHSBEMFPSHEPDTETMPSHHSBEMFBQJUBTLTCVO
EMJOH8BSIUNM
"4-oIUUQXXXHSBEMFPSHMJDFOTFIUNM
(SPPWZoIUUQHSPPWZDPEFIBVTPSH
)BOT %PDLUFS QSPmMF o IUUQTLJMMTNBUUFSDPNFYQFSUQSPmMFKBWBKFF
IBOTEPDLUFS
)BOT
%PDLUFS
4FNJOBS
o
IUUQWJNFPDPNTFBSDIWJEFPT
TFBSDIHSBEMFB
Para Saber Mais
Consulte a 44ª edição da MundoJ, ela fornecerá todas as
informações básicas necessárias que complementam este
artigo.
Consideração finais
Este artigo, de uma maneira geral, demonstrou como criar um exemplo de projeto de construção (build) com estrutura multiprojects,
definindo um projeto Root, onde se situa o arquivo settings.gradle,
que inclui os outros projetos na hierarquia. Possiblitando definir plugins, tasks, repositórios e quaisquer coisas comuns a todos os projetos.
Com isto, foi abordado como definir dependências entre os projetos,
assim como adicioná-los a uma IDE, criar um diretório exploded para
o WAR e remover arquivos desse diretório de uma maneira mais fácil.
Além disso, foi explicado como funciona as etapas do ciclo de vida
do Gradle, fundamental para o entendimento da função que avalia as
dependências entre os projetos, possibilitando a criação de um fatjar
(lembrando que todos os literais strings para separação do caminho
dos diretórios devem ser substituídos de acordo com o S.O., ou então
utilizar a variável separator de java.io.File). Junto a isso, algumas novas
funções nativas do gradle também foram utilizadas e explicadas, o que
leva este artigo a conclusão de sua finalidade.
Sendo assim, as informações contidas nos build scripts são partes
de objetos ricos, que sabem onde devem ser copiados determinados
arquivos, como realizar certas tarefas, como definir os padrões de nomenclaturas com versões, entre outras funções. Sobretudo o desempenho é otimizado, afinal o Gradle sabe quais alterações ocorreram e
efetua novamente o build (ao invés de utilizar o cache) somente dos
projetos necessários. Logo, por se basear em uma linguagem O.O.
(Orientada a Objetos) e, consequentemente, possuir características e
comportamentos, Hans Dockter, fundador e líder do projeto, comenta
em um seminário na JFrog, enquanto fala sobre o projeto, que para
o Gradle é necessário definir apenas o What (o que) e ele definirá o
How (como).
Em suma, esta é uma ferramenta muito poderosa, muitas de suas funções e capacidades não estão descritas aqui (como criação de plug-ins,
dentre outros), mas já é possível entender que ele atende a qualquer
regra de construção necessária. O que o destaca dos demais pela facilidade de customização, entendimento e reutilização de código, afinal
escrever scripts para construção de um projeto na mesma linguagem
em que ele é feito, ou em uma linguagem extensiva como Groovy, é
uma grande vantagem.
GUJ – Discussões sobre o tema do artigo e
assuntos relacionados
Discuta este artigo com 100 mil outros
desenvolvedores em www.guj.com.br/MundoJ
Download