javagradlelwjgl

How can I remove (or separate) LWJGL modules from my own?


I'm trying to run a program with LWJGL 3.3.1 with Gradle 8.0.2. I'm using IntelliJ 2022.2.1 but I run Gradle with a PowerShell instance. The compiling works fine but when I tell it to run the app, it tells me that my module contains a LWJGL package, which in turn exports to mine.

After searching for a while, I didn't find anything so I didn't try much. Also, after looking at the generated zip file, my jar is in the same directory as the LWJGL jars. Here's my build.gradle and module-info.java


build.gradle

plugins {
    id 'java'
    id 'application'
    id 'org.beryx.jlink' version '2.25.0'
}

group 'ch.l1chorpe'
version '1.0.0'

project.ext.lwjglVersion = "3.3.1"
project.ext.lwjglNatives = "natives-windows"


repositories {
    mavenCentral()
}

dependencies {
    implementation platform("org.lwjgl:lwjgl-bom:$lwjglVersion")

    implementation "org.lwjgl:lwjgl"
    implementation "org.lwjgl:lwjgl-assimp"
    implementation "org.lwjgl:lwjgl-cuda"
    implementation "org.lwjgl:lwjgl-glfw"
    implementation "org.lwjgl:lwjgl-opencl"
    implementation "org.lwjgl:lwjgl-opengl"
    implementation "org.lwjgl:lwjgl-stb"
    runtimeOnly "org.lwjgl:lwjgl::$lwjglNatives"
    runtimeOnly "org.lwjgl:lwjgl-assimp::$lwjglNatives"
    runtimeOnly "org.lwjgl:lwjgl-glfw::$lwjglNatives"
    runtimeOnly "org.lwjgl:lwjgl-opengl::$lwjglNatives"
    runtimeOnly "org.lwjgl:lwjgl-stb::$lwjglNatives"
}

jar {
    duplicatesStrategy(DuplicatesStrategy.EXCLUDE)
    manifest {
        attributes 'Main-Class': 'ch.l1chorpe.fractalscl.Main'
    } from { configurations.runtimeClasspath.collect { it.isDirectory() ? it : zipTree(it) } }
}

sourceCompatibility = '19'
targetCompatibility = '19'

application {
    mainModule = 'ch.l1chorpe.fractalscl'
    mainClass = 'ch.l1chorpe.fractalscl.Main'
}

jlink {
    imageZip = project.file("${buildDir}/distributions/FractalsCL-${version}.zip")
    options = ['--strip-debug', '--compress', '2', '--no-header-files', '--no-man-pages']
    launcher {
        name = 'app'
    }
}

jlinkZip {
    group = 'distribution'
}

module-info.java

module ch.l1chorpe.fractalscl {
    requires org.lwjgl;
    requires org.lwjgl.glfw;
    requires org.lwjgl.opengl;

    exports ch.l1chorpe.fractalscl;
}

Solution

  • The problem is that you are creating an "uber"-jar with your current jar block. You can verify this by inspecting the single jar file produced by the Gradle build in the build/libs folder.

    The Java Platform Module System (JPMS) requires separate jar files for separate modules, because every jar/module will provide its own module-info.class at the root of the classpath, which cannot simply be ignored/discarded (which is what you are doing with the duplicatesStrategy(DuplicatesStrategy.EXCLUDE)).

    Since you are building an uber-jar which merges all your own classes/resources and those of the dependencies, this won't work with the Java Platform Module System anymore.

    You could avoid building an "uber"-jar by modifying the jar block to:

    jar {
        manifest {
            attributes 'Main-Class': 'ch.l1chorpe.fractalscl.Main'
        }
    }
    

    and, since this is effectively now only specifying the main class, and you also already specify the main class in application.mainClass, you can completely remove the jar block.