Вам никогда не надо было быстро создать установщик для своего Java-приложения, но не хотелось тратить на это кучу времени, создавая свой собственный? Возможно, вы удивитесь, но в стандартной поставке JDK7 такой инструмент уже присутствует.
Краткое описание
javafxpackager — утилита, созданная для того, чтобы создавать пакеты из программ написанных с помощью JavaFX. Через некоторое время после создания в Oracle решили, что эта же утилита может создавать пакеты и для программ, написанных чисто на Java. Название решили не менять.
Что подаётся на вход? Вы можете подавать на вход как директорию с уже скомпилированными исходниками, так и уже собранный jar. Дальше jar упаковывается вместе с JRE и вы можете подавать это пользователю с ещё не установленной java. Это позволяет не заставлять пользователя устанавливать JRE самостоятельно. Итак, как этим пользоваться?
Примеры использования
Предположим, у нас есть некий HelloWorld-проект: просто директория src с вложенной директорией helloworld и в ней HelloWorld.java:
package helloworld; public class HelloWorld { public static void main (String[] args) { System.out.println ("Hello, world!"); } }
В корне лежит простейший ant'овый build.xml, который умеет только собирать class-файлы:
<?xml version="1.0" encoding="UTF-8"?> <project name="Generic" default="compile" basedir="."> <target name="compile"> <mkdir dir="build/classes"/> <javac srcdir="src" destdir="build/classes" executable="${java.sdk}/bin/javac"/> </target> </project>
Итак, просто соберём проект:
$ ant compile
С помощью javafxpackager можно собирать jar'ы, что мы и сделаем (предварительно создав директорию dist):
$ javafxpackager -createjar -srcdir build/classes -outfile dist/HelloWorld.jar -appclass helloworld.HelloWorld
Если посмотреть на содержимое созданного jar'a, мы увидим, что он несколько отличается от стандартно создаваемого:
$ unzip -l dist/HelloWorld.jar Archive: dist/HelloWorld.jar Length Date Time Name --------- ---------- ----- ---- 0 2013-04-29 15:50 META-INF/ 158 2013-04-29 15:50 META-INF/MANIFEST.MF 0 2013-04-29 15:50 helloworld/ 353 2013-04-29 15:50 helloworld/HelloWorld.class 0 2013-04-29 15:50 com/ 0 2013-04-29 15:50 com/javafx/ 0 2013-04-29 15:50 com/javafx/main/ 2671 2013-04-29 15:50 com/javafx/main/Main$1.class 5633 2013-04-29 15:50 com/javafx/main/NoJavaFXFallback.class 19218 2013-04-29 15:50 com/javafx/main/Main.class 1747 2013-04-29 15:50 com/javafx/main/Main$2.class --------- ------- 29780 11 files
Распаковав его и открыв MANIFEST.MF, мы также увидим, что метод включения тоже несколько отличается от стандартного (он характерен для JavaFX):
Manifest-Version: 1.0 JavaFX-Version: 2.2 JavaFX-Application-Class: helloworld.HelloWorld Created-By: JavaFX Packager Main-Class: com/javafx/main/Main
Далее, перейдём к самому созданию пакетов. По умолчанию директива deploy создаёт только jnlp и html с встроенным плагином.
Но если указать директиву -native all, то создаётся пакет, специфичный для данной операционной системы: deb и rpm для Linux (любых, содержащих dpkg или rpmbuild для каждого из пакетов соответственно), exe и msi для Windows (к сожалению, здесь существует ограничение и должны быть установлены следующие утилиты: Inno Setup для создания exe и WiX Toolset для msi) и app с dmg для MacOS X. Давайте сразу создавать нативные пакеты (jar мы уже, предположительно, создали):
javafxpackager -deploy -v -srcdir dist -outdir dist -outfile HelloWorld -appclass helloworld.HelloWorld -native all
После этого некоторое время будет происходить сборка. Теперь у нас в директории dist появились различные bundle'ы: 2 пакетных (для разных ОС — разные) и 1, который является по сути распакованным пакетом: директория HelloWorld, в которой лежит бинарник HelloWorld, запуская который мы получаем сразу результат:
Hello, world!
Этот код запускается с уже запакованной в директории JRE.
А пакеты можно уже устанавливать.
Но как добавлять такую сборку в проект?
Есть 2 способа: можно использовать тот же самый javafxpackager, добавляя его в ваши, например, ant-скрипты, с помощью, например, exec'a. Но можно сделать куда круче. В ту же поставку java входит пакет ant-javafx.jar, который позволяет всё это же добавлять в ваши ant-скрипты. Что для этого надо сделать?
- Добавить поддержку ant-javafx: в корневом элементе xml-дерева project установить параметр
xmlns:fx="javafx:com.sun.javafx.tools.ant"
, а в его теле добавить
<taskdef resource="com/sun/javafx/tools/ant/antlib.xml" uri="javafx:com.sun.javafx.tools.ant" classpath=".${path.separator}${java.sdk}/lib/ant-javafx.jar"/>
, при этом у вас должна быть установлена переменная ${java.sdk} в корень JDK.
- jar:
<fx:jar destfile="dist/HelloWorld.jar"> <fx:application name="HelloWorld" mainClass="helloworld.HelloWorld" /> <fx:fileset dir="build/classes" /> <fx:manifest> <fx:attribute name="Implementation-Vendor" value="meAndMyCompany"/> <fx:attribute name="Implementation-Title" value="HelloWorld"/> <fx:attribute name="Implementation-Version" value="1.0"/> </fx:manifest> </fx:jar>
- deploy:
<fx:deploy width="100" height="100" nativeBundles="all" outdir="dist" outfile="HelloWorld"> <fx:application name="HelloWorld" mainClass="helloworld.HelloWorld"/> <fx:resources> <fx:fileset dir="dist" includes="*.jar"> </fx:resources> <fx:info title="HelloWorld" vendor="myAndMyCompany"/> </fx:deploy>
Что не работает?
- 64-битная JVM в Linux и Windows. Это связано с тем, что для неё существует только server-edition, а packager считает, что версия JVM — client
- Передача параметров в собранные бинарники
Где лежит подробная документация?
docs.oracle.com/javafx/2/deployment/javafxpackager001.htm — документация по javafxpackager
docs.oracle.com/javafx/2/deployment/javafx_ant_task_reference001.htm — документация по антовым таскам
docs.oracle.com/javafx/2/deployment/self-contained-packaging.htm — дополнительная информация
Автор: dginz