干净的方式来结合多个jar子? 最好使用Ant

我有一些外部的瓶子,我想“rejar”到一个单一的jar的运行时依赖。 这些外部依赖关系存储在external_jars目录中,我希望能够不必全部列出(即,如果依赖关系发生变化,不需要更改构build脚本)。 有什么想法吗?

谷歌给了我一个很好的答案如何做到这一点 – 如果你不介意列出每个jar作为依赖:

http://markmail.org/message/zijbwm46maxzzoo5

粗略地说,我需要沿着以下几条线,这将把lib目录中的所有jar放到out.jar中(用一些合理的覆盖规则)。

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

只需使用zipgroupfileset与Ant Zip任务即可

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

这将压扁所有包含的jar库的内容。

弗拉基米尔的答案是正确的,但我觉得他的build议意味着重新包装一个大的out.jar中的所有jar,然后将它作为一个单独的<zipfileset>或类似的东西join到Ant Jar任务中。 这两步的方法是不必要的。 我不确定这是否与Ant版本连接,但是我有Ant 1.7.1,并且它的<jar>任务理解<zipgroupfileset> ,它允许直接提供第三方jar的所有内容。

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

你可以看看jarjar:

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

尝试首先解压缩您的JAR到编组目录:

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

其中${marshall.dir}是一个临时目录, ${external.jar.dir}是您保存JAR的位置, ${combined.jar}是目标JAR。

如果使用maven,为什么不呢? :)只要使用maven-shade-plugin,就像一个魅力!

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

这是我的解决scheme:

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

你有没有考虑过使用Maven或其他自动pipe理你的依赖的系统? 那么你不需要指定每个库的位置,它们的名字是什么,以及你的直接依赖关系具有的传递依赖性。 你只需在一个地方说明依赖和版本是什么,系统将负责下载库,configuration类path和构build项目。

这个问题很好回答。 我想提一个我觉得有用的工具 – 一个jar子 。 One-Jar更加干净地处理资源(保留所有这些资源)。 如果代码需要处理MANIFEST文件,这更有用。

从网站复制的示例XML

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

那么,我没有那么多的编程 – 但更简单的工作对我来说…如果这个问题意味着 – 将jar文件合并到一个。 当然,这是手动的,肮脏的解决scheme。 我只是解开所有的焦点…然后…创build一个新的tar文件,通过将untarring-in形成的所有目录添加到新的tar文件中。 有效。

Maven或其他构build工具不能“pipe理”多个版本的类文件的parsing。 事实上,Maven首先会导致这些问题,通过传递包含项目未明确要求的所有下游jar文件。

假设在某个项目的传递闭包中(项目所需的所有库和模块,以及所有依赖项目recursion地),有两个版本的类文件。 Maven怎么可能知道哪一个是“正确”的? 哪一个是程序员打算的?

它不能因为这个信息在显式依赖被抛弃而转移的时候丢失了(为了保存XMLtypes)。

如果你正在用ant(我使用eclipse中的ant)构build,你可以通过向ant添加额外的jar文件来添加它们…如果你有一个由多个人维护的项目,不一定是最好的方法,但它的工作原理为一个人的项目,很容易。

例如我的目标是build立.jar文件是:

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

我只是添加了一行来做到这一点:

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

哪里

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

是与外部jar子的目录。 就是这样…你也可以添加多个zipgroupfileset标签。