Apache Ant: come semplificare la vita di un programmatore Java

Apache Ant è un tool di build. In parole povere, possiamo definire Ant una sorta di “make” senza le stranezze ed avversità del “make”. Ant è un programma Java (e quindi multipiattaforma) che ci facilita ed automatizza il processo di sviluppo di applicazioni Java (siano esse Stand Alone Application, Web Application, Enterprise Application) eseguendo per noi tutti gli step necessari per ottenere il prodotto finale di un progetto di grandi dimensioni a partire direttamente dal nostro codice sorgente.

Con Ant possiamo compilare, creare directory, generare la documentazione dei nostri sorgenti nel formato java doc, realizzare file .jar e .war, fare il deploy di Web Application, ecc. il tutto in maniera semplice, intuitiva ed automatizzata. Una mano santa per tutti gli sviluppatori di applicazioni Java!

Ant è un programma che non ha interfacce grafiche, si lancia da linea di comando. I comandi che esegue vengono letti all’interno di un file denominato build.xml. Dentro questo file i comandi che Ant deve eseguire sono definiti mediante opportuni tag (tutto ciò non deve spaventare i newbie, vedremo com’è facile utilizzare Ant e tutti i suoi comandi una volta che si ha a disposizione uno scheletro del build.xml).

Per iniziare, scarichiamo l’ultima versione di Ant dal seguente indirizzo: http://ant.apache.org/bindownload.cgi (al momento della stesura di questo articolo l’ultima versione disponibile è la 1.6.2). Scompattato il file in una directory del File System, dobbiamo settare la variabile di ambiente ANT_HOME ed aggiornare la variabile di ambiente PATH (si presuppone che l’utente abbia già installato sulla propria macchina un JDK e correttamente settato la variabile di ambiente JAVA_HOME).
Ad esempio:

1) Su una macchina Linux:
export ANT_HOME=/usr/local/ant-1.6.2
export JAVA_HOME=/usr/local/jdk-1.4.2
export PATH=${PATH}:${ANT_HOME}/bin:${JAVA_HOME}/bin

2) Su una macchina Windows:
set ANT_HOME=C:ant-1.6.2
set JAVA_HOME=C:jdk1.4.2
set PATH=%PATH%;%ANT_HOME%bin;%JAVA_HOME%bin

Supponiamo adesso di voler realizzare un’applicazione Java mediante l’utilizzo di Ant (in un successivo articolo vedremo come realizzare, deployare e distribuire una Web Application su Tomcat Application Server mediante Ant). Il nome dell’applicazione sarà AppExample. Creiamo le seguenti cartelle nel nostro File System:

AppExample
  +--------- base
  +--------- docs
  +--------- src
      +--------antexample
            +------- main ------------ AppExampleMain.java
            +------- package2 -------- File1Pack1.java
	                          |--- File2Pack1.java
	                          |--- FileNPack1.java
            +------- packageN -------- File1PackN.java
	                          |--- File2PackN.java
	                          |----FileNPackN.java
  build.xml

Dentro la cartella src andremo a mettere i sorgenti della nostra applicazione (la cartella docs possiamo anche lasciarla vuota).

Nella cartella base metteremo i files di properties che l’applicazione andrà a leggere (se necessari), le immagini/icone utilizzate, gli script, ecc. e un file per eseguire l’applicazione in maniera semplice e veloce, ad esempio sotto Linux possiamo creare un file AntExample.sh e scriverci dentro:

java -classpath .:./classes:./lib:$CLASSPATH antexample.main.ExampleMain 

(sotto Windows basta nominare il file AntExample.bat, 
 sostituire ":" con ";" e "/" con "").

Il file build.xml risiede nella root directory dell’applicazione, contiene i comandi che Ant andrà ad eseguire ed avrà la struttura seguente:

<!-- ============== Esempio di file build.xml ================== -->

<?xml version="1.0"?>
<!-- General purpose build script for applications.-->

<project name="AntExample" default="compile" basedir=".">
   <description>
       Applicazione Java Standalone di esempio per l'utilizzo di Ant
   </description>

<!-- ================== Property Definitions ===================== -->

  <property file="build.properties"/>
  <property file="${user.home}/build.properties"/>

<!-- ================= File and Directory Names ==================== -->

  <property name="app.name"  value="AntExample"/>
  <property name="app.version" value="1.0"/>
  <property name="build.home" value="${basedir}/build"/>
  <property name="dist.home" value="${basedir}/dist"/>
  <property name="docs.home"     value="${basedir}/docs"/>
  <property name="src.home"  value="${basedir}/src"/>
  <property name="base.home" value="${basedir}/base"/>

<!-- Specifichiamo adesso la directory da dove importare librerie esterne
      (jar) nel progetto -->

  <property name="shared.lib" value="C:/Projects/lib/shared/lib"/>

<!-- Specifichiamo adesso la directory da dove importare classi
       java nel progetto -->

  <property name="shared.classes" value="C:/Projects/lib/shared/classes"/>

<!-- =============== Custom Ant Task Definitions =================== -->

  <property name="compile.debug" value="true"/>
  <property name="compile.deprecation" value="false"/>
  <property name="compile.optimize" value="true"/>

