fvarrui / JavaPackager

:package: Gradle/Maven plugin to package Java applications as native Windows, MacOS, or Linux executables and create installers for them.
GNU General Public License v3.0
1.07k stars 134 forks source link

Two questions about the Maven plugin #346

Closed armin-reichert closed 1 year ago

armin-reichert commented 1 year ago

I'm submitting a…

I am using your Maven plugin in two of my projects and have two questions:

  1. Can I create an executable "uber"-jar in the same way as the Maven shade plugin? Do I still need Maven shade?
  2. Is it possible to create a Linux deployable archive including a Linux JVM from a Windows computer?

Steps to reproduce the issue/enhancement:

  1. See my attempts of using the plugin at https://github.com/armin-reichert/pacman-javafx/blob/main/pacman-ui-fx-2d/pom.xml and https://github.com/armin-reichert/pacman-javafx/blob/main/pacman-ui-fx-3d/pom.xml

What is the current behavior?

Other information (e.g. related issues, suggestions how to fix, links for us to have context)

fvarrui commented 1 year ago

Hi @armin-reichert!

I am using your Maven plugin in two of my projects and have two questions:

  1. Can I create an executable "uber"-jar in the same way as the Maven shade plugin? Do I still need Maven shade?

Yes, you have to set runnableJar property, pointing to your own uber/fat jar file.

  1. Is it possible to create a Linux deployable archive including a Linux JVM from a Windows computer?

Yes, JP uses non-system dependant libraries to generate both DEB and RPM packages, and you are doing it in the right way (setting a jdkPath for Linux) in order to embed a Linux JRE with your app.

  1. See my attempts of using the plugin at https://github.com/armin-reichert/pacman-javafx/blob/main/pacman-ui-fx-2d/pom.xml and https://github.com/armin-reichert/pacman-javafx/blob/main/pacman-ui-fx-3d/pom.xml

I tried to build your project, but pacman-core dependency is missing. I guess it's a private/local dependency.

What is the current behavior?

  • The "xxx-runnable.jar" created is not executable and the same as the "normal" jar created by Maven.
  • The Linux archive does not contain the Linux JVM despite I specifiy its location on my local system

I think changing your pom.xml in the next way will do the trick:

                    <execution>
                        <id>linux</id>
                        <!-- replace "none" by "package" to activate -->
                        <phase>package</phase>
                        <goals>
                            <goal>package</goal>
                        </goals>
                        <configuration>
                            <platform>linux</platform>
                            <createTarball>true</createTarball>
                            <jdkPath>C:\\dev\linux\jdk-17.0.7</jdkPath>
                            <bundleJre>true</bundleJre>
                            <runnableJar>${project.build.directory}/your-uber.jar</runnableJar>
                        </configuration>
                    </execution>
fvarrui commented 1 year ago

The "xxx-runnable.jar" created is not executable and the same as the "normal" jar created by Maven.

Yes, it is ... if you unzip "xxx-runnable.jar", it has inside META-INF/MANIFEST.MF file. This file contains the Main-Class property, which converts this JAR in runnable. But, don't try to run it from its directory, because libs are stored on another directory. This runnable JAR makes sense when copied into the generated app folder, next to libs directory.

armin-reichert commented 1 year ago

Dear Francisco,

thank you very much for your help!

I am able now to create a Linux "tarball" file which seems to contain everything. But I don't know how to create corresponding .deb or .rpm archives. I am also not sure what is the preferred archive type for different Linux versions (The last time I used Linux was in the 90s).

The updated https://github.com/armin-reichert/pacman-javafx/blob/main/pacman-ui-fx-2d/pom.xml contains my current attempt.

If you want to run the build locally you have to clone the repository https://github.com/armin-reichert/pacman-basic in addition to the pacman-javafx.

I did not understand the remark about the runnable jar. I still need the Maven shade plugin to create an executable jar with everything contained, right? So what is the benefit of addtionally creating the xxx-runnable.jar?

Best regards Armin Reichert

fvarrui commented 1 year ago

