有没有一种方法可以为同一平台上的多个目标的Java应用程序构建安装程序?

时间:2019-11-02 22:36:54

标签: java installer javapackager

我想从相同的源树和同一台计算机上构建.msi,.deb和.pkg。

Java9 +的可分发运行时不再可下载,因此,launch4j + nsis之类的理智解决方案将不再起作用。

javapackager已被Oracle放弃。

OpenJDK的jpackager不能(也永远不会)针对不同的构建项目进行交叉编译,它甚至还不是真正的产品。

是否可以在同一台计算机上为win / linux / macos构建安装程序?

“一次编译,到处运行”的承诺真的死了吗?

我有一个遗留的Java应用程序,现在处于困境,因为MacOS java8不支持java.awt.desktop,这需要java9 +

3 个答案:

答案 0 :(得分:1)

您的问题的答案不短。但我会尽量简短,并指向所有相关信息。

简短的答案是:您可以做到。

更长的答案是:您仍然必须从该目标环境中为每个目标环境构建运行时,但是您只需执行一次。然后,您可以保存该运行时并重复使用,以在单个环境中使用最新的Java jar /代码自动构建安装程序。例如,使用jlink构建运行时映像,使用jpackage构建适用于Windows,Linux和macOS(在相应系统上)的应用程序映像,然后将这些应用程序映像复制到macOS并构建{{ 1}}安装程序(或您选择的安装程序生成器),用于macOS中的每个平台。

更新代码并重新编译时,您可以将新的jar复制到预先构建的应用程序映像中。您还必须复制所有依赖项,但这对于任何安装程序都是必需的。由nsis构建的运行时中有一个配置文件,其中包含选项,类路径等,您可以更改它们而无需重建运行时。

  1. 创建一个可运行的程序,就像
  2. 一样简单
