Começando com o Gradle

No artigo onde expliquei o que são Build Tools do Java, comentei sobre algumas ferramentas famosas, como é o caso do Ant, Maven e Gradle. Entretanto, não entrei em detalhes sobre o funcionamento delas.


Sendo assim, neste artigo vou falar um pouco sobre como o Gradle funciona e como podemos usá-lo no nosso dia a dia. Bora começar?

Sobre o Gradle

Apenas para uma breve introdução, o Gradle trata-se de uma ferramenta de build open source bastante poderosa que nos permite configurar arquivos de build por meio da sua DSL (Domain Specific Language) baseada na linguagem Groovy.

“Então pra eu aprender Gradle eu preciso saber Groovy?”

Não necessariamente, pois o motivo de escolherem uma linguagem dinâmica para a configuração é justamente para evitar a verbosidade da estrutura XML que é muito comum em ferramentas como essa.

Claro, se você conhecer um pouco de Groovy vai tirar bastante proveito da syntax do código.

Orientado a tasks

Além da DSL, a ideia do Gradle é permitir configurações baseando-se em tasks, ou seja, quando queremos criar algum novo comportamento durante o build, vamos criar uma task!

“Legal, mas como posso começar a configuração de build com Gradle?”

Preparando o ambiente

Antes de começar a falar da prática, sugiro que instale o Gradle para realizarmos alguns testes para facilitar a compreensão.

Criando o primeiro arquivo de build

Para darmos início em um projeto Gradle, primeiramente precisamos de um arquivo que tenha a extensão .gradle.

Entretanto, por padrão, o Gradle busca por um arquivo chamado build.gradle, sendo assim, vamos criar o arquivo e abrí-lo com um editor.

Eu costumo usar ou Visual Studio Code ou o IntelliJ (pode ser a versão Communty também) para esses testes devido ao syntax highlight. Tenho preferência pelo IntelliJ devivo ao auto complete ser mais eficiente.

Declarando a primeira task

Dentro do arquivo, vamos escrever o seguinte script:

task minhaPrimeiraTask {
print 'Rodando minha primeira task'
}

Repare que esse script trata-se de uma task que estamos criando. A ideia dela é de fato realizar um processo comum quando temos o primeiro contato, por exemplo, com uma linguagem de programação, ou seja, apresentar uma mensagem apenas.

Portanto, com a nossa task declarada, dentro um terminal ou prompt de comando, vamos rodar o comando gradle minhaPrimeiraTask:

Veja que nesse primeiro momento, o Gradle apresentou a mensagem Rodando minha primeira task da mesma maneira como colocamos no script, mas também, ele iniciou um processo chamado Gradle Daemon. O que isso significa?

Entendendo o Gradle Daemon

Basicamente, esse daemon trata-se de uma instância da JVM para o Gradle com a finalidade de agilizar a execução das tasks. Inclusive, podemos executar novamente a task para comprovar a ideia:

Um detalhe bacana das tasks do Gradle é que não são case sensitive, por isso que conseguimos executar a task minhaPrimeiraTask escrevendo minhaprimeiratask

Repare que agora o resultado foi bem diferente:

  • Não apareceu novamente a inicialização da Gradle Daemon, pois agora o daemon está de pé.
  • O tempo de execução foi de aproximadamente 3 para 0 segundos.

Só que agora você deve estar se perguntando

“Então esse processo vai ficar sem parar no meu computador?”

Exatamente! Caso você queira saber o status dele, basta executar gradle --status:

Repare que ele está apresentando 2 instâncias, pois eu já tinha parado a 4508. Caso queira parar a atual, é só executar o comando gradle --stop:

Em outras palavras, por padrão, todas as vezes que utilizamos o Gradle ele vai executar um Gradle Daemon se não existir uma instância disponível.

Claro, existe a possibilidade de desabilitar essa opção, e para mais detalhes deixo a referência da documentação.

Conhecendo as tasks padrões do Gradle

Fizemos o primeiro contato com o Gradle, entretanto, é muito comum termos a seguinte dúvida considerando o que vimos até agora:

“Então quer dizer que vou ter que criar todas as tasks para o build?”

Não necessariamente, pois, como é de se esperar, já existem diversas tasks disponíveis por padrão no Gradle. Para visualizá-las podemos executar gradle tasks:

Repare que novamente subiu uma instância do Gradle Daemon, pois não tinha uma disponível.

