为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

慕田峪4524236 2024-01-25 15:11:02
我想从同一源树和同一台机器上构建 .msi、.deb 和 .pkg。Java9+ 的可分发运行时不再可下载,因此像 launch4j+nsis 这样完美的解决方案不再有效。javapackager 已被 Oracle 放弃。OpenJDK 的 jpackager 无法(也永远不会)针对不同的构建项目进行交叉编译,而且它甚至还不是真正的产品。有没有办法从同一台机器构建 win/linux/macos 安装程序?“一次编译,到处运行”的承诺真的已经死了吗?我有一个遗留的java应用程序,现在处于不确定状态,因为MacOS java8不支持java.awt.desktop,它需要java9+
查看完整描述

3 回答

?
陪伴而非守候

TA贡献1757条经验 获得超8个赞

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

对于 Mac,如果您没有 Apple 硬件,则可以使用 KVM 映像,以便通过 ssh 发出命令。

对于 Windows,使用 Linux docker 容器,其中包含 wine、Windows 的 OpenJDK、Visual Studio 构建工具、WIX 和 CMake 来执行运行时映像的构建以及自定义的 MSI 安装程序(因为版本太javapackage简单)



查看完整回答
反对 回复 2024-01-25
?
慕容3067478

TA贡献1773条经验 获得超3个赞

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


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


更长的答案是:您仍然需要从目标环境中为每个目标环境构建运行时,但只需执行一次。然后,您可以保存该运行时并重用它,以便在单一环境中使用最新的 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)一起使用。


查看完整回答
反对 回复 2024-01-25
?
跃然一笑

TA贡献1826条经验 获得超6个赞

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

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

  • 在本机使用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

或者,从 迁移nsisinstall4j

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 的重点是可移植性和架构独立性,这种多平台交叉编译工具在任何地方都不存在,这有点荒谬。


查看完整回答
反对 回复 2024-01-25
  • 3 回答
  • 0 关注
  • 117 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信