<!-- ================== External Dependencies ======================= -->
<!-- Qui indichiamo i jar esterni da importare nel progetto
     Nota: il path delle librerie da importare è specificato nel tag
     "<property name="shared.lib" value="C:/Projects/lib/shared/lib"/>".
     Nell'esempio supponiamo di utilizzare la libreria esterna
     "log4j-1.2.8.jar"-->

    <property name="log4j.jar"  value="log4j-1.2.8.jar"/>

<!-- ================== Compilation Classpath ======================= -->

  <path id="compile.classpath">
    <pathelement location="${src.home}"/>
    <pathelement location="${shared.classes}"/>
    <fileset dir="${shared.lib}">
      <include name="*.jar"/>
    </fileset>
  </path>

<!-- =================== All Target ================================ -->
<!--
    The "all" target is a shortcut for running the "clean" target
    followed by the "compile" target, to force a complete recompile.
-->

    <target name="all" depends="clean,compile"
   description="Clean build and dist directories, then compile"/>

<!-- ================== Clean Target ============================== -->

  <target name="clean"
   description="Delete old build and dist directories">
    <delete dir="${build.home}"/>
    <delete dir="${dist.home}"/>
  </target>

<!-- ================== Compile Target =========================== -->

    <target name="compile" depends="prepare"
   description="Compile Java sources">
    <mkdir dir="${build.home}/classes"/>
    <javac srcdir="${src.home}"
          destdir="${build.home}/classes"
            debug="${compile.debug}"
      deprecation="${compile.deprecation}"
         optimize="${compile.optimize}">
        <classpath refid="compile.classpath"/>
    </javac>
    <copy todir="${build.home}">
      <fileset dir="${base.home}" excludes="**/*.java **/*.bak **/*.log*"/>
    </copy>
  </target>

<!-- =================== Dist Target ================================ -->

    <target name="dist" depends="compile,javadoc"
   description="Create binary distribution">
    <basename property="basedir.name" file="."/>

    <mkdir dir="${dist.home}/docs"/>
    <copy todir="${dist.home}/docs">
      <fileset dir="${docs.home}" excludes="**/*.bak"/>
    </copy>

    <mkdir dir="${dist.home}/lib"/>
    <jar jarfile="${dist.home}/lib/${app.name}${app.version}.jar"
         basedir="${build.home}/classes"
         excludes="**/*.bak"/>

    <copy todir="${dist.home}/lib">
      <fileset dir="${build.home}/lib" excludes="**/*.bak"/>
    </copy>

    <copy todir="${dist.home}">
      <fileset dir="${base.home}" excludes="**/*.bak"/>
    </copy>

    <zip destfile="${dist.home}/${app.name}_${basedir.name}
      -${DSTAMP}${TSTAMP}.zip" basedir="${dist.home}"
      excludes="**/*.bak **/*.log*" update="true" />

  </target>

<!-- ================== Javadoc Target ============================ -->

    <target name="javadoc" depends="compile"
   description="Create Javadoc API documentation">

    <mkdir dir="${dist.home}/docs/api"/>
    <javadoc sourcepath="${src.home}"
                destdir="${dist.home}/docs/api"
           packagenames="*">
      <classpath refid="compile.classpath"/>
    </javadoc>

  </target>

<!-- ================== Prepare Target ============================= -->

  <target name="prepare">
    <tstamp/>
    <mkdir dir="${build.home}"/>
    <mkdir dir="${build.home}/classes"/>
    <mkdir dir="${build.home}/lib"/>
    <copy todir="${build.home}/lib">

 <!-- Includere qui le librerie esterne da importare nel progetto
   ed indicate in "External Dependencies" -->

      <fileset dir="${shared.lib}" includes="${log4j.jar}"/>
    </copy>
  </target>

<!-- ================== RmBak Target ============================= -->

  <target name="rmbak"
   description="Delete *.bak files everywhere">

  <delete>
    <fileset dir="${docs.home}" includes="**/*.bak"/>
    <fileset dir="${src.home}" includes="**/*.bak"/>
  </delete>

  </target>

<!-- ================== RmLog Target ============================= -->

  <target name="rmlog"
   description="Delete *.log files from build directory">

  <delete>
    <fileset dir="${build.home}" includes="**/*.log*"/>
  </delete>

  </target>
  </project>

Eseguendo adesso il comando ant compile, avviamo automaticamente la compilazione di tutti i sorgenti che si trovano dentro la cartella src.  Se la compilazione va a buon fine (codice sorgente esente da errori), viene creata una cartella buildche contiene tutte le classi compilate e l’eseguibile per avviare la nostra applicazione.

Eseguendo invece il comando ant dist, viene creata una cartella dist che, oltre a contenere la distribuzione binaria della nostra applicazione (AntExample.jar), contiene la documentazione del nostro codice sorgente nel formato javadoc.

Nel successivo articolo vedremo come realizzare, compilare e deployare una Web Application mediante l’utilizzo di Ant.

 

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *

Questo sito usa Akismet per ridurre lo spam. Scopri come i tuoi dati vengono elaborati.