Hi @armin-reichert!

I am also not sure what is the preferred archive type for different Linux versions (The last time I used Linux was in the 90s).

DEB packages are for Debian based Linux distros and RPM for RedHat based ones. I think both are preferred.

The updated https://github.com/armin-reichert/pacman-javafx/blob/main/pacman-ui-fx-2d/pom.xml contains my current attempt.

If you want to run the build locally you have to clone the repository https://github.com/armin-reichert/pacman-basic in addition to the pacman-javafx.

Ok, I'll try to build your app for Windows and Linux and come back here with my feedback.

I did not understand the remark about the runnable jar. I still need the Maven shade plugin to create an executable jar with everything contained, right?

No, you don't need use Maven shade plugin, unless you want a uber JAR inside the executable ... JP infers all your dependencies from your pom.xml and copies them into libs folder, which is bundled with your app.

So what is the benefit of addtionally creating the xxx-runnable.jar?

JP generates xxx-runnable.jar to bundle it inside you app distribution package (Setup, MSI, DEB, RPM, DMG, ...) ... by itself it is not very useful.

Regards!!

fvarrui commented 1 year ago

One question: do you really need an uber jar?

armin-reichert commented 1 year ago

I though it would be useful to have a single executable jar for users that already have a JRE installed locally. What would be the alternative?

fvarrui commented 1 year ago

I though it would be useful to have a single executable jar for users that already have a JRE installed locally. What would be the alternative?

Ok, it's fine. But you should know that JP can build a distributable package without JRE.

armin-reichert commented 1 year ago

How does this package work? Does the user has to extract it or can he just download and double-click?

fvarrui commented 1 year ago

It would be an installer or a zipball. I plan to add an auto extract-and-run package.

fvarrui commented 1 year ago

Hi @armin-reichert! I've managed to build your app for Windows and Linux without problems ... only one thing: as you are using JavaFX, and JavaFX has system dependant libraries, I changed your pom.xml to deal with this situation and make easy to build your app for Windows and Linux.

pom.xml

