猿问

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

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

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

javapackager 已被 Oracle 放弃。

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

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

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

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


慕田峪4524236
浏览 118回答 3
3回答

陪伴而非守候

我从 Java 9 开始就使用由不同的 docker 映像jlink和jpackage虚拟机组成的跨平台设置,我可以在我的目标平台上构建运行时和安装程序(MSI、DEB/RPM 和 DMG/PKG)主机系统。对于 Mac,如果您没有 Apple 硬件,则可以使用 KVM 映像,以便通过 ssh 发出命令。对于 Windows,使用 Linux docker 容器,其中包含 wine、Windows 的 OpenJDK、Visual Studio 构建工具、WIX 和 CMake 来执行运行时映像的构建以及自定义的 MSI 安装程序(因为版本太javapackage简单)

慕容3067478

你的问题的答案并不短。但我会尽量简短并指出所有相关信息。简短的回答是:你可以做到这一点。更长的答案是:您仍然需要从目标环境中为每个目标环境构建运行时,但只需执行一次。然后,您可以保存该运行时并重用它,以便在单一环境中使用最新的 Java jar/代码自动构建安装程序。例如,用于jlink构建运行时映像并jpackage为 Windows、Linux 和 macOS(在这些各自的系统上)构建应用程序映像,然后将这些应用程序映像复制到 macOS 并nsis为每个平台构建安装程序(或您选择的安装程序生成器)从 macOS 内部。当您更新代码并重新编译时,您只需将新的 jar 复制到预构建的应用程序映像中即可。您还必须复制所有依赖项,但这对于任何安装程序都是必要的。构建的运行时中有一个配置文件,jpackage其中包含选项、类路径等,您可以更改这些文件而无需重建运行时。创建一个可运行的程序,就像这样简单    package com.example;    public class Greeter {        public static void main(String[] args) {            System.out.println("Hi, I'm the greeter. Welcome.");        }    }编译程序并放入 jar 中(greeter.jar在本示例中调用它并放入构建目录中,target在本示例中调用)运行jilnk以构建运行时。以下命令使用jlinkJDK11 中的内容并将结果放入名为 的目录中runtime。此示例包括模块路径上的所有模块,但您可以使用它jdeps来仅获取所需的模块。如果您不想在项目发展并依赖更多 Java 运行时时重新构建此运行时,我建议包括所有模块。更不用说对 JRE 的传递依赖了。    > 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运行jpackage以构建适合打包在安装程序中的应用程序映像。jpackage它使用 JDK14 早期访问版的 jpackage(撰写本文时唯一的 JDK 版本)。命令行选项—win-console仅适用于 Windows,并且仅当程序使用 stdin/stdout(控制台)执行某些操作时才需要。我们的示例写入控制台,所以我们需要这个。运行应用程序时,此参数有时可能会打开控制台窗口,因此如果您有纯基于 Windows (gui) 的应用程序,请将其删除。    > 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运行应用程序.\Greeter\Greeter.exe生成的应用程序映像(在app-image目录中)可用于使用您最喜欢的安装构建器(我使用 NSIS)构建安装程序。您可以在任何平台上执行此操作。此外,当您更新程序时,您只需将新的 jar 复制到应用程序映像中。无需重建应用程序映像或运行时。该 jar 副本可以在任何平台上进行,并且无需运行 Windows 即可为新版本的应用程序构建新的安装程序。如果您的应用程序具有 jar 依赖项(例如来自 Maven 中心),则需要将这些 jar 复制到该Greeter/app目录并app.classpath在Greeter/app/Greeter.cfg文件中更新。同样,所有这些都可以在任何平台上完成,无需启动目标平台(在我的例子中是 Windows)。此外,jpackage它是官方支持的工具,但仅在 EA JDK 14 中可用(我写的时候是 2020 年 2 月)。JDK 14 可以下载并jpackage与其他版本的 JDK(例如 JDK 11 LTS)一起使用。

跃然一笑

在 Linux 上创建 Windows MyApp.exe 和 MyApp-setup.exe:jpackage我根本不需要,只需要jlink、launch4j和nsis:在本机使用jlink一次来创建运行时并压缩结果以供在其他计算机上使用。launch4j可以指示使用该运行时,并且nsis可以指示在安装时复制整个运行时。MyApp.app在 Linux 上创建 MacOS :用于jlink创建可重复用于重新创建的 tarfile Contents/runtime/Contents/Home(如上面的 Windows)复制jpackage生成的Contents/runtime/Contents/Info.plist和Contents/runtime/Contents/MacOS/libjli.dylib复制jpackage生成的Contents/MacOS/MyApp存根并 Contents/MacOS/libapplauncher.dyn希望它们永远不必更改。使用生成的模板作为参考从模板创建并Contents/Info.plist归档Contents/app/MyApp.cfgjpackage填写我的jar文件和其他Contents/app资源Contents/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到install4jhttps://www.ej-technologies.com/products/install4j/overview.html理论上,一旦我在 Linux 上完成所有工作,我就可以将工作移植到 Darwin 和 cygwin (WSL 对我来说不适合 atm,将在最后工作)概念证明在这里(linux、MacOS、cygwin):https://github.com/nyetwurk/ecuxplot考虑到 CI/CD 的兴起,而且 java 的重点是可移植性和架构独立性,这种多平台交叉编译工具在任何地方都不存在,这有点荒谬。
随时随地看视频慕课网APP

相关分类

Java
我要回答