From 4cfa7ceaecfb27ec00f828aced21e4238b7e43a0 Mon Sep 17 00:00:00 2001 From: Anton Afanasyeu Date: Thu, 25 Jun 2026 18:10:39 +0200 Subject: [PATCH] =?UTF-8?q?session-studio:=20runnable=20jar=20=E2=80=94=20?= =?UTF-8?q?shadow=20fat=20jar=20+=20module-path=20launcher=20+=20wrapper?= =?UTF-8?q?=20script?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Launcher.java: non-Application Main-Class entry point (bypasses JVM Application subclass check) - build.gradle: shadow plugin 8.1.1 for fat jar; startScripts patched with --module-path \$APP_HOME/lib + --add-modules; generateWrapper task writes project-root ./ac-session-studio script - ac-session-studio: generated launcher wrapper (./ac-session-studio to run) java -jar build/libs/ac-session-studio.jar still requires --module-path; use ./ac-session-studio instead Co-authored-by: Cursor --- ac-session-studio | 4 ++ build.gradle | 49 +++++++++++++++++++ .../com/foxx/androidcast/studio/Launcher.java | 19 +++++++ 3 files changed, 72 insertions(+) create mode 100755 ac-session-studio create mode 100644 src/main/java/com/foxx/androidcast/studio/Launcher.java diff --git a/ac-session-studio b/ac-session-studio new file mode 100755 index 0000000..b9f6629 --- /dev/null +++ b/ac-session-studio @@ -0,0 +1,4 @@ +#!/bin/sh +# Auto-generated launcher wrapper — re-run ./gradlew generateWrapper to refresh +SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)" +exec "${SCRIPT_DIR}/build/install/ac-session-studio/bin/ac-session-studio" "$@" diff --git a/build.gradle b/build.gradle index a99079b..0fd15e6 100644 --- a/build.gradle +++ b/build.gradle @@ -1,6 +1,7 @@ plugins { id 'application' id 'org.openjfx.javafxplugin' version '0.1.0' + id 'com.github.johnrengelman.shadow' version '8.1.1' } repositories { @@ -22,6 +23,54 @@ application { mainClass = 'com.foxx.androidcast.studio.SessionStudioApp' } +// Patch generated Unix start script to add --module-path $APP_HOME/lib. +tasks.named('startScripts').configure { + doLast { + def script = unixScript + // Replace the -classpath line to also include --module-path before it + script.text = script.text.replace( + ' -classpath "$CLASSPATH" \\', + ' --module-path "$APP_HOME/lib" \\\n --add-modules javafx.controls,javafx.graphics,javafx.base \\\n -classpath "$CLASSPATH" \\' + ) + } +} + dependencies { implementation 'org.json:json:20240303' } + +jar { + manifest { + attributes 'Main-Class': 'com.foxx.androidcast.studio.Launcher' + } +} + +shadowJar { + archiveBaseName = 'ac-session-studio' + archiveClassifier = '' + archiveVersion = '' + manifest { + attributes 'Main-Class': 'com.foxx.androidcast.studio.Launcher' + } + mergeServiceFiles() +} + +// After installDist, generate a convenience wrapper at the project root +tasks.register('generateWrapper') { + dependsOn installDist + doLast { + def wrapper = file("${rootProject.projectDir}/ac-session-studio") + def distBin = "${buildDir}/install/ac-session-studio/bin/ac-session-studio" + wrapper.text = """\ +#!/bin/sh +# Auto-generated launcher wrapper — re-run ./gradlew generateWrapper to refresh +SCRIPT_DIR="\$(cd "\$(dirname "\$0")" && pwd)" +exec "\${SCRIPT_DIR}/build/install/ac-session-studio/bin/ac-session-studio" "\$@" +""" + wrapper.setExecutable(true) + println "Wrapper written: ${wrapper}" + } +} + +// Also attach generateWrapper to the standard build lifecycle +build.dependsOn generateWrapper diff --git a/src/main/java/com/foxx/androidcast/studio/Launcher.java b/src/main/java/com/foxx/androidcast/studio/Launcher.java new file mode 100644 index 0000000..1093ac7 --- /dev/null +++ b/src/main/java/com/foxx/androidcast/studio/Launcher.java @@ -0,0 +1,19 @@ +package com.foxx.androidcast.studio; + +/** + * Fat-jar entry point that does NOT extend javafx.application.Application. + * + * On Java 9+ the JVM checks whether Main-Class is an Application subclass and + * refuses to launch it from a classpath jar when JavaFX modules are not on the + * explicit module path. Delegating through this plain class bypasses that check. + * + * For direct execution use the generated wrapper script instead of java -jar: + * ./build/install/ac-session-studio/bin/ac-session-studio + * or the project-root wrapper: + * ./ac-session-studio + */ +public final class Launcher { + public static void main(String[] args) { + SessionStudioApp.main(args); + } +}