Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JDKPackager doesn't work with latest javafx (any alternatives?) #1667

Closed
jbwheatley opened this issue Jan 9, 2025 · 1 comment
Closed

JDKPackager doesn't work with latest javafx (any alternatives?) #1667

jbwheatley opened this issue Jan 9, 2025 · 1 comment

Comments

@jbwheatley
Copy link

jbwheatley commented Jan 9, 2025

Bit of a shot in the dark, but I have a javafx application for which i'm hoping to create cross-platform launchers. The JDKPackager plugin relies on the existence of ant-javafx.jar which as far as I can see has been dropped by openjfx.

The error that is get is unsurprisingly

[error] (JdkPackager / antBuildDefn) Please set key `JDKPackager / antPackagerTasks` to `ant-javafx.jar` path, which should be found in the `lib` directory of the Oracle JDK 8 installation. For example (Windows):
[error] JDKPackager / antPackagerTasks := Some(file("C:\\Program Files\\Java\\jdk1.8.0_45\\lib\\ant-javafx.jar"))

I'm not so much asking for sbt-native-packager to be updated to support recent versions of javafx, rather would like to know if there are any good alternatives for bundling my app using sbt.

For reference below is my build.sbt, I'm running

  • java 21
  • sbt-native-packager 1.11.0
  • macos arm64
  • sbt 1.10.2

As an aside everything works fine if I create an bash exe with JavaAppPackaging instead, but that doesn't fit my use case.

scalaVersion := "2.13.15"

libraryDependencies ++= Seq(
  "org.scalafx" %% "scalafx" % "22.0.0-R33", 
  "io.circe" %% "circe-core"   % "0.14.1",
  "io.circe" %% "circe-parser" % "0.14.1"
)
libraryDependencies ++= javaFXModules

enablePlugins(JlinkPlugin)
enablePlugins(JDKPackagerPlugin)

// Add JavaFX dependencies
lazy val javaFXModules = {
  // Determine OS version of JavaFX binaries
  lazy val osName = (System.getProperty("os.name"), System.getProperty("os.arch")) match {
    case (n, _) if n.startsWith("Linux")       => "linux"
    case (n, "aarch64") if n.startsWith("Mac") => "mac-aarch64"
    case (n, _) if n.startsWith("Mac")         => "mac"
    case (n, _) if n.startsWith("Windows")     => "win"
    case _                                     => throw new Exception("Unknown platform!")
  }
  Seq("base", "graphics", "media", "controls").map(m => "org.openjfx" % s"javafx-$m" % "22" classifier osName)
}


fork := true

Compile / mainClass := Some("preflop.ranger.PreflopRanger")

jdkPackagerType := "installer"

jdkPackagerToolkit := JavaFXToolkit

jdkPackagerProperties := Map("app.name" -> name.value, "app.version" -> version.value)

jdkPackagerAppArgs := Seq(maintainer.value, packageSummary.value, packageDescription.value)
@jbwheatley
Copy link
Author

jbwheatley commented Jan 15, 2025

I've figured out an alternative for myself using sbt-assembly and jpackage.

I needed to alter the merge strategy for sbt-assembly as follows to work with javafx (NB i am building on mac-aarch64, other OS will come with their own baggage):

assembly / mainClass := Some("my.app.Main")

assembly / assemblyMergeStrategy := {
  case x if Assembly.isConfigFile(x) =>
    MergeStrategy.concat
  case PathList(ps @ _*) if Assembly.isReadme(ps.last) || Assembly.isLicenseFile(ps.last) =>
    MergeStrategy.rename
  case PathList("META-INF", xs @ _*) =>
    (xs map { _.toLowerCase }) match {
      case ("manifest.mf" :: Nil) | ("index.list" :: Nil) | ("dependencies" :: Nil) =>
        MergeStrategy.discard
      case ps @ (x :: xs) if ps.last.endsWith(".sf") || ps.last.endsWith(".dsa") =>
        MergeStrategy.discard
      case "plexus" :: xs =>
        MergeStrategy.discard
      case "services" :: xs =>
        MergeStrategy.filterDistinctLines
      case ("spring.schemas" :: Nil) | ("spring.handlers" :: Nil) =>
        MergeStrategy.filterDistinctLines
      case ("substrate" :: xs) => MergeStrategy.discard //Added to default here
      case _                   => MergeStrategy.deduplicate
    }
  case "module-info.class" => MergeStrategy.concat //Added to default here
  case _                   => MergeStrategy.deduplicate
}

then run sbt assembly, followed by

jpackage --input target/scala-2.13 \
  --name MyApp \  
  --main-jar my-app-assembly-0.0.1.jar \
  --type dmg 

this quick tutorial for jpackage was helpful https://www.baeldung.com/java14-jpackage

Will close this issue, but hopefully the other 2 users of scalafx might find this useful 😆

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant