Skip to content

Commit 2844114

Browse files
author
alferio
committed
feat(dist): appimage
• Added AppImage packaging for Linux and wired it into GitHub release CI. - lwjgl3/build.gradle - added :lwjgl3:bundleLinuxAppImage - it builds from the existing bundleLinuxDir output, creates an AppDir, writes: - AppRun - octodraw.desktop - octodraw.png - stages the Linux bundle under usr/lib/octodraw - uses APPIMAGETOOL env var if provided, otherwise appimagetool - outputs dist/octodraw-dist-<version>-linux.AppImage - .github/workflows/release.yml - Linux job now downloads appimagetool - Linux build now runs: - :lwjgl3:bundleLinuxTar - :lwjgl3:bundleLinuxAppImage - :lwjgl3:jarLinux - :core:pluginApiJar - uploaded Linux artifacts now include dist/*.AppImage - release upload now includes *.AppImage What this does not change: - Android - Windows - portable desktop tar build - webcomponent build Use: - local: - APPIMAGETOOL=/path/to/appimagetool ./gradlew :lwjgl3:bundleLinuxAppImage -PreleaseNumber=<version> - CI: - handled automatically by the updated release workflow
1 parent d9e2b58 commit 2844114

2 files changed

Lines changed: 115 additions & 2 deletions

File tree

.github/workflows/release.yml

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,13 +27,22 @@ jobs:
2727
with:
2828
distribution: "temurin"
2929
java-version: "21"
30+
- name: Fetch appimagetool
31+
run: |
32+
set -euo pipefail
33+
curl -fsSL -o "$RUNNER_TEMP/appimagetool.AppImage" \
34+
https://github.com/AppImage/AppImageKit/releases/download/continuous/appimagetool-x86_64.AppImage
35+
chmod +x "$RUNNER_TEMP/appimagetool.AppImage"
3036
- name: Build Linux bundle + JVM jars
31-
run: ./gradlew :lwjgl3:bundleLinuxTar :lwjgl3:jarLinux :core:pluginApiJar -PreleaseNumber="${{ inputs.tag }}"
37+
env:
38+
APPIMAGETOOL: ${{ runner.temp }}/appimagetool.AppImage
39+
run: ./gradlew :lwjgl3:bundleLinuxTar :lwjgl3:bundleLinuxAppImage :lwjgl3:jarLinux :core:pluginApiJar -PreleaseNumber="${{ inputs.tag }}"
3240
- uses: actions/upload-artifact@v4
3341
with:
3442
name: octodraw-linux
3543
path: |
3644
dist/*.tar.gz
45+
dist/*.AppImage
3746
lwjgl3/build/libs/*.jar
3847
core/build/libs/octodraw-plugin*.jar
3948
@@ -369,7 +378,7 @@ jobs:
369378
else
370379
gh release edit "$TAG" --draft="$DRAFT" --prerelease="$PRERELEASE"
371380
fi
372-
files=$(find artifacts -type f \( -name "*.zip" -o -name "*.tar.gz" -o -name "*.snap" -o -name "*.jar" -o -name "*.msi" -o -name "*.msix" -o -name "*.apk" -o -name "*.aab" \))
381+
files=$(find artifacts -type f \( -name "*.zip" -o -name "*.tar.gz" -o -name "*.AppImage" -o -name "*.snap" -o -name "*.jar" -o -name "*.msi" -o -name "*.msix" -o -name "*.apk" -o -name "*.aab" \))
373382
if [ -z "$files" ]; then
374383
echo "No release artifacts found."
375384
exit 1

lwjgl3/build.gradle

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -789,6 +789,110 @@ configureBundleTask("bundleWin", "win", tasks.named("fetchJdkWin"), file("$jdkCa
789789
configureBundleTask("bundleMacArm64", "mac", tasks.named("fetchJdkMacArm64"), file("$jdkCacheDir/mac-arm64"), true, false)
790790
configureBundleTarTask("bundleLinuxTar", "linux", tasks.named("fetchJdkLinux"), file("$jdkCacheDir/linux-x64"), true)
791791
configureBundleTarTask("bundleMacArm64Tar", "mac", tasks.named("fetchJdkMacArm64"), file("$jdkCacheDir/mac-arm64"), true)
792+
tasks.register("bundleLinuxAppImage") {
793+
dependsOn "bundleLinuxDir"
794+
outputs.file rootProject.file("dist/octodraw-dist-${bundleVersion}-linux.AppImage")
795+
doLast {
796+
if (!os.contains("linux")) {
797+
throw new GradleException("AppImage packaging is only supported on Linux hosts.")
798+
}
799+
def appImageToolPath = System.getenv("APPIMAGETOOL") ?: "appimagetool"
800+
def probe = null
801+
try {
802+
probe = new ProcessBuilder(appImageToolPath, "--version")
803+
.directory(project.projectDir)
804+
.redirectErrorStream(true)
805+
.start()
806+
probe.inputStream.text
807+
} catch (IOException ignored) {
808+
probe = null
809+
}
810+
if (probe == null || probe.waitFor() != 0) {
811+
throw new GradleException("appimagetool not found. Install appimagetool or set APPIMAGETOOL.")
812+
}
813+
814+
def bundleDir = rootProject.file("dist/octodraw-dist-${bundleVersion}-linux")
815+
if (!bundleDir.exists()) {
816+
throw new GradleException("Linux bundle directory not found: ${bundleDir}")
817+
}
818+
819+
def appDir = file("$buildDir/appimage/Octodraw.AppDir")
820+
def outFile = rootProject.file("dist/octodraw-dist-${bundleVersion}-linux.AppImage")
821+
project.delete(appDir)
822+
project.delete(outFile)
823+
824+
def payloadDir = new File(appDir, "usr/lib/octodraw")
825+
def binDir = new File(appDir, "usr/bin")
826+
def applicationsDir = new File(appDir, "usr/share/applications")
827+
def iconDir = new File(appDir, "usr/share/icons/hicolor/512x512/apps")
828+
[payloadDir, binDir, applicationsDir, iconDir].each { it.mkdirs() }
829+
830+
project.copy {
831+
from(bundleDir)
832+
into(payloadDir)
833+
}
834+
835+
def launcher = new File(binDir, "octodraw")
836+
launcher.text = """#!/bin/sh
837+
set -eu
838+
HERE="\$(CDPATH= cd -- "\$(dirname -- "\$0")" && pwd)"
839+
APPDIR="\$(CDPATH= cd -- "\$HERE/../.." && pwd)"
840+
exec "\$APPDIR/usr/lib/octodraw/octodraw-jre" "\$@"
841+
"""
842+
launcher.setExecutable(true, false)
843+
844+
def appRun = new File(appDir, "AppRun")
845+
appRun.text = """#!/bin/sh
846+
set -eu
847+
HERE="\$(CDPATH= cd -- "\$(dirname -- "\$0")" && pwd)"
848+
exec "\$HERE/usr/bin/octodraw" "\$@"
849+
"""
850+
appRun.setExecutable(true, false)
851+
852+
def desktopEntry = """[Desktop Entry]
853+
Name=Octodraw
854+
Comment=3D drafting and modeling tool
855+
Exec=octodraw %U
856+
Icon=octodraw
857+
Terminal=false
858+
Type=Application
859+
Categories=Graphics;3DGraphics;Engineering;
860+
MimeType=application/octet-stream;
861+
StartupWMClass=Octodraw
862+
"""
863+
new File(appDir, "octodraw.desktop").text = desktopEntry
864+
new File(applicationsDir, "octodraw.desktop").text = desktopEntry
865+
866+
def iconSource = rootProject.file("assets/appicon_512x512.png")
867+
if (!iconSource.exists()) {
868+
iconSource = rootProject.file("assets/appicon.png")
869+
}
870+
project.copy {
871+
from(iconSource)
872+
into(appDir)
873+
rename { "octodraw.png" }
874+
}
875+
project.copy {
876+
from(iconSource)
877+
into(iconDir)
878+
rename { "octodraw.png" }
879+
}
880+
881+
ensureUnixRuntimeExecutables(payloadDir)
882+
883+
def pack = new ProcessBuilder(appImageToolPath, appDir.absolutePath, outFile.absolutePath)
884+
.directory(rootProject.projectDir)
885+
.inheritIO()
886+
pack.environment().put("ARCH", "x86_64")
887+
if (appImageToolPath.endsWith(".AppImage")) {
888+
pack.environment().put("APPIMAGE_EXTRACT_AND_RUN", "1")
889+
}
890+
def process = pack.start()
891+
if (process.waitFor() != 0) {
892+
throw new GradleException("appimagetool failed while building ${outFile.name}.")
893+
}
894+
}
895+
}
792896

793897
tasks.register("bundleLinuxSnap") {
794898
outputs.file rootProject.file("dist/octodraw-dist-${bundleVersion}-linux.snap")

0 commit comments

Comments
 (0)