Чистый способ объединить несколько банок? Желательно с помощью Ant - PullRequest
58 голосов
/ 05 февраля 2009

У меня есть зависимости времени выполнения от некоторых внешних jar-файлов, которые я хотел бы "перераспределить" в один jar-файл. Эти внешние зависимости хранятся в каталоге external_jars, и я хотел бы иметь возможность не перечислять их все (т. Е. Не нужно менять сценарии сборки, если меняются зависимости). Есть мысли?

Google дал мне хороший ответ о том, как это сделать - если вы не возражаете, перечислив каждую банку в качестве зависимости:

http://markmail.org/message/zijbwm46maxzzoo5

Грубо говоря, я хочу что-то вроде следующего: объединить все jar-файлы из каталога lib в out.jar (с некоторыми нормальными правилами перезаписи).

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

Ответы [ 11 ]

65 голосов
/ 25 октября 2009

Ответ Владимира верен, но я чувствую, что то, что он предлагает, подразумевает переупаковку всех банок в один большой out.jar, который затем передается в задание Ant Jar как один <zipfileset> или что-то в этом роде. Этот двухэтапный подход не нужен. Я не уверен, связано ли это с версией 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>
54 голосов
/ 06 февраля 2009

Просто используйте zipgroupfileset с заданием Ant Zip

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

Это сгладит содержимое всех включенных jar-библиотек.

23 голосов
/ 05 февраля 2009

Вы можете проверить jarjar:

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

9 голосов
/ 05 февраля 2009

Попробуйте сначала извлечь ваши 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.

4 голосов
/ 31 января 2012

Если вы используете 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>
2 голосов
/ 14 января 2011

Это мое решение:

<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 голос
/ 25 апреля 2012

Если вы строите с помощью ant (я использую ant из eclipse), вы можете просто добавить дополнительные файлы 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>

Я просто добавил одну строку, чтобы сделать это:

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

, где

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

был каталог с внешними банками. И это все ... Вы также можете добавить несколько тегов zipgroupfileset.

1 голос
/ 14 марта 2012

На вопрос хорошо ответили. Я хотел упомянуть один инструмент, который я считаю полезным - One-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>
1 голос
/ 05 февраля 2009

Рассматривали ли вы использование Maven или какой-либо другой системы, которая автоматически управляет вашими зависимостями? Тогда вам не нужно будет указывать, где находится каждая библиотека, каковы их имена и какие транзитивные зависимости имеют ваши прямые зависимости. Вы бы просто указали в одном месте, какова зависимость и ее версия, и система позаботится о загрузке библиотек, настройке пути к классам и создании проекта.

0 голосов
/ 15 апреля 2010

Maven или другие инструменты сборки не могут "управлять" разрешением нескольких версий файлов классов. Фактически, Maven вызывает эти проблемы, в первую очередь, путем транзитивного включения всех последующих jar-файлов, которые явно не требуются для проекта.

Предположим, что где-то в транзитивном закрытии проекта (все библиотеки и модули, требуемые для проекта, и все его зависимые проекты, рекурсивно) существуют две версии файла классов. Как мог Мейвен узнать, какой из них «правильный»? какой был задуман программистом?

Не может, потому что эта информация была потеряна, когда явные зависимости были отброшены в пользу транзитивных (чтобы сохранить типизацию XML).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...