MacOS support overhaul, Apple M1 and breaking changes

I think I don’t quite understand what’s going on and, since I don’t have a mac, hopefully somebody could kindly explain it to me. So let’s see if I got this straight: if I understand it correctly GLFW must run on the main thread, and because AWT also runs on the main thread, both can’t run at the same time. If that is the problem, wouldn’t it be possible to terminate the AWT thread (after closing the settings dialog) before starting GLFW? If no, why not?

Anyway, IMHO a game engine made for programmers shouldn’t show a settings dialog as default behavior.

2 Likes

Not fan of the settings dialog. I always turn it off… After I have build something that allows users (and me) to change these settings with ease and is better integrated to whatever I’m building.

For those jME tests, or demos, whatever we call those, it is important. Starting to learn jME, starting to make an app. I would say it is a valuable thing to have.

3 Likes

Can I recommend opening an issue on the glfw github repo? There currently is not one open at the moment (at least not that I can find). Perhaps that issue can link to the patch gdx-lwjgl3-glfw-awt-macos extensions to add support for mixing GLFW and AWT on macOS by badlogic · Pull Request #6772 · libgdx/libgdx · GitHub.

I’m surprised the author of the patch has not opened a PR, but perhaps he can get tagged on the issue.

I have no way to test this problem currently, so perhaps someone who does can open the issue with glfw and provide the relevant feedback to them.

They are interested in macos support, I think that is very apparent with the work they are doing right now to support the new M1 chips, so perhaps this can be included in that work.

Thanks,
Trevor

3 Likes

Just In: LWJGL 3 just got a modified macos lwjgl binding for glfw to allow glfw to run on any thread: feat(glfw): add libglfw_async.dylib · LWJGL/lwjgl3@72fc20d · GitHub

14 Likes

Woah, I never thought I could see this. This is great news!

1 Like

That is great news! That has been annoying to deal with.

Awesome!

10000x this.
The settingsdialog should be a separate application.

3 Likes

This is great news and well timed at that. I just switched to a M1 Mac and can’t get any of my JME projects to work as they are all designed to run off the main thread. I’ve tried checking out the master branch of https://github.com/LWJGL/lwjgl3 and executing:

./gradlew build publishToMavenLocal

Which succeeds, then going to the master branch of https://github.com/jMonkeyEngine/jmonkeyengine.git

editing common.gradle’s lwjgl3Version properties like so:

lwjgl3Version = '3.3.1-SNAPSHOT' // used in both the jme3-lwjgl3 and jme3-vr build scripts

and the running the build, but it fails with

:jme3-lwjgl3:test: Could not find org.lwjgl:lwjgl:3.3.1-SNAPSHOT.

Has anyone gotten this updated lwjgl 3 to work on a Mac M1?

1 Like

I believe @RiccardoBlb had JME apps working on an Apple M1.

Unless you’ve built LWJGL locally, you probably want lwjgl3Version = '3.3.0'.

to run lwjgl/jme off the main thread you need to use async-glfw https://github.com/LWJGL/lwjgl3/commit/72fc20d9306c98ff4741ec65a2d0fe443fae87b2
it is available in 3.3.1-SNAPSHOT, just add snapshot-repo in your build.gradle

    repositories {
        mavenCentral()
        maven {
            url "https://oss.sonatype.org/content/repositories/snapshots/"
        }
    }
1 Like

So this is my minimal build.gradle file. still failing to resolve the lwjgl3 artifact.

Can someone explain how the binding between org.jmonkeyengine:jme3-lwjgl3 and org.lwjgl:lwjgl3 works? or just post a working minimal build.gradle file for a Mac M1 hello world off the main thread?

repositories {
    mavenLocal()
    mavenCentral()
    maven {url "https://oss.sonatype.org/content/repositories/snapshots/"}

}

dependencies {
    implementation "org.jmonkeyengine:jme3-core:3.5.0-stable"
    implementation "org.jmonkeyengine:jme3-desktop:3.5.0-stable"
    implementation "org.jmonkeyengine:jme3-lwjgl3:3.5.0-stable"
    implementation 'org.lwjgl:lwjgl3:3.3.1-SNAPSHOT'
}```

You can try the following… I use this to override the dependency between jme-nifty and its Nifty.

configurations.all {
    resolutionStrategy.dependencySubstitution {
        substitute module('com.github.nifty-gui:nifty') with module('com.github.tonihele.nifty-gui:nifty:1.4-SNAPSHOT')
        substitute module('com.github.nifty-gui:nifty-default-controls') with module('com.github.tonihele.nifty-gui:nifty-default-controls:1.4-SNAPSHOT')
        substitute module('com.github.nifty-gui:nifty-style-black') with module('com.github.tonihele.nifty-gui:nifty-style-black:1.4-SNAPSHOT')
    }
}

You might confirm that this actually worked by looking in ~/.m2/repository. For most projects, I think of “gradle install” when I think “push to maven local”… but either way, looking in your local maven repo will tell you if it succeeded.

That can help narrow down where the disconnect is.

1 Like

Thank you for your help, but I am still stuck. I’ve tried two approaches, one is to compile lwjgl3 myself from the master branch, I’ve tagged this version as 3.3.1c-SNAPSHOT to avoid confusion. The other is to consume the 3.3.1-SNAPSHOT that is available in the repository https://oss.sonatype.org/content/repositories/snapshots/.

When I compile lwjgl3 myself, I look in my ~/.m2 repo and see the bom for 3.3.1c-SNAPSHOT present.

treemark@Marks-Mac-mini lwjgl3 % ./gradlew clean build publishToMavenLocal
treemark@Marks-Mac-mini lwjgl3 % find ~/.m2 | grep 3.3.1c
/Users/treemark/.m2/repository/org/lwjgl/lwjgl-bom/3.3.1c-SNAPSHOT
/Users/treemark/.m2/repository/org/lwjgl/lwjgl-bom/3.3.1c-SNAPSHOT/lwjgl-bom-3.3.1c-SNAPSHOT.pom
/Users/treemark/.m2/repository/org/lwjgl/lwjgl-bom/3.3.1c-SNAPSHOT/maven-metadata-local.xml
/Users/treemark/.m2/repository/org/lwjgl/lwjgl-bom/3.3.1c-SNAPSHOT/lwjgl-bom-3.3.1c-SNAPSHOT.module

In my minimal consuming project my build.gradle file looks like this.

repositories {
    mavenLocal()
    mavenCentral()
    maven { url "https://oss.sonatype.org/content/repositories/snapshots/" }
}



dependencies {
    implementation platform("org.lwjgl:lwjgl-bom:3.3.1c-SNAPSHOT")
    implementation "org.jmonkeyengine:jme3-core:3.5.0-stable"
    implementation "org.jmonkeyengine:jme3-desktop:3.5.0-stable"
    implementation "org.jmonkeyengine:jme3-lwjgl3:3.5.0-stable"
}

In this configuration I still get failures to resolve all the individual native libraries, but it succeeds in seeing the lwjgl-bom.

runtimeClasspath - Runtime classpath of source set 'main'.
+--- org.lwjgl:lwjgl-bom:3.3.1c-SNAPSHOT
|    +--- org.lwjgl:lwjgl:3.3.1c-SNAPSHOT FAILED
|    +--- org.lwjgl:lwjgl-glfw:3.3.1c-SNAPSHOT FAILED
|    +--- org.lwjgl:lwjgl-jemalloc:3.3.1c-SNAPSHOT FAILED
|    +--- org.lwjgl:lwjgl-openal:3.3.1c-SNAPSHOT FAILED
|    +--- org.lwjgl:lwjgl-opencl:3.3.1c-SNAPSHOT FAILED
|    \--- org.lwjgl:lwjgl-opengl:3.3.1c-SNAPSHOT FAILED
+--- org.jmonkeyengine:jme3-core:3.5.0-stable
+--- org.jmonkeyengine:jme3-desktop:3.5.0-stable
|    \--- org.jmonkeyengine:jme3-core:3.5.0-stable
\--- org.jmonkeyengine:jme3-lwjgl3:3.5.0-stable
     +--- org.jmonkeyengine:jme3-core:3.5.0-stable
     +--- org.jmonkeyengine:jme3-desktop:3.5.0-stable (*)
     +--- org.lwjgl:lwjgl:3.3.0 -> 3.3.1c-SNAPSHOT FAILED
     +--- org.lwjgl:lwjgl-glfw:3.3.0 -> 3.3.1c-SNAPSHOT FAILED
     +--- org.lwjgl:lwjgl-jemalloc:3.3.0 -> 3.3.1c-SNAPSHOT FAILED
     +--- org.lwjgl:lwjgl-openal:3.3.0 -> 3.3.1c-SNAPSHOT FAILED
     +--- org.lwjgl:lwjgl-opencl:3.3.0 -> 3.3.1c-SNAPSHOT FAILED
     \--- org.lwjgl:lwjgl-opengl:3.3.0 -> 3.3.1c-SNAPSHOT FAILED

The other way I tried was just to include 3.3.1-SNAPSHOT from lwjgl3’s maven repo… this does seem to pick up all the required transient dependencies correctly.


compileClasspath - Compile classpath for source set 'main'.
+--- org.lwjgl:lwjgl-bom:3.3.1-SNAPSHOT
|    +--- org.lwjgl:lwjgl:3.3.1-SNAPSHOT (c)
|    +--- org.lwjgl:lwjgl-glfw:3.3.1-SNAPSHOT (c)
|    +--- org.lwjgl:lwjgl-jemalloc:3.3.1-SNAPSHOT (c)
|    +--- org.lwjgl:lwjgl-openal:3.3.1-SNAPSHOT (c)
|    +--- org.lwjgl:lwjgl-opencl:3.3.1-SNAPSHOT (c)
|    \--- org.lwjgl:lwjgl-opengl:3.3.1-SNAPSHOT (c)
+--- org.jmonkeyengine:jme3-core:3.5.0-stable
+--- org.jmonkeyengine:jme3-desktop:3.5.0-stable
|    \--- org.jmonkeyengine:jme3-core:3.5.0-stable
\--- org.jmonkeyengine:jme3-lwjgl3:3.5.0-stable
     +--- org.jmonkeyengine:jme3-core:3.5.0-stable
     +--- org.jmonkeyengine:jme3-desktop:3.5.0-stable (*)
     +--- org.lwjgl:lwjgl:3.3.0 -> 3.3.1-SNAPSHOT
     +--- org.lwjgl:lwjgl-glfw:3.3.0 -> 3.3.1-SNAPSHOT
     |    \--- org.lwjgl:lwjgl:3.3.1-SNAPSHOT
     +--- org.lwjgl:lwjgl-jemalloc:3.3.0 -> 3.3.1-SNAPSHOT
     |    \--- org.lwjgl:lwjgl:3.3.1-SNAPSHOT
     +--- org.lwjgl:lwjgl-openal:3.3.0 -> 3.3.1-SNAPSHOT
     |    \--- org.lwjgl:lwjgl:3.3.1-SNAPSHOT
     +--- org.lwjgl:lwjgl-opencl:3.3.0 -> 3.3.1-SNAPSHOT
     |    \--- org.lwjgl:lwjgl:3.3.1-SNAPSHOT
     \--- org.lwjgl:lwjgl-opengl:3.3.0 -> 3.3.1-SNAPSHOT
          \--- org.lwjgl:lwjgl:3.3.1-SNAPSHOT

It also compiles correctly, but at runtime it fails with:

java.lang.UnsatisfiedLinkError: Failed to locate library: liblwjgl.dylib
	at org.lwjgl.system.Library.loadSystem(Library.java:164)
	at org.lwjgl.system.Library.loadSystem(Library.java:63)
	at org.lwjgl.system.Library.<clinit>(Library.java:51)
	at org.lwjgl.system.MemoryUtil.<clinit>(MemoryUtil.java:100)
	at org.lwjgl.system.Pointer$Default.<clinit>(Pointer.java:67)
	at org.lwjgl.system.Callback.<clinit>(Callback.java:40)
	at com.jme3.system.lwjgl.LwjglWindow.createContext(LwjglWindow.java:195)
	at com.jme3.system.lwjgl.LwjglWindow.initInThread(LwjglWindow.java:529)
	at com.jme3.system.lwjgl.LwjglWindow.run(LwjglWindow.java:662)
	at com.jme3.system.lwjgl.LwjglWindow.create(LwjglWindow.java:493)
	at com.jme3.app.LegacyApplication.start(LegacyApplication.java:490)
	at com.jme3.app.LegacyApplication.start(LegacyApplication.java:442)
	at com.jme3.app.SimpleApplication.start(SimpleApplication.java:126)
	at com.appliedvillainy.jme.Main.main(Main.java:26)

Mac OS Arm64 natives added recently in this commit

which is not included in the JME 3.5.0-stable release I think. You should build it from the master branch.

1 Like

my config looks like this:

import org.gradle.internal.os.OperatingSystem

dependencies {
    implementation "${jme3.g}:jme3-desktop:${jme3.v}"
    implementation "${jme3.g}:jme3-plugins:${jme3.v}"
    implementation "${jme3.g}:jme3-effects:${jme3.v}"
    implementation("${jme3.g}:jme3-lwjgl3:${jme3.v}"){
        exclude group: 'org.lwjgl'
    }

    def arch = ""
    if (System.getProperty("os.arch") == "aarch64") {
        arch = "-arm64"
    }

    def os = ""
    if (OperatingSystem.current().isLinux()) {
        os = "linux"
    } else if (OperatingSystem.current().isMacOsX()) {
        os = "macos"
    } else if (OperatingSystem.current().isWindows()) {
        os = "windows"
    }
    def lwjgl = "3.3.1-SNAPSHOT"
    def lwjglNative = "natives-${os}${arch}"

    implementation "org.lwjgl:lwjgl:${lwjgl}:${lwjglNative}"
    implementation "org.lwjgl:lwjgl-opencl:${lwjgl}"
    implementation "org.lwjgl:lwjgl-glfw:${lwjgl}"
    implementation "org.lwjgl:lwjgl-glfw:${lwjgl}:${lwjglNative}"
    implementation "org.lwjgl:lwjgl-jemalloc:${lwjgl}"
    implementation "org.lwjgl:lwjgl-jemalloc:${lwjgl}:${lwjglNative}"
    implementation "org.lwjgl:lwjgl-opengl:${lwjgl}"
    implementation "org.lwjgl:lwjgl-opengl:${lwjgl}:${lwjglNative}"
    implementation "org.lwjgl:lwjgl-openal:${lwjgl}"
    implementation "org.lwjgl:lwjgl-openal:${lwjgl}:${lwjglNative}"
}

Ok, I’m closer now. By updating jme’s build file to utilize lwjgl 3.3.1-SNAPSHOT and then including the following in my game project’s build file I got the hello world blue cube to appear.

implementation "org.jmonkeyengine:jme3-lwjgl3:3.6.1-SNAPSHOT"

The only hold up now is that it still won’t execute off the main thread. I’ve tried adding

org.lwjgl.system.Configuration.GLFW_LIBRARY_NAME.set("libglfw_async.dylib");

to my static main method, but that doesn’t seem to help either. Can someone explain how you get GLFW to utilize the new mac os m1 async library?

LWJGL 3.3.1 has just been released.

6 Likes

It would be nice if an async version of GLFW (libglfw_async) is added for Linux as well.

1 Like