2009-11-30 21 views
57

Estoy usando Ant para construir algunos proyectos Java.
En algunos, tengo un directorio lib/, que contiene dependencias externas, en forma de archivos JAR.Creando un paquete jar con ant

Durante la creación, creo un contenedor incluido, que contiene el código del proyecto, junto con las dependencias, agregando al archivo jar jar un zipfileset para cada uno de los archivos jar en el directorio lib/.

El problema es que cada vez que añada un frasco, o cambiar nombres, necesito recordar para actualizar el archivo build.xml, ya que no podía encontrar una manera de añadir los zipfilesets de una manera automática, que incluirá todos jarros en un cierto patrón (por ejemplo, lib/*.jar).

¿Hay una mejor manera de hacerlo?

He considerado escribir mi propia Ant Task para esto, o usar la ant API de Groovy para hacer esto programáticamente, pero me preguntaba si hay una forma de hacerlo usando la hormiga "vainilla".

Respuesta

50

En mi objetivo, tengo algo como esto:

<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> 

Y aquí es cómo construyo mi ruta de clases:

<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 se utiliza desde el objetivo del paquete publicado encima. Esta parte la copié de otro lado, así que no estoy tan familiarizado con ella.

Edición rápida. Javac también necesita saber sobre esos frascos.

<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

Aquí hay un método similar al de jonescb que contiene el final 'build.xml' (la gran imagen) que falta en esta respuesta: http://www.mkyong.com/ant/ant-create-a-fat-jar -file/ – Stephan

0

Aquí hay un ejemplo simple de un objetivo ant que creará un jar (llamado test.jar) que incluye todos los archivos jar bajo el directorio lib. Tal vez esto resolverá tu problema?

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

¿Los archivos jar pueden simplemente anidarse? ¿Estás seguro de que esto funcionará? – abyx

+0

hmmm, supongo que no, estaba pensando en guerras y webapps en lugar de jarras, lo siento por eso. – Upgradingdave

29

Utilice un zipgroupfileset. Por ejemplo:

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

El zipgroupfileset se documenta con la tarea Zip.

+0

Como respondió jonescb, esa es realmente la solución. Nunca lo vi, ya que está oculto en la tarea Zip – abyx

+0

El gran problema con esto es si los archivos jar tienen archivos adicionales, normalmente en el directorio MANIFEST. Por ejemplo, muchos de los frascos de marco de primavera contienen archivos spring.handlers, spring.schemas y spring.tooling que ... bueno, no he pensado cómo manejarlos ... fusionándolos? – ticktock

+1

@GeorgeBaxter He estado buscando lo mismo y terminé haciendo [esto] (http://stackoverflow.com/a/24083318/2208271). Avíseme si encuentra una mejor solución. – Sithsu

6

Para aquellos de ustedes usando NetBeans aquí es cómo se puede crear archivo JAR con las bibliotecas liado usando zipgroupfileset:

<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> 

He añadido esta definición objetivo al final del archivo build.xml. El nombre del objetivo es -post-jar.

Cuestiones relacionadas