Search code examples
downloadfatjarjavaexec-gradle-plugin

Making a Java Runnable JAR that downloads platform-specific libraries


I have a small Java (Kotlin) app. It requires some big libraries like openblas and opencv. I'd like to package it up in a drag-and-drop executable JAR file, but when I build a fatJar, it includes the libraries for all possible platforms, and ends up being over 600MB.

That is way too huge! I'd much prefer a small app that downloads the appropriate libraries for the user's platform when you run it for the first time. Is this a standard? I can't assume the end user will have Gradle or Maven installed, just that they have a JRE installed.

I tried what I think is the latest fatJar for build.gradle.kts:

val fatJar = task("fatJar", type = Jar::class) {
    archiveBaseName.set("${project.name}-fat")
    manifest {
        attributes["Implementation-Title"] = project.name
        attributes["Implementation-Version"] = project.version
        attributes["Main-Class"] = application.mainClass
    }
    duplicatesStrategy = DuplicatesStrategy.EXCLUDE
    from(configurations.runtimeClasspath.get().map { if (it.isDirectory) it else zipTree(it) })
    with(tasks["jar"] as CopySpec)
}

And then checked which libraries were in the JAR file: it was behaving correctly and not duplicating Kotlin versions or anything else bad.


Solution

  • I believe https://github.com/JetBrains/compose-multiplatform/blob/master/tutorials/Native_distributions_and_local_execution/README.md#basic-usage is what I'm looking for. I haven't got it working yet, but it sounds like the feature set.