2009-02-05 20 views
56

Tengo dependencias de tiempo de ejecución en algunos archivos jar externos que me gustaría "volver a unir" en un solo contenedor. Estas dependencias externas se almacenan en un directorio external_jars, y me gustaría poder no tener que enumerarlas todas (es decir, no necesitar cambiar mis scripts de compilación si mis dependencias cambian). ¿Alguna idea?¿Manera limpia de combinar varios tarros? Preferiblemente usando Ant

Google me dio una buena respuesta sobre cómo hacer esto - si no te importa lista cabo cada frasco como una dependencia:

http://markmail.org/message/zijbwm46maxzzoo5

Aproximadamente, quiero algo en la línea de la siguiente , que combinaría todos los archivos jar en el directorio lib en out.jar (con algunas reglas de sobrescritura).

jar -combine -out out.jar -in lib/*.jar 

Respuesta

53

Sólo tiene que utilizar zipgroupfileset con la hormiga Zip task

<zip destfile="out.jar"> 
    <zipgroupfileset dir="lib" includes="*.jar"/> 
</zip> 

Esto se aplane el contenido de todas las bibliotecas tarro incluidos.

+0

Perdón por secuestrar la pregunta de otra persona. Hice esto, pero ahora puedo ejecutar mi aplicación. No puede encontrar algunas de las clases. ¿Debo todavía separar el classpath como java -cp xxx -jar yyy.jar? – uriDium

+8

Me entristece que todas las respuestas de trabajo parezcan girar en torno a la escritura de un archivo de compilación de ant y ninguna de ellas implica una simple invocación de línea de comandos. –

+2

Si lo hace en ant, puede incluirlo en su script de compilación como un objetivo, que es probablemente el único momento en el que desea hacerlo. –

23

se puede consultar jarjar:

http://code.google.com/p/jarjar/

+0

tres minutos para responder perfecto = <3 stackoverflow – Jacob

+2

doh! Miré en esto. Tiene mucha funcionalidad avanzada que resulta que no necesito. Lo que falta (al menos de los documentos en el sitio) es una forma fácil de hacer algo como: jar -combine -out out.jar -in lib/*. Jar que es lo que necesito – Jacob

+0

jar jar jar funciona –

9

Trate extraer el JAR en un directorio de clasificación en primer lugar:

<target name="combine-jars"> 
    <mkdir dir="${marshall.dir}"/> 
    <unzip dest="${marshall.dir}"> 
     <fileset dir="${external.jar.dir}"> 
      <include name="**/*.jar"/> 
     </fileset> 
    </unzip> 
    <jar destfile="${combined.jar}" basedir="${marshall.dir"}> 
    <delete dir="${marshall.dir}"/> 
</target> 

Dónde ${marshall.dir} es un directorio temporal, ${external.jar.dir} es donde se mantener los JAR, y ${combined.jar} es el JAR objetivo.

+2

Los ejemplos anteriores incluirán los otros jars -as jar! - en el archivo jar. Este, por otro lado, primero desinflará todos los archivos jar a * .class, y luego creará un jar de todos los archivos de clase. – Yossale

1

¿Ha considerado usar Maven o algún otro sistema que administre sus dependencias automáticamente? Entonces no necesitaría especificar dónde se encuentra cada biblioteca, cuáles son sus nombres y qué dependencias transitivas tienen sus dependencias directas. Simplemente indicaría en un solo lugar cuál es la dependencia y su versión, y el sistema se encargaría de descargar las bibliotecas, configurar el classpath y construir el proyecto.

65

La respuesta de Vladimir es correcta, pero creo que lo que sugiere implica volver a empaquetar todas las jarras en una gran out.jar, que luego se alimenta a la tarea Ant Jar como una sola <zipfileset> o algo así. Este enfoque de dos pasos es innecesario. No estoy seguro si esto está conectado con la versión Ant, pero tengo Ant 1.7.1, y su tarea <jar> comprende <zipgroupfileset>, lo que permite alimentar todo el contenido de los archivos jar de terceros directamente.

<jar destfile="MyApplication.jar"> 
    <zipgroupfileset dir="lib" includes="*.jar" /> 
    <!-- other options --> 
    <manifest> 
    <attribute name="Main-Class" value="Main.MainClass" /> 
    </manifest> 
</jar> 
0

Bueno, no soy tanto en la programación - pero algo más simple que funcionó para mí ... si la pregunta significaba - que combina los archivos JAR de a uno. Por supuesto, esta es una solución manual y sucia. Acabo de destrabar todos los tars ... y luego ... creé un nuevo archivo tar, agregando todos los directorios formados anulando el registro en el nuevo archivo tar. funcionó.

0

Maven u otras herramientas de compilación no pueden "administrar" la resolución de múltiples versiones de archivos de clase. De hecho, Maven causa estos problemas en primer lugar, a través de la inclusión transitiva de todos los archivos jar descendentes que no son explícitamente requeridos por un proyecto.