Observe que o Gradle fez uma lista bem grande de possíveis tasks que podem ser executadas no nosso projeto. Vamos entendê-las:

  • Build Setup: tasks para o processo de setup.
  • Help: tasks de ajuda de modo geral.

De forma resumida, essa listagem apresentou 2 grupos de tasks, como também, a descrição de cada um deles.

Entretanto, por listar todas as tasks possíveis para o nosso projeto, por que a nossa não apareceu?

Listando todas as tasks, inclusive as nossas

Como vimos, todas as tasks que foram apresentadas, fazem parte de um grupo e possuem uma descrição, certo?

Em outras palavras, para que vejamos todas as tasks, mesmo que não façam parte de um grupo ou tenham uma descrição, basta apenas usar o parâmetro --all:

Note que a nossa task aparece em um grupo chamado de Other tasks! Isto é, esse é o grupo padrão para todas as tasks que não possuem um grupo.

“Bacana, mas como adicionamos um grupo e uma descrição para deixar a nossa task visível?”

Adicionando grupo e descrição nas tasks

Basicamente, precisamos adicionar o seguinte conteúdo no corpo da nossa task:

task minhaPrimeiraTask {
group 'tasks pessoais'
description 'testes de primeiro contato com o Gradle'
print 'Rodando minha primeira task'
}

Então, após salvar o build.gradle, ao executar novamente a task tasks:

Repare que agora aparece o nosso grupo Tasks pessoais, como também, a nossa task com a descrição que criamos!

Muito bom! Aprendemos um pouco sobre tasks do Gradle, mas até o momento, não fomos capazes de criar um build que nos permita desenvolver um projeto em Java, certo?

Em outras palavras, agora que entendemos o mínimo de como podemos criar uma task e como podemos visualizar todas as tasks disponíveis do projeto, daremos início num processo de build para construir uma aplicação Java.

Criando um projeto Gradle inicial

Como vimos, nas tasks disponíveis, temos a task init do grupo Build Setup que indica uma inicialização de um novo build do Gradle.

De fato a ideia dessa task é permitir a criação de um projeto Gradle inicial com arquivos comuns.

Portanto, antes de executar essa task, vamos criar um diretório para representar um projeto base que usaremos como exemplo.

Nesse caso vou colocar o nome de ceep, pois trata-se de um projeto que estou usando como base para outros artigos que venho escrevendo de Kotlin 😅

Então, dentro do diretório vamos executar o comando gradle init:

A princípio, parece que não aconteceu nada demais, né? Entretanto, veja que o Gradle apresentou a mensagem 2 actionable tasks: 2 executed, isso significa que o Gradle executou duas tasks ao chamar a task init e podemos ver o resultado verificando a estrutura do diretório:

Repare que além do build.gradle foram gerados outros arquivos e um diretório:

  • gradle: diretório que contém os arquivos do Gradle wrapper.
  • gradlew: Gradle wrapper para sistemas baseados em Unix (Linux).
  • gradlew.bat: Gradle wrapper para Windows.
  • settings.gradle: configurações do projeto.

Como a ideia do artigo é apenas uma breve introdução, não daremos tanta atenção nos demais arquivos, ou seja, vamos verificar o conteúdo que foi gerado no arquivo build.gradle:

Note que ele apresenta um comentário bem grande dando instruções de como podemos criar um sample de um projeto Java. De fato, se seguirmos as sugestões do Gradle, daremos o nosso primeiro passo no build de um projeto Java.

Entretanto, repare que essa abordagem não parece tão objetiva, pois o Gradle criou um projeto inicial e ainda precisamos realizar mais configurações…

Isso acontece, pois a task init, por padrão, assume um tipo de projeto conhecido como basic que o próprio nome já diz o que ele faz, isto é, gera um projeto básico.

É justamente por esse motivo que o Gradle não gerou um projeto Java como esperado.

Definindo o tipo do projeto como aplicação Java na inicialização

Além do tipo basic, o Gradle nos fornece outros tipos de projetos, dentre eles temos o java-application que tem o objetivo de gerar um projeto de uma aplicação Java, logo, vamos criar novamente o nosso projeto com a task init utilizando esse tipo.

Entretanto, para que isso seja possível no mesmo diretório, precisamos remover tanto o arquivo os arquivos build.gradle e settings.gradle, pois eles são utilizados como base para indicar que existe um projeto do Gradle, ou seja, se eles estiverem presentes, a task init não cria um projeto novo.