jpackage
  1. 编译程序并将其放置在jar中(在本示例中称为 package com.example; public class Greeter { public static void main(String[] args) { System.out.println("Hi, I'm the greeter. Welcome."); } } 并在构建目录中放置,在本示例中称为greeter.jar
  2. 运行target来构建运行时。以下命令使用JDK11中的jilnk,并将结果放入名为jlink的目录中。此示例包括模块路径上的所有模块,但是您可以使用runtime来获取所需的模块。我建议包括所有模块,如果您不想在项目发展时依赖于更多的Java运行时,则不必重新构建该运行时。更不用说对JRE的传递依赖。
jdeps
  1. 运行 > set JLINK=C:\Program Files\Java\jdk-11.0.6\bin\jlink.exe > "%JLINK%" --no-header-files --no-man-pages --compress=2 --strip-debug --add-modules ALL-MODULE-PATH --output runtime 以生成适合打包在安装程序中的应用程序映像。它使用来自JDK14早期访问的jpackage(在撰写本文时,唯一具有jpackage的JDK版本)。命令行选项jpackage仅适用于Windows,仅在程序使用stdin / stdout(控制台)执行某些操作时才需要。我们的示例写入控制台,因此我们需要这样做。该参数有时可能会在运行应用程序时打开控制台窗口,因此,如果您有基于Windows的纯(gui)应用程序,请将其删除。
—win-console
  1. 使用 > set JPKG=C:\Program Files\Java\jdk-14-ea\bin\jpackage.exe > "%JPKG%" --type app-image -i target —win-console -n Greeter --main-class com.example.Greeter --main-jar greeter.jar --runtime-image runtime
  2. 运行应用程序

生成的应用程序映像(在.\Greeter\Greeter.exe目录中)可用于与您最喜欢的安装生成器一起构建安装程序(我使用NSIS)。您可以在任何平台上执行此操作。此外,在更新程序时,只需要将新的jar复制到应用程序映像中。无需重建应用程序映像或运行时。该jar副本可以在任何平台上进行,并且无需运行Windows即可为新版本的应用程序构建新的安装程序。

如果您的应用程序具有jar依赖项(例如,来自Maven Central),则需要将这些jar复制到app-image目录中,并更新Greeter/app文件中的app.classpath。同样,所有这些都可以在任何平台上完成,而无需启动目标平台(在我的情况下为Windows)。

此外,Greeter/app/Greeter.cfg是受官方支持的工具,但仅在EA JDK 14(在我撰写本文时为2020年2月)中可用。可以下载JDK 14,并且jpackage可以与其他版本的JDK(例如JDK 11 LTS)一起使用。

请参见https://blogs.oracle.com/jtc/a-brief-example-using-the-early-access-jpackage-utility

jpackage的JEP已标记为“已关闭/已交付”,表明该工具已经成熟,正等待发布JDK 14:https://openjdk.java.net/jeps/343

GitHub上有一个示例项目,其中包含有关如何运行jpackagejlink的许多有用的命令行示例:https://github.com/jtconnors/SocketClientFX 尽管此项目使用了过时的命令选项。您可以运行jpackage来获取新选项。

有用链接:

JDK 14(最早访问日期为2020年3月17日):http://jdk.java.net/14/

说明jlink的非模块化用法:https://medium.com/azulsystems/using-jlink-to-build-java-runtimes-for-non-modular-applications-9568c5e70ef4

jlink手册:https://docs.oracle.com/javase/9/tools/jlink.htm#JSWOR-GUID-CECAC52B-CFEE-46CB-8166-F17A8E9280E9

jpackage-使用jpackage --help选项运行以获得良好的参考信息

答案 1 :(得分:1)

我从Java 9开始使用jlinkjpackage的跨平台安装程序,该安装程序由不同的docker映像和虚拟机组成,可以在其中构建运行时和安装程序(MSI,DEB / RPM和DMG / PKG)在我的主机系统中的目标平台上。

对于Mac,如果没有Apple Hardware,则可以使用KVM映像,您可以在其中通过ssh发出命令。

对于Windows,使用Linux docker容器,其中装有酒,用于Windows的OpenJDK,Visual Studio构建工具,用于执行运行时映像构建的WIX和CMake以及自定义的MSI安装程序(自{{ }}版本太简单了

答案 2 :(得分:0)

在linux上创建Windows MyApp.exe和MyApp-setup.exe:

我根本不需要jpackage,只需要jlinklaunch4jnsis

  • 原生使用jlink来创建运行时和tar,
    可在其他计算机上使用的结果。
  • 可以指示
  • launch4j使用该运行时,而nsis可以
    要求在安装时复制整个运行时。

在linux上创建MacOS MyApp.app

  • 使用jlink创建一个可重复使用的tarfile,以重新创建 Contents/runtime/Contents/Home(例如上面的窗口)
  • 复制在jpackage中生成的
    Contents/runtime/Contents/Info.plist
    Contents/runtime/Contents/MacOS/libjli.dylib
  • 复制在jpackage生成的Contents/MacOS/MyApp存根中,然后 Contents/MacOS/libapplauncher.dyn,希望他们永远不必 改变。
  • 从以下位置创建Contents/Info.plistContents/app/MyApp.cfg文件 jpackage生成的模板作为参考的模板
  • 使用我的jar文件和其他资源填充Contents/appContents/Resources

在Linux上创建pkg:

https://gist.github.com/msabramo/2a8e44eb6dcc3b89437d33649b0b1841

在linux上创建dmg:

https://askubuntu.com/questions/1117461/how-do-i-create-a-dmg-file-on-linux-ubuntu-for-macos

或者,从nsis迁移到install4j

https://www.ej-technologies.com/products/install4j/overview.html

从理论上讲,一旦我所有的工作都可以在linux上进行,我就可以将精力转移到Darwin和cygwin上(WSL不适用于我的atm,最后可以正常工作)

概念证明在这里(Linux,MacOS,cygwin):

https://github.com/nyetwurk/ecuxplot

考虑到CI / CD的兴起以及Java的全部重点是可移植性和体系结构独立性,这种多平台交叉编译工具在任何地方都不存在真是荒谬。