Supongamos que en algún lugar del cierre transitivo de un proyecto (todas las bibliotecas y módulos requeridos por el proyecto, y todos sus proyectos dependientes, recursivamente) hay dos versiones de un archivo de clase.¿Cómo podría Maven saber cuál es el "correcto"? ¿Cuál fue diseñado por el programador?

No puede porque esta información se perdió cuando se descartaron las dependencias explícitas en favor de las transitivas (para guardar el tipado XML).

+0

http://stackoverflow.com/questions/816858/maven-remove-a-single- La dependencia transitiva explica cómo excluir una dependencia transitiva. –

2

Esta es mi solución:

<target name="-post-jar"> 
    <echo>Packaging ${application.title} into a single JAR</echo> 

    <jar destfile="${basedir}${file.separator}${dist.dir}${file.separator}_${ant.project.name}_.jar"> 
     <zipgroupfileset dir="${basedir}${file.separator}${dist.dir}" includes="${ant.project.name}.jar"/> 
     <zipgroupfileset dir="${basedir}${file.separator}${dist.dir}${file.separator}lib" includes="*.jar"/> 
     <manifest> 
      <attribute name="Main-Class" value="${main.class}"/> 
     </manifest> 
    </jar> 
</target> 
+1

Cómo configurar valores de $ {basedir} $ {archivo.separador} – Mubasher

+0

@ Antubasher: $ Anticipo} y $ {archivo.separador} son proporcionados por Ant por defecto, no es necesario que los configure. Puede probar esto en un archivo build.xml simple: miproyecto $ {} $ {basedir file.separator}

4

Si se utiliza experto, ¿por qué no? :) ¡Solo use el plugin maven-shade, funciona como un encanto!

<project> 
    ... 
    <build> 
    <plugins> 
     <plugin> 
     <groupId>org.apache.maven.plugins</groupId> 
     <artifactId>maven-shade-plugin</artifactId> 
     <version>1.5</version> 
     <executions> 
      <execution> 
      <phase>package</phase> 
      <goals> 
       <goal>shade</goal> 
      </goals> 
      <configuration> 
       <transformers> 
       <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer"> 
        <mainClass>com.YOUR_COMPANY.YOUR_MAIN_CLASS</mainClass> 
       </transformer> 
       </transformers> 
      </configuration> 
      </execution> 
     </executions> 
     </plugin> 
    </plugins> 
    </build> 
    ... 
</project> 
1

La pregunta está bien respondida. Quería mencionar una herramienta que considero útil: One-Jar. One-Jar maneja los recursos de forma más limpia (manteniéndolos a todos). Esta más útil si el código XML necesita process MANIFEST files.

Muestra copiado desde el sitio web ..

<import file="one-jar-ant-task.xml"/> 

    <target name="hello" depends="init"> 
     <!-- Build lib.jar --> 
     <javac destdir="${classes.dir}/lib"> 
      <src path="${lib.dir}" /> 
     </javac> 
     <jar destfile="${build.dir}/lib.jar" > 
      <fileset dir="${classes.dir}/lib"/> 
     </jar> 
     <!-- Build classes for main.jar --> 
     <javac destdir="${classes.dir}/src"> 
      <src path="${src.dir}" /> 
      <classpath path="${build.dir}/lib.jar"/> 
     </javac> 
     <!-- Construct the One-JAR file --> 
     <one-jar destfile="hello.jar" manifest="hello.mf"> 
      <main> 
       <!-- Construct main.jar from classes and source code --> 
       <fileset dir="${classes.dir}/src"/> 
      </main> 
      <lib> 
       <fileset file="${build.dir}/lib.jar" /> 
      </lib> 
     </one-jar> 
     <echo> 
      Now you can run the Hello One-JAR example using 
      $ java -jar hello.jar 
     </echo> 

    </target> 
0

Si usted está construyendo con la hormiga (estoy usando la hormiga de Eclipse), sólo puede agregar los archivos jar adicionales diciendo a la hormiga para agregarlos ... No necesariamente el mejor método si tienes un proyecto mantenido por varias personas pero funciona para un proyecto de una persona y es fácil.

por ejemplo, mi objetivo que estaba construyendo el archivo .jar fue:

<jar destfile="${plugin.jar}" basedir="${plugin.build.dir}"> 
    <manifest> 
     <attribute name="Author" value="ntg"/> 
     ................................ 
     <attribute name="Plugin-Version" value="${version.entry.commit.revision}"/> 
    </manifest> 
</jar> 

acabo añade una línea para que sea:

<jar ...."> 
    <zipgroupfileset dir="${external-lib-dir}" includes="*.jar"/> 
    <manifest> 
     ................................ 
    </manifest> 
</jar> 

donde estaba

<property name="external-lib-dir" value="C:\...\eclipseWorkspace\Filter\external\...\lib" /> 

la dir con los frascos externos. Y eso es todo ... También puede agregar varias etiquetas zipgroupfileset.

Cuestiones relacionadas