2009-11-30 6 views
57

J'utilise Ant pour créer des projets Java.
Dans certains, j'ai un répertoire lib/, qui contient des dépendances externes, sous la forme de fichiers JAR.Création d'un bocal avec ant

Lors de la génération, je crée un fichier jar contenant le code du projet, en plus des dépendances, en ajoutant au fichier jar du paquet un zipfileset pour chacun des fichiers jar du répertoire lib/. Le problème est que chaque fois que j'ajoute un pot, ou que je change de nom, je dois me rappeler de mettre à jour le fichier build.xml, car je ne pouvais pas trouver un moyen d'ajouter automatiquement les zipfilesets bocaux dans un certain modèle (par exemple lib/*.jar).

Existe-t-il une meilleure façon de procéder? J'ai envisagé d'écrire ma propre tâche Ant pour cela, ou d'utiliser l'API de Groovy pour le faire par programmation, mais je me demandais s'il y avait un moyen de le faire en utilisant "vanilla" ant.

Répondre

50

Dans mon objectif, j'ai quelque chose comme ceci:

<jar destfile="${store.dir}/temp_final.jar" filesetmanifest="skip"> 
    <zipgroupfileset dir="dist" includes="*.jar"/> 
    <zipgroupfileset dir="dist/lib" includes="*.jar" excludes=""/> 

    <manifest> 
     <attribute name="Main-Class" value="${main.class}"/> 
     <attribute name="Class-Path" value="${mf.classpath}"/> 
    </manifest> 
</jar> 

Et voici comment je construis mon classpath:

<path id="build.classpath"> 
    <fileset dir="${basedir}/"> 
     <include name="${lib.dir}/*.jar"/> 
    </fileset> 
</path> 

<pathconvert property="mf.classpath" pathsep=" "> 
    <path refid="build.classpath"/> 
    <mapper> 
     <chainedmapper> 
      <flattenmapper/> 
      <globmapper from="*.jar" to="lib/*.jar"/> 
     </chainedmapper> 
    </mapper> 
</pathconvert> 

mf.classpath est utilisé de la cible de package affiché au dessus. Cette partie que j'ai copiée d'ailleurs, donc je ne la connais pas très bien.

Modification rapide. Javac a également besoin de connaître ces bocaux.

<path id="jars"> 
    <fileset dir="${lib.dir}" includes="**/*.jar"/> 
</path> 

<target name="compile"> 
    <mkdir dir="${build.dir}"/> 
    <javac srcdir="${src.dir}" destdir="${build.dir}" classpathref="jars" debug="on"/> 
</target> 
+1

Voici une méthode similaire à celle de jonescb contenant le dernier 'build.xml' (la grande image) qui manque dans cette réponse: http://www.mkyong.com/ant/ant-create-a-fat-jar -file/ – Stephan

0

Voici un exemple simple d'une cible ant qui va créer un fichier jar (nommé test.jar) qui inclut tous les fichiers jar sous le répertoire lib. Peut-être que cela va résoudre votre problème?

<target name="jar"> 
    <jar destfile="test.jar"> 
     <fileset dir="lib/" includes="**/*.jar" /> 
    </jar> 
</target> 
+1

Les fichiers JAR peuvent-ils simplement être imbriqués? Êtes-vous sûr que cela fonctionnera? – abyx

+0

hmmm, je suppose que non, je pensais guerres et webapps au lieu de pots, désolé '. – Upgradingdave

29

Utilisez un zipgroupfileset. Par exemple:

<target name="jar"> 
    <jar destfile="foo.jar" basedir="${dir.classes}"> 
     <zipgroupfileset dir="lib" includes="*.jar"/> 
    </jar> 
</target> 

Le zipgroupfileset est documenté avec la tâche Zip.

+0

Comme jonescb a répondu, c'est vraiment la solution. Jamais vu, car il est caché dans la tâche Zip – abyx

+0

Le gros problème avec ceci est si les fichiers jar ont des fichiers supplémentaires, généralement dans le répertoire MANIFEST. Par exemple, la plupart des bocaux à ressort contiennent des spring.handlers, des spring.schemas et des spring.tooling files ... eh bien, je n'ai pas compris comment les gérer ... fusionner? – ticktock

+1

@GeorgeBaxter Été à la recherche de la même chose et a fini par faire [this] (http://stackoverflow.com/a/24083318/2208271). Faites-moi savoir si vous trouvez une meilleure solution. – Sithsu

6

Pour ceux d'entre vous ici en utilisant NetBeans comment vous pouvez créer une archive JAR avec les bibliothèques utilisant zipgroupfileset INCORPORES:

<target name="-post-jar"> 

    <property name="store.jar.name" value="MyJarName"/> 

    <property name="store.dir" value="dist"/> 
    <property name="store.jar" value="${store.dir}/${store.jar.name}.jar"/> 

    <echo message="Packaging ${application.title} into a single JAR at ${store.jar}"/> 

    <jar destfile="${store.dir}/temp_final.jar" filesetmanifest="skip"> 
     <zipgroupfileset dir="dist" includes="*.jar"/> 
     <zipgroupfileset dir="dist/lib" includes="*.jar"/> 

     <manifest> 
      <attribute name="Main-Class" value="${main.class}"/> 
     </manifest> 
    </jar> 

    <zip destfile="${store.jar}"> 
     <zipfileset src="${store.dir}/temp_final.jar" 
     excludes="META-INF/*.SF, META-INF/*.DSA, META-INF/*.RSA"/> 
    </zip> 

    <delete file="${store.dir}/temp_final.jar"/> 
    <delete dir="${store.dir}/lib"/> 
    <delete file="${store.dir}/README.TXT"/> 
</target> 

J'ai ajouté cette définition cible à la fin du fichier build.xml. Le nom de la cible est -post-jar.