2012-05-07 7 views
5

Ho uno script di build incorporato in Ant che ha un macrodef che accetta alcuni parametri predefiniti, target, root e simili, e quindi due facoltativi , extrasrc-f ed extrasrc-c. Dopo che sono entrati, mi piace fare un controllo aggiornato su tutte le risorse pertinenti, quindi fare una build solo se il target non è aggiornato.Creare un elemento in stile Union e Macrodef con contenuto dinamico in runtime in Ant

Quello che ho in questo momento,

<?xml version="1.0" encoding="UTF-8"?> 
<project name="Custom build" default="default"> 

    <taskdef resource="net/sf/antcontrib/antlib.xml" 
     classpath="C:/dev/ant/ant-contrib/ant-contrib-1.0b3.jar"/> 

    <macrodef name="checkuptodate"> 
     <attribute name="target" /> 
     <element name="resource" /> 
     <sequential> 
      <condition property="needbuild"> 
       <and> 
        <resourcecount when="greater" count="0"> <resource /> </resourcecount> 
        <not> 
         <uptodate targetfile="@{target}"> 
          <srcresources> <resource /> </srcresources> 
         </uptodate> 
        </not> 
       </and> 
      </condition> 
     </sequential> 
    </macrodef> 

    <macrodef name="projbuild"> 
     <attribute name="root" /> 
     <attribute name="target" /> 

     <element name="extrasrc-f" optional="true" /> 
     <element name="extrasrc-c" optional="true" /> 
     <sequential> 
      <local name="needbuild" /> 
      <checkuptodate target="@{root}/bin/@{target}"> 
       <resource> 
        <union> 
         <extrasrc-f /> 
         <fileset dir="@{root}/src" includes="**/*.java" /> 
        </union> 
       </resource> 
      </checkuptodate> 

      <if> 
       <istrue value="${needbuild}" /> 
       <then> 
        <javac 
         srcdir="@{root}/src" 
         destdir="@{root}/bin" 
         includeantruntime="false" 
        > 
         <extrasrc-c /> 
        </javac> 
       </then> 
      </if> 

     </sequential> 
    </macrodef> 

    <target name="default"> 

     <projbuild root="." target="EntryPoint.class"> 
      <extrasrc-f> 
       <fileset dir="Proj2/src" includes="**/*.java" /> 
       <fileset dir="Proj3/src" includes="**/*.java" /> 
      </extrasrc-f> 
      <extrasrc-c> 
       <classpath location="Proj2/src" /> 
       <classpath location="Proj3/src" /> 
      </extrasrc-c> 
     </projbuild> 

    </target> 

</project> 

Ma come si può vedere, a questo punto nel tempo, per me è inefficiente, a fare quello che voglio, ho per creare e passare a almeno un set di file e più percorsi di classe. Quello che mi piacerebbe davvero fare è passare in una lista di directory, quindi creare gli elementi extrasrc-f ed extrasrc-c al volo da quelle informazioni, ma per la vita di me, non ho idea di come Sono in grado di farlo.

Ho letto molto su molte delle classi funky Ant e Ant-Contrib, ma non ho letto nulla che mi permettesse di fare qualcosa di simile, che trovo strano, perché per me sembra un situazione ovvia.

Mi sto avvicinando a questo in un modo molto sbagliato, o c'è qualcosa che mi manca? Se utilizzo in modo errato Ant, mi piacerebbe che i puntatori vadano nella giusta direzione su come farlo correttamente, creare un catchall, creare template in un macrodef (o target, se questo è l'unico modo per farlo) che verifica più sorgenti file contro un file che viene creato, passando anche in altri percorsi di classe o libreria, preferibilmente in una singola lista.

risposta

0

Forse è possibile utilizzare un paio di attività <scriptdef> per aiutare a suddividere quelle macro.

Primo, uno che prende un elenco separato da virgole di directory e genera lo <union> da esse. Si fornisce il refid che si desidera utilizzare per fare riferimento all'unione come attributo id. Sono inclusi ed esclusi facoltativi.

<scriptdef name="dirs2union" language="javascript"> 
    <attribute name="dirs" /> 
    <attribute name="id" /> 
    <attribute name="includes" /> 
    <attribute name="excludes" /> 
    <![CDATA[ 
     var dirs = attributes.get("dirs").split(","); 
     var includes = attributes.get("includes"); 
     var excludes = attributes.get("excludes"); 

     var union = project.createDataType("union"); 
     project.addReference(attributes.get("id"), union); 

     for (var i = 0; i < dirs.length; i++) { 
      var fs = project.createDataType("fileset"); 
      fs.setDir(new java.io.File(dirs[i])); 
      if (includes) 
       fs.setIncludes(includes); 
      if (excludes) 
       fs.setExcludes(excludes); 

      union.add(fs); 
     } 
    ]]> 
</scriptdef> 

Il secondo - molto simili - script fa l'equivalente per la generazione di percorso:

<scriptdef name="dirs2path" language="javascript"> 
    <attribute name="dirs" /> 
    <attribute name="id" /> 
    <![CDATA[ 
     var dirs = attributes.get("dirs").split(","); 

     var path = project.createDataType("path"); 
     project.addReference(attributes.get("id"), path); 

     for (var i = 0; i < dirs.length; i++) { 
      var pe = project.createDataType("path"); 
      pe.setLocation(new java.io.File(dirs[i])); 
      path.add(pe); 
     } 
    ]]> 
</scriptdef> 

Un esempio di utilizzo potrebbe allora essere qualcosa del tipo:

<property name="dirs" value="Proj2/src,Proj3/src" /> 

<dirs2union dirs="${dirs}" id="my.union" includes="**/*.java" /> 
<dirs2path dirs="${dirs}" id="my.path" /> 

... later (e.g.) ... 

<union refid="my.union" /> 
<classpath refid="my.path" /> 

È quindi possibile modificare le macro o prendere l'attributo dirs e generare internamente e classpath, o magari generarli una volta altrove e passare semplicemente i riferimenti.

Non ho tentato di includere le directory @{root} in questa illustrazione, ma dovrebbe essere possibile adattare quanto sopra per quello.

+0

Ci scusiamo per la risposta lenta, uh. –

+0

Haha, non ti preoccupare Martin, una risposta è sempre apprezzata, anche se in ritardo. Da quando ho fatto questa domanda, non sono più con la stessa compagnia, ma gioco regolarmente con gli script di Ant, e non avevo idea di scriptdef, grazie mille per questo! – seaders

Problemi correlati