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

compile OpenGL demos to native executable #36

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,4 @@
/.project
/*.iml
/dependency-reduced-pom.xml
.gradle
162 changes: 149 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,22 +1,158 @@
# lwjgl3-demos
Demo suite for LWJGL 3
# lwjgl3-opengl-demos + GraalVM native image

## Building
OpenGL Demos for LWJGL 3 compiled to native executable by GraalVM native-image utility.

./mvnw package

To override main class
All OpenGL demos in [src/org/lwjgl/demo/opengl](src/org/lwjgl/demo/opengl) are included in the build.

./mvnw package -Dclass=opengl.UniformArrayDemo
Gradle and Maven build scripts are provided for building the project,
which requires JDK 11+ or GraalVM 21+ (for native image).

## Running
## GraalVM pre-requisites

java -jar target/lwjgl3-demos.jar
The [GraalVM native-image](https://www.graalvm.org/reference-manual/native-image) page
shows how to set up GraalVM and its native-image utility for common platforms.
[Gluon](https://gluonhq.com/) also provides some setup
[details](https://docs.gluonhq.com/#_platforms) for GraalVM native-image creation.

on Mac OS you need to specify the `-XstartOnFirstThread` JVM argument, so the above becomes:
This project's Gradle build script uses the
[client-gradle-plugin](https://github.com/gluonhq/client-gradle-plugin)
from Gluon to build the native executable from Gradle with GraalVM.

java -XstartOnFirstThread -jar target/lwjgl3-demos.jar
The GraalVM native-image utility will use the configuration files in
`res/META-INF/native-image` folder to assist in the native-image generation.

To override main class
Gluon also provides the [client-maven-plugin](https://github.com/gluonhq/client-maven-plugin)
which is used in this project's Maven build script and works similarly to the above
client-gradle-plugin.

## Gradle build tasks

### Run in standard JVM

To build and run the OpenGL demos in standard JVM with Gradle, execute the `run` task:

gradlew run

By default, the [SimpleDrawElements](src/org/lwjgl/demo/opengl/SimpleDrawElements.java) demo is executed
by the above `run` task without parameter. To run a different OpenGL demo, e.g.
[WavefrontObjDemo](src/org/lwjgl/demo/opengl/assimp/WavefrontObjDemo.java), execute the `run` task
with that specific demo class as parameter:

gradlew run --args=opengl.assimp.WavefrontObjDemo

System properties can be passed on to the running demo with the -D parameter,
e.g. to print out some debug info in the console:

gradlew run --args=opengl.assimp.WavefrontObjDemo -Dorg.lwjgl.util.Debug=true

The above tasks can use any standard JDK 11+.

### Produce native executable

To generate native executable, GraalVM 21+ need be set up as mentioned in
*GraalVM pre-requisites* section above.

Once GraalVM is set up and available in the path, run the `nativeBuild` task:

gradlew nativeBuild

The `nativeBuild` task would take a while to compile the OpenGL demo source code and
link them with the LWJGL libraries into an executable file.
The resulting `lwjgl3-opengl-demos` file is (in Linux):

build/client/x86_64-linux/lwjgl3-opengl-demos

(or if building on a Windows machine:

build\client\x86_64-windows\lwjgl3-opengl-demos.exe

)

which can then be run directly with a demo class as parameter
(e.g. [DepthEdgeShaderDemo20](src/org/lwjgl/demo/opengl/fbo/DepthEdgeShaderDemo20.java)):

./build/client/x86_64-linux/lwjgl3-opengl-demos opengl.fbo.DepthEdgeShaderDemo20

System properties can be passed on to the running demo with the -D parameter,
e.g. to print out some debug info in the console:

./build/client/x86_64-linux/lwjgl3-opengl-demos opengl.fbo.DepthEdgeShaderDemo20 -Dorg.lwjgl.util.Debug=true

(or if building on a Windows machine:

build\client\x86_64-windows\lwjgl3-opengl-demos.exe opengl.fbo.DepthEdgeShaderDemo20
build\client\x86_64-windows\lwjgl3-opengl-demos.exe opengl.fbo.DepthEdgeShaderDemo20 -Dorg.lwjgl.util.Debug=true

)

## Maven build tasks

### Run in standard JVM

To build and run the OpenGL demos in standard JVM with Maven, execute the
`compile` then `exec:exec` tasks:

mvnw compile
mvnw exec:exec

By default, the [SimpleDrawElements](src/org/lwjgl/demo/opengl/SimpleDrawElements.java) demo is executed
by the above `exec:exec` task without parameter. To run a different OpenGL demo, e.g.
[WavefrontObjDemo](src/org/lwjgl/demo/opengl/assimp/WavefrontObjDemo.java), execute the `exec:exec` task
with that specific demo class as value of the property `class`:

mvnw exec:exec -Dclass=opengl.assimp.WavefrontObjDemo

System properties can be passed on to the running demo with the -Dsys.props parameter,
e.g. to print out some debug info in the console:

mvnw exec:exec -Dclass=opengl.assimp.WavefrontObjDemo -Dsys.props="-Dorg.lwjgl.util.Debug=true"

The above tasks can use any standard JDK 11+.

### Produce native executable

To generate native executable, GraalVM 21+ need be set up as mentioned in
*GraalVM pre-requisites* section above.

Once GraalVM is set up and available in the path, run the `client:build` task:

mvnw client:build

The `client:build` task would take a while to compile the OpenGL demo source code and
link them with the LWJGL libraries into an executable file.
The resulting `lwjgl3-opengl-demos` file is (in Linux):

target/client/x86_64-linux/lwjgl3-opengl-demos

(or if building on a Windows machine:

target\client\x86_64-windows\lwjgl3-opengl-demos.exe

)

which can then be run directly with a demo class as parameter
(e.g. [Demo33Ubo](src/org/lwjgl/demo/opengl/raytracing/Demo33Ubo.java)):

./target/client/x86_64-linux/lwjgl3-opengl-demos opengl.raytracing.Demo33Ubo

System properties can be passed on to the running demo with the -D parameter,
e.g. to print out some debug info in the console:

./target/client/x86_64-linux/lwjgl3-opengl-demos opengl.raytracing.Demo33Ubo -Dorg.lwjgl.util.Debug=true

(or if building on a Windows machine:

target\client\x86_64-windows\lwjgl3-opengl-demos.exe opengl.raytracing.Demo33Ubo
target\client\x86_64-windows\lwjgl3-opengl-demos.exe opengl.raytracing.Demo33Ubo -Dorg.lwjgl.util.Debug=true

)

## Compressed native executable

The resulting `lwjgl3-opengl-demos` executable file, whether produced by Gradle or Maven build script,
can be further reduced in size via compression using the [UPX](https://upx.github.io) utility,
as described [here](https://medium.com/graalvm/compressed-graalvm-native-images-4d233766a214).

For example, the resulting `lwjgl3-opengl-demos.exe` native application file produced in Windows
is normally 72MB in size, but is compressed to 24MB with the UPX command: `upx --best lwjgl3-opengl-demos.exe`

java -cp target/lwjgl3-demos.jar org.lwjgl.demo.opengl.UniformArrayDemo
137 changes: 137 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
plugins {
id 'application'
id 'com.gluonhq.client-gradle-plugin' version '0.1.36' //requires GraalVM 21+
}

wrapper {
gradleVersion = '6.8.3'
distributionType = Wrapper.DistributionType.ALL
}

group = 'org.lwjgl'
description = 'LWJGL3 OpenGL demos with native image by GraalVM'
//version = '0.0.1-SNAPSHOT'

ext {
lwjglVersion = '3.2.3'
jomlVersion = '1.10.1'
swtVersion = '4.6.1'
graalvmVersion = '21.0.0.2'

//LWJGL modules used: minimal OpenGL
lwjglModules = ['lwjgl', 'lwjgl-assimp', 'lwjgl-glfw', 'lwjgl-openal', 'lwjgl-opengl', 'lwjgl-stb']

mainClassName = 'org.lwjgl.demo.DemoLauncher'
}

repositories {
mavenCentral()
mavenLocal()
}

//detect the OS (assuming 64-bit, on Intel/AMD hardware)
private static String getCurrentPlatform() {
def currentOS = org.gradle.nativeplatform.platform.internal.DefaultNativePlatform.currentOperatingSystem;
if (currentOS.isWindows()) {
return 'windows'
} else if (currentOS.isLinux()) {
return 'linux'
} else if (currentOS.isMacOsX()) {
return 'macos'
}
return null
}

dependencies {
implementation "org.joml:joml:$jomlVersion"
//for compiling GraalVM substitution classes
compileOnly "org.graalvm.nativeimage:svm:$graalvmVersion"

def currentOS = getCurrentPlatform()

//OS-specific SWT library (64-bit Intel/AMD hardware only)
if (currentOS == 'windows')
implementation "org.eclipse.swt:org.eclipse.swt.win32.win32.x86_64:$swtVersion"
else if (currentOS == 'linux')
implementation "org.eclipse.swt:org.eclipse.swt.gtk.linux.x86_64:$swtVersion"
else if (currentOS == 'macos')
implementation "org.eclipse.swt:org.eclipse.swt.cocoa.macosx.x86_64:$swtVersion"

//get recommended dependency versions from the LWJGL BOM
implementation platform("org.lwjgl:lwjgl-bom:$lwjglVersion")

//add LWJGL modules and the current OS's natives to the compile and runtime classpaths
lwjglModules.each {
implementation "org.lwjgl:$it"
if (it != 'lwjgl-egl') { //lwjgl-egl has no native libraries
//use natives for 64-bit Intel/AMD platforms only
if (it == 'lwjgl-vulkan') {
if (currentOS == 'macos') {
//Vulkan natives exist for Mac OSX only
runtimeOnly "org.lwjgl:$it::natives-$currentOS"
}
} else {
runtimeOnly "org.lwjgl:$it::natives-$currentOS"
}
}
}
}

sourceSets {
main {
java {
srcDirs = ['src']
//include launcher & GraalVM substitution code
include 'org/lwjgl/demo/DemoLauncher.java', 'org/lwjgl/graalvm/*'
//restrict to opengl demo source code & utilities
include 'org/lwjgl/demo/opengl/**'
include 'org/lwjgl/demo/intro/*'
include 'org/lwjgl/demo/util/*'
}
resources {
srcDirs = ['res']
//include the GraalVM native-image configuration files
include 'META-INF/**'
//restrict to opengl demo resources only
include 'org/lwjgl/demo/*'
include 'org/lwjgl/demo/opengl/**'
}
}
}

application {
mainClass = project.mainClassName
applicationName = project.name //name of the resulting native executable
}

compileJava {
options.release = 11 //use JDK11+ for compiling & running
options.encoding = 'UTF-8'
}

jar.archiveBaseName = 'lwjgl3-opengl-demos'

run {
//default demo is opengl.SimpleDrawElements
//(the package "org.lwjgl.demo." is prepended automatically)
args 'opengl.SimpleDrawElements'

//get system properties specified from the command line (for debugging, etc.)
//and pass them on to the running application's JVM
systemProperties = System.getProperties()

//use the following jvmArgs for as many different run scenarios as possible,
//and for all the code-execution paths as much as possible,
//to generate (or merge with) the GraalVM native-image configuration files
//in the res/META-INF/native-image directory.
//This directory is read by GraalVM during the native-image build.

//jvmArgs = ["-agentlib:native-image-agent=config-merge-dir=res/META-INF/native-image"]
}

gluonClient {
compilerArgs = [
'--initialize-at-run-time=org.lwjgl',
'--report-unsupported-elements-at-runtime',
]
}
Binary file added gradle/wrapper/gradle-wrapper.jar
Binary file not shown.
5 changes: 5 additions & 0 deletions gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.8.3-all.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
Loading