<project xmlns="http://maven.apache.org/POM/4.0.0"
    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>de.amr.games.pacman</groupId>
    <artifactId>pacman-ui-fx-2d</artifactId>
    <version>1.0</version>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.target>17</maven.compiler.target>
        <maven.compiler.source>17</maven.compiler.source>       
        <exec.mainClass>de.amr.games.pacman.ui.fx.app.Main</exec.mainClass>
        <vs.java>11</vs.java>
        <vs.javafx>17.0.7</vs.javafx>
        <vs.maven-compiler-plugin>3.10.1</vs.maven-compiler-plugin>
        <vs.maven-jar-plugin>3.2.0</vs.maven-jar-plugin>
        <vs.maven-shade-plugin>3.4.1</vs.maven-shade-plugin>
        <vs.javafx-maven-plugin>0.0.8</vs.javafx-maven-plugin>
        <vs.tinylog>2.6.1</vs.tinylog>
    </properties>

    <profiles>
        <profile>
            <id>build-for-windows</id>
            <activation>
                <property>
                    <name>javafx.platform</name>
                    <value>win</value>
                </property>
            </activation>
            <build>
                <plugins>
                    <plugin>
                        <groupId>io.github.fvarrui</groupId>
                        <artifactId>javapackager</artifactId>
                        <version>1.7.2</version>
                        <configuration>
                            <generateInstaller>true</generateInstaller>
                            <winConfig>
                                <generateSetup>true</generateSetup>
                                <generateMsi>false</generateMsi>
                                <generateMsm>false</generateMsm>
                            </winConfig>
                        </configuration>
                        <executions>
                            <execution>
                                <id>windows-installer-with-jre</id>
                                <phase>package</phase>
                                <goals>
                                    <goal>package</goal>
                                </goals>
                                <configuration>
                                    <name>${project.name}-jre</name>
                                    <bundleJre>true</bundleJre>
                                </configuration>
                            </execution>
                            <execution>
                                <id>windows-installer-without-jre</id>
                                <phase>package</phase>
                                <goals>
                                    <goal>package</goal>
                                </goals>
                                <configuration>
                                    <name>${project.name}-no-jre</name>
                                    <bundleJre>false</bundleJre>
                                </configuration>
                            </execution>
                        </executions>
                    </plugin>
                </plugins>
            </build>
        </profile>
        <profile>
            <id>build-for-linux</id>
            <activation>
                <property>
                    <name>javafx.platform</name>
                    <value>linux</value>
                </property>
            </activation>
            <build>
                <plugins>
                    <plugin>
                        <groupId>io.github.fvarrui</groupId>
                        <artifactId>javapackager</artifactId>
                        <version>1.7.2</version>
                        <configuration>
                            <platform>linux</platform>
                            <createTarball>true</createTarball>
                            <jdkPath>C:\Users\fvarrui\jdk\linux\jdk-19.0.2+7</jdkPath>
                            <bundleJre>true</bundleJre>
                            <runnableJar>${project.build.directory}/${project.name}-${project.version}-shaded.jar</runnableJar>
                            <copyDependencies>false</copyDependencies>
                            <linuxConfig>
                                <generateDeb>true</generateDeb>
                                <generateRpm>true</generateRpm>
                                <generateAppImage>false</generateAppImage>
                            </linuxConfig>                      
                        </configuration>
                        <executions>
                            <execution>
                                <phase>package</phase>
                                <goals>
                                    <goal>package</goal>
                                </goals>
                            </execution>
                        </executions>
                    </plugin>
                </plugins>
            </build>
        </profile>
    </profiles>

    <dependencies>

        <dependency>
            <groupId>de.amr.games.pacman</groupId>
            <artifactId>pacman-core</artifactId>
            <version>1.0</version>
        </dependency>

        <dependency>
            <groupId>org.openjfx</groupId>
            <artifactId>javafx-controls</artifactId>
            <version>${vs.javafx}</version>
        </dependency>

        <dependency>
            <groupId>org.openjfx</groupId>
            <artifactId>javafx-media</artifactId>
            <version>${vs.javafx}</version>
        </dependency>

        <dependency>
            <groupId>org.tinylog</groupId>
            <artifactId>tinylog-api</artifactId>
            <version>${vs.tinylog}</version>
        </dependency>

        <dependency>
            <groupId>org.tinylog</groupId>
            <artifactId>tinylog-impl</artifactId>
            <version>${vs.tinylog}</version>
        </dependency>

    </dependencies>

    <build>
        <plugins>

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>${vs.maven-compiler-plugin}</version>
                <configuration>
                    <release>${vs.java}</release>
                </configuration>
            </plugin>

            <plugin>
                <groupId>org.openjfx</groupId>
                <artifactId>javafx-maven-plugin</artifactId>
                <version>${vs.javafx-maven-plugin}</version>
                <configuration>
                    <mainClass>${mainClass}</mainClass>
                </configuration>
            </plugin>

            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-shade-plugin</artifactId>
                <version>${vs.maven-shade-plugin}</version>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>shade</goal>
                        </goals>
                        <configuration>
                            <shadedArtifactAttached>true</shadedArtifactAttached>
                            <transformers>
                                <transformer
                                    implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                                    <mainClass>${exec.mainClass}</mainClass>
                                </transformer>
                            </transformers>
                        </configuration>
                    </execution>
                </executions>
            </plugin>

        </plugins>

    </build>

</project>

Now it's using Maven profiles, so you can change the build behaviour specifying a variable.

Build for Windows:

mvn package -Djavafx.platform=win

and for Linux:

mvn package -Djavafx.platform=linux

I hope it helps!

Anyway, I encourage you to use GitHub Actions to automate the building process for all platforms. It's a bit hard to config at first, but very useful.

armin-reichert commented 1 year ago

Dear Francisco,

Thank you so much for your help! I changed my build files as suggested. Of course, the GitHub workflow would be the best solution.

Regards Armin Reichert

fvarrui commented 1 year ago

Great! Happy to help 😃