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

nye*_*yet 5 java installation javapackager

我想从同一源代码树和同一台机器上构建 .msi、.deb 和 .pkg。

Java9+ 的可分发运行时不再可下载,因此像 launch4j+nsis 这样的完美解决方案不再有效。

javapackager 已经被 Oracle 抛弃了。

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

有没有办法在同一台机器上为 win/linux/macos 构建安装程序?

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

我有一个遗留的 java 应用程序,现在处于不确定状态,因为 MacOS java8 不支持 java.awt.desktop,它需要 java9+

Jas*_*son 3

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

\n\n

简短的回答是:你可以做到这一点。

\n\n

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

\n\n

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

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

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

\n\n

如果您的应用程序具有 jar 依赖项(例如来自 Maven 中心),则您\xe2\x80\x99 将需要将这些 jar 复制到该Greeter/app目录并app.classpathGreeter/app/Greeter.cfg文件中更新。同样,所有这些都可以在任何平台上完成,无需启动目标平台(在我的例子中是 Windows)。

\n\n

此外,jpackage它是官方支持的工具,但仅在 EA JDK 14 中可用(我写的时间是 2020 年 2 月)。JDK 14 可以下载并jpackage与其他版本的 JDK(例如 JDK 11 LTS)一起使用。

\n\n

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

\n\n

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

\n\n

GitHub 上有一个示例项目,其中有很多关于如何运行jlink和的有用命令行示例jpackage: https: //github.com/jtconnors/SocketClientFX \n尽管该项目使用过时的命令选项。您可以运行jpackage --help以获取新选项。

\n\n

有用的链接:

\n\n

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

\n\n

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

\n\n

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

\n\n

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

\n