我想从相同的源树和同一台计算机上构建.msi,.deb和.pkg。
Java9 +的可分发运行时不再可下载,因此,launch4j + nsis之类的理智解决方案将不再起作用。
javapackager已被Oracle放弃。
OpenJDK的jpackager不能(也永远不会)针对不同的构建项目进行交叉编译,它甚至还不是真正的产品。
是否可以在同一台计算机上为win / linux / macos构建安装程序?
“一次编译,到处运行”的承诺真的死了吗?
我有一个遗留的Java应用程序,现在处于困境,因为MacOS java8不支持java.awt.desktop,这需要java9 +
答案 0 :(得分:1)
您的问题的答案不短。但我会尽量简短,并指向所有相关信息。
简短的答案是:您可以做到。
更长的答案是:您仍然必须从该目标环境中为每个目标环境构建运行时,但是您只需执行一次。然后,您可以保存该运行时并重复使用,以在单个环境中使用最新的Java jar /代码自动构建安装程序。例如,使用jlink
构建运行时映像,使用jpackage
构建适用于Windows,Linux和macOS(在相应系统上)的应用程序映像,然后将这些应用程序映像复制到macOS并构建{{ 1}}安装程序(或您选择的安装程序生成器),用于macOS中的每个平台。
更新代码并重新编译时,您可以将新的jar复制到预先构建的应用程序映像中。您还必须复制所有依赖项,但这对于任何安装程序都是必需的。由nsis
构建的运行时中有一个配置文件,其中包含选项,类路径等,您可以更改它们而无需重建运行时。
jpackage
package com.example;
public class Greeter {
public static void main(String[] args) {
System.out.println("Hi, I'm the greeter. Welcome.");
}
}
并在构建目录中放置,在本示例中称为greeter.jar
)target
来构建运行时。以下命令使用JDK11中的jilnk
,并将结果放入名为jlink
的目录中。此示例包括模块路径上的所有模块,但是您可以使用runtime
来获取所需的模块。我建议包括所有模块,如果您不想在项目发展时依赖于更多的Java运行时,则不必重新构建该运行时。更不用说对JRE的传递依赖。jdeps
> 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
> 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
目录中)可用于与您最喜欢的安装生成器一起构建安装程序(我使用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上有一个示例项目,其中包含有关如何运行jpackage
和jlink
的许多有用的命令行示例: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开始使用jlink
和jpackage
的跨平台安装程序,该安装程序由不同的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
,只需要jlink
,launch4j
和nsis
:
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.plist
和Contents/app/MyApp.cfg
文件
jpackage
生成的模板作为参考的模板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
迁移到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的全部重点是可移植性和体系结构独立性,这种多平台交叉编译工具在任何地方都不存在真是荒谬。