Após a remoção, execute o comando gradle init --type java-application:

Observe que novamente duas tasks foram acionadas, porém, apenas uma delas foi executada e a outra está indicando que foi atualizada (up-to-date).

“O que isso significa?”

Uma breve introdução à construção incremental

Uma das grandes vantagens ao utilizar o Gradle, é justamente a ideia do incremental build, isto é, o Gradle “não executa tasks que já foram executada”.

Lembra que quando executamos a tasks init pela primeira vez, foram executadas 2 tasks? Uma dessas tasks era responsável em gerar os arquivos de wrapper, porém, não removemos nenhum deles.

Justamente por esse motivo, o Gradle não viu a necessidade de executar essa task! Incrível, né?

Esse é um assunto que pode levar bastante tempo, por isso não vou me aprofundar, porém, se tiver alguma dúvida, fique à vontade em perguntar.

Entendo os arquivos gerados para aplicação Java

Legal, vamos verificar o que foi gerado em um projeto do tipo java-application:

Repare que agora, além dos arquivos do Gradle que vimos anteriormente, temos também o diretório src (também conhecido como source set) que contém uma estrutura bem similar ao padrão que vemos em projetos Maven:

  • main/java: código fonte para desenvolvimento.
  • test/java: código fonte para testes.

Inclusive, o Gradle já gerou alguns arquivos Java pra gente, vamos dar uma olhada em cada um deles:

Veja que trata-se de classes de exemplo para testarmos o nosso projeto. Aproveitando vamos dar uma olhada no conteúdo que foi gerado do arquivo build.gradle:

Veja que dessa vez, além dos comentários, o Gradle já adicionou alguns plugins, repositórios, dependências e definiu uma main class…

Em outras palavras, o próprio Gradle já fez toda a estrutura que é comum em um projeto Java pra gente! Portanto, o que nos resta é apenas testar e verificar o comportamento desse projeto. Mas como podemos fazer isso?

Verificando as tasks do projeto Java

Agora que estamos nesse projeto com toda essa configuração, vamos verificar as tasks disponíveis para ele:

Wow! Olha o tanto de tasks que temos disponíveis com a configuração do nosso projeto atual. Isso significa que temos diversas ações que podemos aplicar nesse projeto.

Rodando o projeto

A primeira delas é justamente a run que indica a execução do projeto, vamos rodá-la e ver o que acontece:

Inicialmente o Gradle verificou que eu não tinha a dependência do Guava e por isso a baixou primeiro.

Depois de finalizar o download e realizar outras tasks (como a de compilação), ela executou a task run, que por sua vez, executou a classe App, justamente por esse motivo do download (internet boa… Sacomé 😁) que o processo num todo demorou aproximadamente 17 segundos.

Sendo assim, vamos verificar o que acontece ao executar a task run novamente:

Bem mais rápido, né? Mais incrível ainda, é quando verificamos a estrutura de arquivos do nosso projeto:

Veja que agora surgiu o diretório build que mantém de todos os arquivos compilados, ou seja, para que a classe App fosse executada, foi necessário criar o .class dela e o Gradle já fez tudo isso pra gente!

Para saber mais

Vimos bastante conteúdo sobre o que é o Gradle e como podemos utilizá-lo de maneira inicial usando apenas o command line.

Entretanto, a ideia do Gradle não é fazer com que a gente desenvolva aplicações em editores quaisquer e realizando o processo de build via command line.

Ou seja, com esse projeto gerado, o próximo passo é importá-lo em uma IDE que dê suporte ao Gradle, como é o caso do IntelliJ IDEA que já vem com o plugin do Gradle instalado.

É possível também usar no Eclipse e no NetBeans, porém, vai precisar baixar o plugin a parte.

Dessa forma, ao invés do projeto ser gerenciado por uma IDE, ele é gerenciado pelo Gradle fortalecendo a ideia de compatibilidade independentemente da IDE.

Conclusão

Neste artigo tivemos o nosso primeiro contato com o Gradle e aprendemos das features e peculiaridades da ferramenta, como por exemplo, como começar um build, a instância do Gradle Daemon, execução de tasks, listagem de tasks e a criação de um projeto para dar suporte a aplicações Java.

E aí, o que achou do Gradle? Aproveite e deixe o seu feedback nos comentários 😉

One clap, two clap, three clap, forty?

By clapping more or less, you can signal to us which stories really stand out.