saalfeldlab / paintera

GNU General Public License v2.0
100 stars 17 forks source link

Create standalone app #253

Closed hanslovsky closed 2 months ago

hanslovsky commented 5 years ago

The installation process is hard for people who are not familiar with command line and conda. To make Paintera more accessible, we should try to create standalone packages that ideally ships Java as well.

Self contained packaging through the javapackager might be a good way to do that. I tried so far, with mixed success. For all cases, add these lines to pom.xml inside the <prpofiles></profiles> tag:

<profile>
    <id>with-slf4j-simple</id>
    <dependencies>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-simple</artifactId>
            <version>${slf4j-simple.version}</version>
            <scope>compile</scope>
        </dependency>
    </dependencies>
</profile>

javafx-maven-plugin

Add these lines to pom.xml:

<build>
    <plugins>
        <plugin>
            <groupId>com.zenjava</groupId>
            <artifactId>javafx-maven-plugin</artifactId>
            <version>8.8.3</version>
            <configuration>
                <mainClass>${main-class}</mainClass>
            </configuration>
        </plugin>
    </plugins>
</build>

Then run

mvn -Pwith-slf4j-simple jfx:native
target/jfx/native/Paintera/Paintera

Not sure if this package is still maintained (last commit in March of 2018) and is a package with the same artifactId but I do not know if and how they are related.

Build uber jar and then use javapackager

Add these lines to pom.xml inside the <profiles></profiles> tag:

<profile>
    <id>uber</id>
    <build>
        <plugins>
            <!-- Maven Assembly Plugin -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-assembly-plugin</artifactId>
                <version>2.4.1</version>
                <configuration>
                    <!-- get all project dependencies -->
                    <descriptorRefs>
                        <descriptorRef>jar-with-dependencies</descriptorRef>
                    </descriptorRefs>
                    <!-- MainClass in mainfest make a executable jar -->
                    <archive>
                        <manifest>
                            <mainClass>${main-class}</mainClass>
                        </manifest>
                    </archive>

                </configuration>
                <executions>
                    <execution>
                        <id>make-assembly</id>
                        <!-- bind to the packaging phase -->
                        <phase>package</phase>
                        <goals>
                            <goal>single</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</profile>

Then run

mvn -Pwith-slf4j-simple,uber clean package
java -jar target/paintera-0.16.1-SNAPSHOT-jar-with-dependencies.jar

If those issue can be resolved, then package it with

javapackager  \
    -deploy \
    -name Paintera \
    -native \
    -outdir out \
    -outfile paintera \
    -srcdir target \
    -srcfiles paintera-0.16.1-SNAPSHOT-jar-with-dependencies.jar  \
    -appclass org.janelia.saalfeldlab.paintera.Paintera

When packaged natively, there is also a weird delay also observed with javafx-maven-plugin.

Build shaded jar and then use javapackager

Add these lines to pom.xml inside the <profiles></profiles> tag:

<profile>
    <id>shaded</id>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-shade-plugin</artifactId>
                <version>3.1.0</version>
                <configuration>
                    <filters>
                        <filter>
                            <artifact>*:*</artifact>
                            <excludes>
                                <exclude>META-INF/*.SF</exclude>
                                <exclude>META-INF/*.DSA</exclude>
                                <exclude>META-INF/*.RSA</exclude>
                            </excludes>
                        </filter>
                    </filters>
                    <artifactSet>
                        <excludes>
                            <exclude>*hadoop*</exclude>
                            <exclude>*spark*</exclude>
                            <exclude>*scala*</exclude>
                        </excludes>
                    </artifactSet>
                    <shadedArtifactId>${project.artifactId}</shadedArtifactId>
                    <shadedArtifactAttached>true</shadedArtifactAttached>
                    <!-- Do not minimize for now to speed up packaging. -->
                    <!-- <minimzeJar>true</minimzeJar> -->

                    <relocations>
                        <relocation>
                            <pattern>org.apache.commons.compress</pattern>
                            <shadedPattern>org.janelia.saalfeldlab.org.apache.commons.compress</shadedPattern>
                        </relocation>
                    </relocations>
                </configuration>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>shade</goal>
                        </goals>
                        <configuration>
                            <transformers>
                                <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                                    <mainClass>${main-class}</mainClass>
                                </transformer>
                            </transformers>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</profile>

Then run

mvn -Pwith-slf4j-simple,shaded clean package
java -jar target/paintera-0.16.1-SNAPSHOT-shaded.jar

General Issues:

hanslovsky commented 5 years ago

Relevant for #251

hanslovsky commented 5 years ago

Possibly related: https://bugs.openjdk.java.net/browse/JDK-8138944

hanslovsky commented 5 years ago

Also related (and look who created that post :smile:): https://stackoverflow.com/questions/30809330/how-can-dynamic-jvm-command-line-flags-be-passed-to-a-self-contained-javafx-appl

hanslovsky commented 5 years ago

Also have a look at jpackage: https://www.infoq.com/news/2019/03/jep-343-jpackage/ https://jdk.java.net/jpackage/

Probably(?) not compatible with Java8.

constantinpape commented 4 years ago

I don't know if this has been discussed elsewhere, but would it be possible to ship with Fiji? I.e. adding it via a paintera update site. This would be the easiest way to deploy it to users.

hanslovsky commented 4 years ago

Unfortunately, that is not possible because Fiji uses swing/awt and Paintera uses the JavaFX UI framework. Interop is not great between those

constantinpape commented 4 years ago

Unfortunately, that is not possible because Fiji uses swing/awt and Paintera uses the JavaFX UI framework. Interop is not great between those

Thanks for the clarification. In that case, having a standalone app would indeed be a very good solution. Once you have a first version, I am happy to test.

hanslovsky commented 4 years ago

I think the easiest way for ward is to create tar/zip files with (or without) the required Java Runtime and all Jars and shell (Linux/macOS) and batch (Windows) scripts that execute that, with installers for macOS/Windows and deb (or other packages) for Linux. I will not be at Janelia much longer, so I will not be able to address this but this may be a good community contribution because it does not require any (deep) knowledge about Java programming.

Also, cc @igorpisarev and @axtimwalde

cmhulbert commented 1 year ago

The most recent Paintera release now has some platform specific standalone installers for MacOS, Windows, and Ubuntu. It's not currently a replacement for the conda release process, but it's useful for installing a version that tracks against the master branch. It uses the jtoolprovider-plugin for maven, which facilitates using jpackage to generate the standalone JRE.

It's triggered on pushes to master, through github actions, so should always track with the most recent master commit.

The README has some more information about it, including some known limitations at the moment.

Releases are here: https://github.com/saalfeldlab/paintera/releases

tinevez commented 1 year ago

I tested it this morning on a Mac M2. And it works! Great job!.

axtimwalde commented 1 year ago

This is surprising because we do not build releases for M1/2...

cmhulbert commented 1 year ago

To be clear, it can be done, I have tested locally on an M1 and it works well. But the github automatic releases are not built on M1/M2 Macs. It's something I hope to set up soon, as we refine this release process

tinevez commented 1 year ago

Well, to me it looks like you are very good at it for something you don't do:

Screenshot 2023-06-08 at 07 14 19
cmhulbert commented 2 months ago

Currently, the Github Actions based release is the formal release, so I will close this as done. There are still some questions about publishing the releases to native store, and how to automate updates, but I think those are best tracked in dedicated issues.