Automatizar várias tarefas típicas associadas ao desenvolvimento de software: compilação, distribuição, instalação e limpeza.
O Ant é uma ferramenta de open source para automatizar o processo de
construção de aplicações, semelhante ao make
.
O processo de construção é definido num ficheiro de construção (build file) em formato XML, evitando os problemas inerentes às makefiles.
As operações que é possível executar como parte do processo de construção estão implementadas em Java, sendo facilmente extensível e possibilitando a introdução de novas operações sempre que necessário. Esta característica leva a que haja uma fraca dependência do sistema operativo em uso, visto que tudo é executado através da máquina virtual Java.
Cada ficheiro de construção contém um único projecto, que define o processo de construção.
Um projecto (project) define um ou mais alvos (targets) que executam tarefas (tasks), parametrizadas por propriedades (properties).
O projecto permite ainda a definição do seu nome; o alvo de omissão, quando nenhum é estipulado na invocação do Ant; e o directório base, a utilizar sempre que houver referências a caminhos relativos.
Todas as tarefas definidas fora de um alvo são associadas a um alvo implícito invocado sempre como parte da inicialização do projecto.
Num projecto podem definir-se um ou mais alvos. Cada alvo é um contentor de tarefas que cooperam para realizar parte do processo de construção.
Um alvo pode definir dependências em relação a outros alvos que devem ser executados antes, sendo a ordem por que são definidas as dependências a seguida durante a execução (excepto se houver outras dependências). Convém notar que cada alvo apenas é executado a primeira vez, mesmo que seja referido em vários pontos do grafo de dependências.
É ainda possível condicionar a execução de um alvo à existência (ou não) de propriedades definidas.
Uma tarefa (task) é um procedimento, tipicamente executado dentro de um alvo. Cada um tem diversos atributos específicos, que funcionam como argumentos para a sua execução.
O Ant fornece um conjunto de tarefas pré-definidas que satisfazem as necessidades de grande parte dos processos de construção. Existe também a possibilidade de estender o Ant com novas tarefas.
Uma propriedade (property) é um par nome, valor. Uma vez definida, uma propriedade não pode ser modificada, excepto de forma temporária na
execução da tarefa antcall
.
Sempre que se refere o nome de uma propriedade em texto, este é substituido pelo valor que lhe está associado.
O Ant é executado através do comando ant
e por omissão procura um ficheiro
de construção chamado build.xml
. Este comportamento pode ser alterado
através do uso da opção -f
seguida do nome do ficheiro de construção que
se pretende utilizar.
$ antexecuta o alvo de omissão do ficheiro de construção
build.xml
$ ant -f another-build.xmlexecuta o alvo de omissão do ficheiro de construção
another-build.xml
Este vídeo apresenta o uso do Ant a partir da linha de comandos para executar um projecto exemplo.
Para executar um alvo indica-se ao Ant qual (ou quais) os alvos a executar:
$ ant Aexecuta o alvo A definido no ficheiro de construção de omissão.
$ ant A B Cexecuta primeiro o alvo A, seguido do alvo B e terminando com a execução do alvo C definidos no ficheiro de construção de omissão.
Para saber os alvos definidos num projecto pode utilizar-se a opção
-p
(ou -projecthelp
) do Ant:
$ ant -p
O IDE Eclipse suporta o uso de ficheiros de construção Ant através da
View Ant
(para a tornar visível: menu Window
-> Show View
->
Ant
). No entanto não utiliza esses ficheiros para definir internamente
como será o processo de construção de um projecto definido no IDE, pelo que
o seu uso tem de ser explícito.
Este vídeo apresenta o uso do Ant a partir do Eclipse para executar um projecto exemplo.
Uma propriedade define-se utilizando a tarefa pré-definida <property>
e
os atributos name
e value
.
<property name="greeting" value="Good day!"/>
As propriedades são muitas vezes utilizadas para guardar caminhos do
sistema de ficheiros. Utilizando a forma normal de definir uma
propriedade esta representará sempre um caminho absoluto. Caso se queira
definir um caminho relativo ao directório base do projecto pode
utilizar-se o atributo location
em vez do atributo value
:
<property name="relative-filename" location="xpto.txt"/>
Para ler uma ou mais propriedades definidas num ficheiro de texto pode
usar-se isoladamente o atributo file
da tarefa. As propriedades e seus
valores encontram-se definidos no ficheiro passado nesse atributo e
seguindo o seguinte formato:
# a comment name1=value1 name2=value2
A execução da tarefa abaixo define, no contexto do projecto, todas as
propriedades que se encontram definidas no ficheiro build.properties
:
<property file="build.properties"/>
É sempre possível definir uma variável através da linha de comandos
utilizando a opção -D
do Ant tantas vezes quantas as propriedades a
definir:
$ ant -Dname1=value1 -Dname2=value2 target
Nota: Uma vez que esta é sempre a primeira definição da propriedade é bastante útil quando se pretende alterar momentaneamente uma propriedade que se encontra definida no ficheiro de construção.
Um alvo define-se através da etiqueta <target>
, podendo incluir ou não
tarefas a executar no seu corpo:
<target name="A"/> <target name="B"> ... </target>
O atributo depends
indica os alvos que têm que ser executados antes do
actual. Numa execução do Ant, cada alvo é executado apenas uma vez. A ordem
definida é respeitada na execução, a não ser que existam outras
dependências.
<target name="A"/> <target name="B" depends="A"/> <target name="C" depends="B"/> <target name="D" depends="C,B,A"/> ...
$ ant D
Neste caso, qual a ordem de execução? C, B, A, D ? (D, C, B, A), (C, B, A), (B, A), (A) ? A, B, C, D? Em casos de dúvida (como este) é aconselhável construir o grafo de dependências.
Os atributos if
/ unless
permitem a execução de um alvo condicionada pela
existência/não existência de propriedades definidas.
Dado um ficheiro de construção que inclui o seguinte alvo:
<target name="A" if="property.1"/> ...
Qual o resultado de executar o alvo A?
$ ant A
E se a execução incluir a definição da propriedade?
$ ant -Dproperty.1=anything A
No primeiro caso a propriedade não se encontra definida, pelo que o alvo A não chega a executar-se.
No segundo caso, a propriedade é explicitamente definida aquando da execução do alvo A, pelo que este será executado.
E o que sucede quando se misturam dependências de alvos e de propriedades?
<target name="A" if="property.1"/> ... <target name="B" depends="A" unless="property.2"> ... </target>
$ ant B
Neste caso, é primeiro verificado que a propriedade property.1
está
definida e, na afirmativa, executa-se o alvo A. Só depois das dependências
de alvos terem sido verificadas é que se verifica se a propriedade
property.2
está definida e, na afirmativa, se executa o alvo B.
Assim, a seguinte execução executa A, B:
$ ant -Dproperty.1=avalue B
Do mesmo modo, a execução seguinte não executa nenhum alvo:
$ ant -D property.2=something B
Por fim, a invocação seguinte executa apenas A:
$ ant -Dproperty.1=avalue -Dproperty.2=anothervalue B
Um alvo para o qual não está definida uma descrição textual é considerado interno pelo Ant, não sendo apresentado quando se pede a listagem dos alvos disponíveis de um projecto.
Um alvo cujo nome comece por -
não pode ser invocado pelo Ant
directamente a partir da linha de comandos, uma vez que o carácter -
é
considerado pelo Ant indicador de que se segue uma opção.
Alguns exemplos de tarefas básicas incluidas no Ant são:
javac
- permite compilar código-fonte Java
java
- permite executar um programa Java
mkdir
, copy
, delete
- operações sobre o sistema de ficheiros
echo
- permite imprimir mensagens para o terminal
replace
- permite fazer substituições de texto em ficheiros
tstamp
- define um conjunto de propriedades pré-definidas com
informação sobre o instante em que foi invocada
Um projecto define-se recorrendo à etiqueta XML <project>
. Esta pode
ainda ser configurada com qualquer dos seguintes atributos: name
(nome do
projecto), default
(alvo de omissão) e/ou basedir
(directório de
omissão):
<project name="MyProject" default="build" basedir="."> ... </project>
Por omissão, o Ant procura a definição do projecto num ficheiro de
construção chamado build.xml
, no entanto é possível dar-lhe qualquer
outro nome, bastando para tal invocar o Ant com a opção -f
seguida do
nome do ficheiro de construção.
$ ant -f another-build-file.xml
Para se utilizar o valor de uma propriedade num texto deve usar-se a
notação ${nome}
. Por exemplo, se a propriedade dir tiver o valor
c:/proj
, então ${dir}/classes
é substituído por c:/proj/classes
.
Uma estrutura de directórios tipicamente associada a um projecto Ant tem o seguinte aspecto:
Em src fica o código-fonte e ficheiros de propriedades (*.java, *.properties).
Em etc ficam scripts e outros ficheiros que não são código fonte (*.txt, *.sql, etc).
Em lib ficam bibliotecas extra (*.jar).
O directório build é temporário e serve para guardar as classes do programa compiladas (*.class) e outros ficheiros auxiliares.
O directório dist é temporário e serve para guardar os resultados finais da compilação, por exemplo, um arquivo JAR.
<project name="MyProject" default="run" basedir="."> <description>simple example build file</description> <property name="src.dir" location="src"/> <property name="build.dir" location="build"/> <property name="inputFile" location="etc\input_file.txt"/> <property name="outputFile" location="etc\output_file.txt"/> <property name="run.mainclass" value="example.OrderPropertyFile"/> <property name="run.args" value="${inputFile} ${outputFile}"/> <target name="init"> <mkdir dir="${build.dir}"/> </target> <target name="clean" description="Delete the build directory" > <delete dir="${build.dir}"/> </target> <target name="compile" depends="init" description="Compiles the source code" > <javac srcdir="${src.dir}" destdir="${build.dir}"/> </target> <target name="run" depends="compile" description="Runs the program" > <java classname="${run.mainclass}" fork="true"> <arg line="${run.args}"/> <classpath> <pathelement location="${build.dir}"/> </classpath> </java> </target> <target name="show" description="Shows property values" > <echo message="src.dir = ${src.dir}"/> <echo message="build.dir = ${build.dir}"/> <echo message="run.mainclass = ${run.mainclass}"/> <echo message="run.args = ${run.args}"/> </target> </project>
ant init
- cria os directórios temporários
ant clean
- limpa os directórios temporários
ant compile
- depende de init, e compila o código do programa
ant run
- depende de compile, que depende de init, e executa o programa
compilado
ant show
- mostra o valor das propriedades utilizadas e que podem ser
parametrizadas
A definição de propriedades na linha de comandos permite alterar o comportamento observado, sem alterar o ficheiro de construção.
ant -Drun.args=xpto show
- modifica o valor de uma propriedade na linha
de comando e mostra o valor das propriedades utilizadas
A aplicação JavaPares é utilizada nos vídeos explicativos como exemplo de uma aplicação de consola e pode ser utilizada para exercitar o uso do Ant. Os vídeos explicativos mostram uma versão antiga desta aplicação.
Demonstração da utilização do Ant na consola e no Eclipse
ImportAnt - para simplificar os ficheiros de construção Ant e a configuração de aplicações Web e Web Services
Partes © 2009, 2010 Docentes de Sistemas Distribuídos e de Engenharia de Software, DEI, IST, UTL
Date: 2010/02/24 02:12:45 AM