web-dev-qa-db-ja.com

複数のjarを結合するクリーンな方法?できればAntを使用して

いくつかの外部jarにランタイム依存関係があり、それらを単一のjarに「再jar」したい。これらの外部依存関係は、external_jarsディレクトリに格納されています。すべてをリストする必要はありません(つまり、依存関係が変更されてもビルドスクリプトを変更する必要はありません)。何かご意見は?

Googleはこれを行う方法について良い答えをくれました-依存関係として各jarをリストすることを気にしないのであれば:

http://markmail.org/message/zijbwm46maxzzoo5

大まかに言うと、libディレクトリ内のすべてのjarをout.jarに結合する(次の適切な上書きルールを使用する)次のようなものが必要です。

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

Antでzipgroupfilesetを使用するだけです Zipタスク

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

これにより、含まれているすべてのjarライブラリのコンテンツがフラット化されます。

55
Vladimir

ウラジミールの答えは正しいものですが、彼が提案することは、すべての瓶を1つの大きなout.jarに再梱包することを意味し、それは単一の<zipfileset>またはそのようなものとしてAnt Jarタスクに供給されます。この2段階のアプローチは不要です。これが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>
65
nightingale

Jarjarをチェックアウトできます。

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

23
Staale

まず、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です。

9
David Grant

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

これは私の解決策です:

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

質問はよく答えられます。便利だと思うツールを1つ挙げたいと思います- One-Jar 。 One-Jarは(すべてを保持することで)リソースをよりクリーンに処理します。これは、コードで MANIFESTファイルの処理 が必要な場合に便利です。

Webサイトからコピーされたサンプル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>
1
Jayan

Antでビルドしている場合(私はEclipseのantを使用しています)、antに言って追加のjarファイルを追加するだけです。一人のプロジェクトのため、簡単です。

たとえば、.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>

1行追加して作成しました。

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

どこで

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

外部jarのあるディレクトリでした。それだけです...複数のzipgroupfilesetタグを追加することもできます。

1
ntg

Maven または依存関係を自動的に管理する他のシステムの使用を検討しましたか?次に、各ライブラリの場所、ライブラリの名前、および直接依存関係にある推移的な依存関係を指定する必要はありません。依存関係とそのバージョンを1か所に記述するだけで、システムがライブラリのダウンロード、クラスパスの構成、プロジェクトのビルドを処理します。

1
Esko Luontola

まあ、私はプログラミングにはあまり興味がありません-しかし、もっと簡単なものが私のために働いた...質問が意味するなら-jarファイルを1つに結合します。もちろん、これは手動の汚い解決策です。すべてのtarをuntarしました...そして、新しいtarファイルにuntarring-inによって形成されたすべてのディレクトリを追加して、新しいtarファイルを作成しました。出来た。

0
Sowmya

Mavenまたはその他のビルドツールは、クラスファイルの複数のバージョンの解像度を「管理」できません。実際、Mavenは、プロジェクトで明示的に必要とされていないすべてのダウンストリームjarファイルを推移的に含めることにより、そもそもこれらの問題を引き起こします。

プロジェクトの推移的な閉鎖のどこか(プロジェクトに必要なすべてのライブラリとモジュール、およびすべての依存プロジェクト、再帰的に)に、クラスファイルの2つのバージョンがあるとします。 Mavenは、どれが「正しい」ものであるかをどのようにして知ることができますか?プログラマーが意図したものはどれですか?

明示的な依存関係が一時的な依存関係(XMLの型付けを保存するため)を優先して破棄されたときに、この情報が失われたためにできません。

0
hans anderson