Чистый способ объединить несколько банок? Предпочтительно с использованием муравья


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

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

http://markmail.org/message/zijbwm46maxzzoo5

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

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

11 ответов:

просто использовать zipgroupfileset С АНТ Zip task

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

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

ответ Владимира правильный, но я чувствую, что то, что он предлагает, подразумевает переупаковку всех банок в один большой выход.jar, который затем подается в задачу Ant Jar как один <zipfileset> или что-то подобное. Этот двухэтапный подход не нужен. Я не уверен, связано ли это с версией Ant, но у меня есть Ant 1.7.1, и его <jar> задач понимает <zipgroupfileset>, что позволяет напрямую подавать все содержимое сторонних банок.

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

попробуйте сначала извлечь свою банку в каталог сортировки:

<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} где вы держите банку, и ${combined.jar} является целевой банку.

Если вы используете 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>

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

<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 или какая-то другая система, которая автоматически управляет зависимостями? Тогда вам не нужно будет указывать, где находится каждая библиотека, каковы их имена и какие транзитивные зависимости имеют ваши прямые зависимости. Вы просто укажете в одном месте, что такое зависимость и ее версия, и система позаботится о загрузке библиотек, настройке пути к классам и создании проекта.

на этот вопрос есть хороший ответ. Я хотел упомянуть один инструмент, который я считаю полезным -One-Jar. One-Jar обрабатывает ресурсы более чисто (сохраняя все из них). Это более полезно, если код должен обрабатывать файлы манифеста.

образец 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>

Если вы строите с 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" />

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

Ну, я не столько в программировании, но что-то проще для меня...если вопрос подразумевал-объединение файлов jar в один. Конечно, это ручное, грязное решение. Я только что распотрошил все смолы...и..создал новый файл tar, добавив все каталоги, сформированные путем распаковки в новый файл tar. это сработало.

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

предположим, что где-то в транзитивном закрытии проекта (все библиотеки и модули, требуемые проектом, и все это зависимые проекты, рекурсивно) есть две версии файла класса. Как мог Maven возможно, знаете, какой из них "правильный"? какой из них был задуман программистом?

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