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
11 个解决方案
#1
53
Just use zipgroupfileset
with the Ant Zip task
只需使用带有Ant Zip任务的zipgroupfileset
<zip destfile="out.jar">
<zipgroupfileset dir="lib" includes="*.jar"/>
</zip>
This will flatten all included jar libraries' content.
这将使所有包含jar库的内容变得平坦。
#2
65
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.
弗拉基米尔的回答是正确的,但我觉得他的建议意味着把所有的罐子都装进一个大罐子里。jar,然后将其作为一个
<jar destfile="MyApplication.jar">
<zipgroupfileset dir="lib" includes="*.jar" />
<!-- other options -->
<manifest>
<attribute name="Main-Class" value="Main.MainClass" />
</manifest>
</jar>
#3
23
You could check out jarjar:
你可以看看jarjar:
http://code.google.com/p/jarjar/
http://code.google.com/p/jarjar/
#4
9
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.
$ {马歇尔。dir}是一个临时目录,${external.jar。dir}是保存JAR和${的地方。jar}是目标jar。
#5
4
If using maven, why wouldn't you ? :) Just use the maven-shade-plugin, works like a charm !
如果使用maven,为什么不呢?:)使用maven-shade插件,就像一个魅力!
<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>
#6
2
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>
#7
1
Have you considered using Maven or 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或其他自动管理依赖项的系统?然后,您就不需要指定每个库的位置、它们的名称以及您的直接依赖项具有哪些传递依赖项。您只需在一个地方声明依赖项及其版本,系统将负责下载库、配置类路径和构建项目。
#8
1
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.
这个问题回答得很好。我想提到一个我觉得有用的工具——一个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>
#9
1
If you are building with ant (I am using ant from eclipse), you can just add the extra jar files by saying to ant to add them... Not necessarily the best method if you have a project maintained by multiple people but it works for one person project and is easy.
如果您正在使用ant(我正在使用来自eclipse的ant)进行构建,您可以通过命令ant添加额外的jar文件……如果你有一个由多人维护的项目,它不一定是最好的方法,但是它适用于一个人的项目,而且很简单。
for example my target that was building the .jar file was:
例如,我构建.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>
I just added one line to make it:
我只是加了一行
<jar ....">
<zipgroupfileset dir="${external-lib-dir}" includes="*.jar"/>
<manifest>
................................
</manifest>
</jar>
where
在哪里
<property name="external-lib-dir" value="C:\...\eclipseWorkspace\Filter\external\...\lib" />
was the dir with the external jars. And that's it... You can add multiple zipgroupfileset tags as well.
是带有外部jar的dir。就是这样……您还可以添加多个zipgroupfileset标签。
#10
0
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文件合并到一个文件中。当然,这是手动的、肮脏的解决方案。我只是把所有的祭坛…然后. .通过在新的tar文件中添加untarring- in形成的所有目录,创建一个新的tar文件。它工作。
#11
0
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类型)。
#1
53
Just use zipgroupfileset
with the Ant Zip task
只需使用带有Ant Zip任务的zipgroupfileset
<zip destfile="out.jar">
<zipgroupfileset dir="lib" includes="*.jar"/>
</zip>
This will flatten all included jar libraries' content.
这将使所有包含jar库的内容变得平坦。
#2
65
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.
弗拉基米尔的回答是正确的,但我觉得他的建议意味着把所有的罐子都装进一个大罐子里。jar,然后将其作为一个
<jar destfile="MyApplication.jar">
<zipgroupfileset dir="lib" includes="*.jar" />
<!-- other options -->
<manifest>
<attribute name="Main-Class" value="Main.MainClass" />
</manifest>
</jar>
#3
23
You could check out jarjar:
你可以看看jarjar:
http://code.google.com/p/jarjar/
http://code.google.com/p/jarjar/
#4
9
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.
$ {马歇尔。dir}是一个临时目录,${external.jar。dir}是保存JAR和${的地方。jar}是目标jar。
#5
4
If using maven, why wouldn't you ? :) Just use the maven-shade-plugin, works like a charm !
如果使用maven,为什么不呢?:)使用maven-shade插件,就像一个魅力!
<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>
#6
2
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>
#7
1
Have you considered using Maven or 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或其他自动管理依赖项的系统?然后,您就不需要指定每个库的位置、它们的名称以及您的直接依赖项具有哪些传递依赖项。您只需在一个地方声明依赖项及其版本,系统将负责下载库、配置类路径和构建项目。
#8
1
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.
这个问题回答得很好。我想提到一个我觉得有用的工具——一个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>
#9
1
If you are building with ant (I am using ant from eclipse), you can just add the extra jar files by saying to ant to add them... Not necessarily the best method if you have a project maintained by multiple people but it works for one person project and is easy.
如果您正在使用ant(我正在使用来自eclipse的ant)进行构建,您可以通过命令ant添加额外的jar文件……如果你有一个由多人维护的项目,它不一定是最好的方法,但是它适用于一个人的项目,而且很简单。
for example my target that was building the .jar file was:
例如,我构建.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>
I just added one line to make it:
我只是加了一行
<jar ....">
<zipgroupfileset dir="${external-lib-dir}" includes="*.jar"/>
<manifest>
................................
</manifest>
</jar>
where
在哪里
<property name="external-lib-dir" value="C:\...\eclipseWorkspace\Filter\external\...\lib" />
was the dir with the external jars. And that's it... You can add multiple zipgroupfileset tags as well.
是带有外部jar的dir。就是这样……您还可以添加多个zipgroupfileset标签。
#10
0
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文件合并到一个文件中。当然,这是手动的、肮脏的解决方案。我只是把所有的祭坛…然后. .通过在新的tar文件中添加untarring- in形成的所有目录,创建一个新的tar文件。它工作。
#11
0
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类型)。