Utilizando Ant (parte 2)
domingo, diciembre 16, 2001 at 1:00AM
Introducción a Ant (II): un ejemplo comentado
Descripción
En este artículo vamos a escribir un ejemplo completo con las tareas más comunes, explicando paso a paso cada elemento.
Para aquellos que no concozcan Ant, existe un artículo previo que explica qué es Ant y cómo se usa.
Empezando...
El ejemplo cubrirá la compilación, distribución, documentación y ejecución de una aplicación. Mantendremos una estructura jerárquica de directorios, separados por ficheros
fuente, clases generadas, ficheros distribuibles y documentación. En el directorio donde empieza esta jerarquía situaremos el fichero build.xml con el proyecto y algún otro
fichero que necesitemos.
Podemos empezar con la estructura básica del proyecto. El directorio actual, donde se encuentra el fichero build.xml servirá como directorio base del proyecto.
Ya podemos ir incluyendo algunas propiedades, que actuarán a modo de constantes, con los directorios que vamos a ir utilizando. Concretamente, usaremos un directorio
'src' para guardar los ficheros fuente, un directorio 'lib' para guardar clases y ficheros .jar necesarios para compilar y ejecutar, un directorio 'classes' para guardar las clases
Java compiladas, un directorio 'dist' donde guardaremos los ficheros a distribuir como aplicación final lista para ser utilizada, un directorio 'doc' para guardar la
documentación generada con el javadoc y un directorio 'conf' para guardar otros ficheros.
Para indicar todo esto, utilizaremos un elemento 'project' como el siguiente:
<project name="Ejemplo" basedir=".">
<property name="src" value="src"/>
<property name="lib" value="lib"/>
<property name="classes" value="classes"/>
<property name="dist" value="dist"/>
<property name="doc" value="doc"/>
<property name="conf" value="conf"/>
</project>
Compilando los ficheros fuente
Para compilar los ficheros fuente, usaremos un objetivo 'compilar'.
La tarea para compilar nos permite indicar el directorio de los fuentes, el directorio destino donde dejar las clases generadas y el classpath a usar, donde buscar clases y
librerías necesarias. También puede ser interesante indicar los modos verbose y debug. Esta tarea será algo como:
<javac srcdir="${src}" destdir="${classes}" classpath="${lib}" verbose="true" debug="true">
Además, tenemos que generar el stub y el skeleton de una clase a la que se accede vía RMI. Debemos indicar el directorio donde buscar la clase a compilar además de ésta
y del classpath a usar. También es interesante el modo debug. Para ello podemos usar la siguiente tarea:
<rmic base="${classes}" classname="com.javahispano.ejemplo.ServidorRMI" classpath="${lib}" debug="true"/>
Es posible que nos interese guardar en algún fichero una indicación acerca de la compilación. Para guardar en un fichero un sencillo mensaje podríamos usar la siguiente
tarea, a la que se le pasa el mensaje y el fichero a escribir:
<echo message="Datos, datos, datos..." file="${conf}/datos.txt"/>
El objetivo completo quedaría como:
<target name="compilar">
<javac srcdir="${src}" destdir="${classes}" classpath="${lib}" verbose="true" debug="true">
<rmic base="${classes}" classname="com.javahispano.ejemplo.ServidorRMI" classpath="${lib}" debug="true"/>
<echo message="Datos, datos, datos..." file="${conf}/datos.txt"/>
</target>
Generando la documentación
La tarea para documentar admite muchos parámetros aunque la mayoría son la extensión literal de los parámetros pasados a la herramienta javadoc.
Básicamente, hay que indicar el directorio donde buscar los ficheros fuente, el classpath donde buscar clases y librerías existentes, el directorio de destino y los paquetes a
documentar. Además, indicamos otras opciones: establecer el modo verbose, indicar el nivel de acceso hasta el cual documentar (access), indicar que incluya las etiquetas
author y version, indicar los títulos de la ventana (windowtitle) y de la lista de paquetes (doctitle) y pedir que separe el índice por letras (splitindex). La tarea queda más o
menos como sigue:
<target name="documentar">
<javadoc sourcepath="${fuentes}" classpath="${lib}" destdir="${doc}"
packagenames="${paquetes}"
verbose="true" author="true"
access="private" splitindex="true" version="true"
windowtitle="${titulo}" doctitle="${titulo}"/>
</target>
Se utilizan dos propiedades, 'paquetes' y 'titulo' que podemos declarar como elementos dentro del elemento 'project', de la siguiente manera:
<property name="paquetes" value="com.javahispano.*"/>
<property name="titulo" value="Un ejemplo completo"/>
Distribuyendo la aplicación
Distribuir la aplicación básicamente consiste en generar un fichero .jar con las clases generadas, un fichero .zip con los ficheros fuente y un fichero 'LEEME' adicional.
Al crear el fichero .jar deberemos indicar el nombre del fichero y el directorio base a partir del cual coger los ficheros a empaquetar. También es posible indicar el modo
compress para comprimir la información empaquetada:
<jar jarfile="${dist}/ejemplo.jar" basedir="${classes}" compress="true"/>
La creación del fichero .zip es muy similar. Sólo cambian los directorios a usar. Previamente, habremos copiado el fichero 'LEEME' al directorio de los fuentes.
La tarea resultante sería algo como:
<target name="distribuir">
<jar jarfile="${dist}/ejemplo.jar" basedir="${classes}" compress="true"/>
<copy file="LEEME" todir="${src}"/>
<zip zipfile="${dist}/ejemplo_src.jar" basedir="${src}" compress="true"/>
</target>
Haciendo alguna prueba
Es útil tener una tarea para realizar alguna prueba con la aplicación ya compilada. Para ello usamos la tarea java, a la que indicamos que la clase a ejecutar es
"com.javahispano.ejemplo.Ejemplo", cuál es el classpath (compuesto) donde buscar clases y librerías existentes, el parámetro que se le pasa ('123') y qué propiedad se debe
pasar a la máquina virtual.
Todo ello se puede hacer con un objetivo como:
<target name="probar" depends="compilar">
<java classname="com.javahispano.ejemplo.Ejemplo"
<classpath>
<pathelement path="${classes}"/>
<pathelement path="${lib}"/>
</classpath>
<arg value="123"/>
<jvmarg value="-Dpropiedades.propiedad=valor"/>
</java>
</target>
Por primera vez introducimos una dependencia. Como ya se indicó en el primer artículo, el atributo depends obliga a Ant a ejecutar primero la tarea 'compilar'. Una vez
terminada, se ejecutará la tarea 'probar'.
Un objetivo global
Es útil tener un objetivo para ejecutar varias tareas, una detrás de otra. Concretamente, puede ser útil para compilar, distribuir y documentar la aplicación. Para ello podemos
usar un objetivo como:
<target name="todo" depends="compilar, distribuir, documentar"/>
Además, es posible indicar que por defecto, se ejecute esta tarea cuando se utilice este fichero build.xml sin indicar explícitamente un objetivo. Esto se consigue con el
atributo 'default' en el elemento 'project':
<project name="Ejemplo" basedir="." default="todo">
Terminando el proyecto
Es interesante mantener el entorno limpio de clases Java obsoletas, documentación inadecuada, etc. Al fin y al cabo, cuando compilamos, ya no nos interesan las clases
antiguas sino las nuevas. Ocurre lo mismo con la documentación generada o los ficheros .jar y .zip.
Podemos crear una tarea para 'limpiar' un poco los directorio destino, y evitar que se junten demasiados archivos en desuso. Con el siguiente objetivo borramos los
directorios cuyo contenido se genera dinámicamente:
<target name="limpiar">
<delete dir="${classes}"/>
<delete dir="${doc}"/>
<delete dir="${dist}"/>
<delete file="${conf}/datos.txt"/>
</target>
Será necesario crearlos antes de guardar contenido en su interior, mediante las siguientes tareas, repartidas en los objetivos compilar, documentar y distribuir,
respectivamente:
<mkdir dir="${classes}"/>
<mkdir doc="${doc}"/>
<mkdir dir="${dist}"/>
El proyecto completo
El fichero build.xml queda como sigue:
<project name="Ejemplo" basedir="." default="todo">
<property name="src" value="src"/>
<property name="lib" value="lib"/>
<property name="classes" value="classes"/>
<property name="dist" value="dist"/>
<property name="doc" value="doc"/>
<property name="conf" value="conf"/>
<property name="paquetes" value="com.javahispano.*"/>
<property name="titulo" value="Un ejemplo completo"/>
<target name="limpiar">
<delete dir="${classes}"/>
<delete dir="${doc}"/>
<delete dir="${dist}"/>
<delete file="${conf}/datos.txt"/>
</target>
<target name="compilar" depends="limpiar">
<mkdir dir="${classes}"/>
<javac srcdir="${src}" destdir="${classes}" classpath="${lib}" verbose="true" debug="true">
<rmic base="${classes}" classname="com.javahispano.ejemplo.ServidorRMI" classpath="${lib}" debug="true"/>
<echo message="Datos, datos, datos..." file="${conf}/datos.txt"/>
</target>
<target name="documentar">
<mkdir doc="${doc}"/>
<javadoc sourcepath="${fuentes}" classpath="${lib}" destdir="${doc}"
packagenames="${paquetes}"
verbose="true" author="${autor}"
private="true" splitindex="true" version="true"
windowtitle="${titulo}" doctitle="${titulo}"/>
</target>
<target name="distribuir" depends="compilar">
<mkdir dir="${dist}"/>
<copy file="LEEME" todir="${dist}"/>
<jar jarfile="${dist}/ejemplo.jar" basedir="${classes}"
includes="${conf}/datos.txt" compress="true"/>
<zip zipfile="${dist}/ejemplo_src.jar" basedir="${src}"
includes="LEEME" compress="true"/>
</target>
<target name="probar" depends="compilar>
<java classname="com.javahispano.ejemplo.Ejemplo"
<classpath>
<pathelement path="${classes}"/>
<pathelement path="${lib}"/>
</classpath>
<arg value="123"/>
<jvmarg value="-Dpropiedades.propiedad=valor"/>
</java>
</target>
<target name="todo" depends="compilar, distribuir, documentar"/>
</project>
|
j2se 
Reader Comments