Java 组合多个罐子的干净方法?最好使用 Ant
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/515428/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Clean way to combine multiple jars? Preferably using Ant
提问by Jacob
I have runtime dependencies on some external jars that I would like to "rejar" into a single jar. These external dependencies are stored in an external_jars directory, and I'd like to be able to not have to list them all (i.e., not to need to change my build scripts if my dependencies change). Any thoughts?
我对一些外部 jar 有运行时依赖关系,我想将它们“rejar”到单个 jar 中。这些外部依赖项存储在 external_jars 目录中,我希望不必将它们全部列出(即,如果我的依赖项发生变化,则不需要更改我的构建脚本)。有什么想法吗?
Google gave me a good answer on how to do this - if you don't mind listing out each jar as a dependency:
谷歌给了我一个很好的答案,告诉我如何做到这一点——如果你不介意将每个 jar 列为依赖项:
http://markmail.org/message/zijbwm46maxzzoo5
http://markmail.org/message/zijbwm46maxzzoo5
Roughly, I want something along the lines of the following, which would combine all jars in the lib directory into out.jar (with some sane overwrite rules).
粗略地说,我想要一些类似于以下内容的东西,它将 lib 目录中的所有 jar 组合到 out.jar (具有一些合理的覆盖规则)。
jar -combine -out out.jar -in lib/*.jar
采纳答案by Vladimir
Just use zipgroupfileset
with the Ant Zip task
只需zipgroupfileset
与 Ant Zip 任务一起使用
<zip destfile="out.jar">
<zipgroupfileset dir="lib" includes="*.jar"/>
</zip>
This will flatten all included jar libraries' content.
这将展平所有包含的 jar 库的内容。
回答by Staale
回答by David Grant
Try extracting your JAR's to a marshalling directory first:
首先尝试将 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>
Where ${marshall.dir}
is a temporary directory, ${external.jar.dir}
is where you keep the JAR's, and ${combined.jar}
is the target JAR.
Where${marshall.dir}
是临时目录,${external.jar.dir}
是您保存 JAR 的位置,${combined.jar}
是目标 JAR。
回答by Esko Luontola
Have you considered using Mavenor some other system which manages your dependencies automatically? Then you would not need to specify where each library is located, what their names are, and what transitive dependencies your direct dependencies have. You would just state in one place what the dependency and its version are, and the system would take care of downloading the libraries, configuring the classpath and building the project.
您是否考虑过使用Maven或其他一些自动管理您的依赖项的系统?那么您就不需要指定每个库的位置、它们的名称以及您的直接依赖项具有哪些传递依赖项。您只需在一个地方说明依赖项及其版本是什么,系统将负责下载库、配置类路径和构建项目。
回答by nightingale
Vladimir's answer is a correct one, but I feel that what he suggests implies repacking all jars in a one big out.jar, which is then feeded to Ant Jar task as a single <zipfileset>
or something like that. This two-step approach is unnecessary. I'm not sure whether this is connected with Ant version, but I have Ant 1.7.1, and its <jar>
task understands <zipgroupfileset>
, which allows to feed all contents of third party jars' directly.
Vladimir 的回答是正确的,但我觉得他的建议意味着将所有罐子重新打包在一个大的 out.jar 中,然后将其作为单个<zipfileset>
或类似的东西提供给 Ant Jar 任务。这种两步法是不必要的。我不确定这是否与 Ant 版本有关,但我有 Ant 1.7.1,它的<jar>
任务理解<zipgroupfileset>
,它允许直接提供第三方 jars 的所有内容。
<jar destfile="MyApplication.jar">
<zipgroupfileset dir="lib" includes="*.jar" />
<!-- other options -->
<manifest>
<attribute name="Main-Class" value="Main.MainClass" />
</manifest>
</jar>
回答by Sowmya
Well, I am not so much in to programming - but something simpler worked for me...if the question meant - combining jar files in to one. Ofcourse, this is manual, dirty solution. I just untarred all the tars...and then..created a new tar file, by adding all the directories formed by untarring- in to the new tar file. it worked.
好吧,我不太喜欢编程 - 但更简单的东西对我有用......如果问题意味着 - 将 jar 文件合二为一。当然,这是手动的,肮脏的解决方案。我只是解压了所有的 tars...然后...创建了一个新的 tar 文件,通过将 untarring-in 形成的所有目录添加到新的 tar 文件中。有效。
回答by hans anderson
Maven or other build tools can't "manage" the resolution of multiple versions of class files. In fact, Maven causes these problems in the first place, through transitive inclusion of all downstream jar files that are not explicitly required by a project.
Maven 或其他构建工具无法“管理”多个版本的类文件的解析。事实上,Maven 首先通过传递包含项目未明确要求的所有下游 jar 文件来导致这些问题。
Suppose somewhere in the transitive closure of a project (all libraries and modules required by the project, and all it's dependent projects, recursively) there are two versions of a class file. How could Maven possibly know which one is the 'correct' one? which one was intended by the programmer?
假设在一个项目的传递闭包(项目所需的所有库和模块,以及所有它的依赖项目,递归)的某个地方,有两个版本的类文件。Maven 怎么可能知道哪一个是“正确”的?哪个是程序员打算的?
It can't because this information was lost when explicit dependencies were thrown away in favor of transitive ones (to save XML typing).
不能,因为当显式依赖项被丢弃以支持传递依赖项(以节省 XML 类型)时,此信息丢失了。
回答by Matt
This is my solution:
这是我的解决方案:
<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>
回答by Mozart Brocchini
If using maven, why wouldn't you ? :) Just use the maven-shade-plugin, works like a charm !
如果使用 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>
回答by Jayan
The question is well answered. I wanted mention one tool I find useful - One-Jar. One-Jar handles resources more cleanly (by keeping all of them). This more useful if the code needs to process MANIFEST files.
这个问题很好回答。我想提到一个我觉得有用的工具 - One-Jar。One-Jar 更干净地处理资源(通过保留所有资源)。如果代码需要处理清单文件,这会更有用。
Sample XML copied from website..
从网站复制的示例 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>