[Bug] LWJGL crashes on some devices

Started by Zoe, December 18, 2017, 19:29:03

Previous topic - Next topic

Zoe

This question is related to the Android port of LWJGL

So I tried installing a game of mine on my tablet. I got an error ([this thing](https://stackoverflow.com/questions/24572052/install-failed-no-matching-abis-when-install-apk)). I added some code in build.gradle to bypass that and install it anyways.

Obviously, the error itself is clear: Missing natives. I bypassed it at the time because I thought it was a mistake

I bypass it and essentially force an install. On running it, it crashes:

    java.lang.UnsatisfiedLinkError: Failed to locate library: liblwjgl.so

The only part in my code the stacktrace points to is this line:

    GLES.createCapabilities();

Then it goes into LWJGL with expected calls from there.

I also tried reproducing this with the `android-test` repo to check if it's an error with my code or if it's an LWJGL issue. I reproduced it there too. And I created a third project and added that single line (along with a GLSurfaceView and the accompanying renderer of course).

I have two devices (a Samsung S6 edge and a NVIDIA shield tablet) for testing. Installing and running on my phone works like a charm. Attempting to install on the tablet fails (and when the install fail is bypassed) crashes.

Went ahead and downloaded the AnTuTu benchmark app (for the info). These two devices are very similar: same OS version, OpenGL ES version, etc. Obviously, screen size, and in general the screen hardware is different (obviously). None of the expected differences matter though. One difference is 32 vs 64 bit, but running on a 32 bit device works fine. The only remaining difference is the processor. My phone is x86 while my tablet is ARM.

Does LWJGL not support ARM Android devices?

spasi

You must build LWJGL for ARM/Android manually. The instructions are in the android-test repository for now. Both arm64-v8a and armeabi-v7a architectures have been tested and should work.

Zoe

The only part with the different processor architectures I see in the android-test repo are the vulkan validation layers (I'm not using Vulkan btw).

I cloned the lwjgl3 repo, followed the instructions (checkout android, build with ant and copy the aar file). I re-compiled it to check if I had done it wrong, still the same issue. (I didn't download the desktop jars. Built it manually in the first place)


Zoe

Re-cloned the LWJGL3 repo, and re-compiled the lwjgl.aar file (for the 3rd time or so). Still can't get it to run on ARM devices.

It doesn't want to install because it can't find the natives. Forcing the install:

    splits {
        abi {
            enable true
            reset()
            include 'x86', 'armeabi-v7a'
            universalApk true
        }
    }

installs it but crashes on boot because it can't find the native lib

spasi

Sounds like it's trying to load the 64bit natives. Try an arm64-v8a build instead of armeabi-v7a. If it still fails, run your application with -Dorg.lwjgl.util.Debug=true and -Dorg.lwjgl.util.DebugLoader=true and post the output here.

Zoe

Trying to boot an emulator, encountering some issues so it may take a while. I'll let you know how it goes.

But I doubt there's any way to pass arguments because there's no way to retrieve them with the Activity lifecycle. There's simply no main method to intercept the arguments in. It would be possible to pass extras through a Bundle, but I don't see how LWJGL would intercept that. <a href="https://stackoverflow.com/questions/20197242/android-native-application-command-line-arguments">Related</a>


spasi

You can do it programmatically using the org.lwjgl.system.Configuration class. Set Configuration.DEBUG and Configuration.DEBUG_LOADER to true before doing anything else with LWJGL.

Zoe

Waiting for the ARM 64 emulator to come online (it's incredibly slow even with 4 gigs of RAM). Launched the app on my tablet again with the flags enabled. The output:

2-20 18:31:50.255 15618-15635/? W/System.err: [LWJGL] Version: 3.1.2 SNAPSHOT
12-20 18:31:50.255 15618-15635/? W/System.err: [LWJGL]     OS: Linux v3.10.96+
12-20 18:31:50.255 15618-15635/? W/System.err: [LWJGL]    JRE: 0 armv7l
12-20 18:31:50.255 15618-15635/? W/System.err: [LWJGL]    JVM: Dalvik v2.1.0 by The Android Project
12-20 18:31:50.255 15618-15635/? W/System.err: [LWJGL] Loading library (system): lwjgl
12-20 18:31:50.258 15618-15635/? W/System.err: [LWJGL]    liblwjgl.so not found in java.library.path
12-20 18:31:50.258 15618-15635/? W/System.err: [LWJGL] Failed to load a library. Possible solutions:
12-20 18:31:50.258 15618-15635/? W/System.err:    a) Add the directory that contains the shared library to -Djava.library.path or -Dorg.lwjgl.librarypath.
12-20 18:31:50.258 15618-15635/? W/System.err:    b) Add the JAR that contains the shared library to the classpath.
12-20 18:31:50.264 15618-15635/? E/AndroidRuntime: FATAL EXCEPTION: GLThread 4932
                                                   Process: com.example.mygame, PID: 15618
                                                   java.lang.UnsatisfiedLinkError: Failed to locate library: liblwjgl.so
                                                       at org.lwjgl.system.Library.loadSystem(Library.java:145)
                                                       at org.lwjgl.system.Library.loadSystem(Library.java:65)
                                                       at org.lwjgl.system.Library.<clinit>(Library.java:48)
                                                       at org.lwjgl.system.Library.loadSystem(Library.java:87)
                                                       at org.lwjgl.opengles.GLES.<clinit>(GLES.java:60)
                                                       at com.example.mygame.engine.SRenderer.onSurfaceCreated(SRenderer.java:34)
                                                       at android.opengl.GLSurfaceView$GLThread.guardedRun(GLSurfaceView.java:1521)
                                                       at android.opengl.GLSurfaceView$GLThread.run(GLSurfaceView.java:1253)

spasi

Actually, you might have a better luck on the Samsung S6. The Shield tablet does not support arm64-v8a. Both devices should run an armeabi-v7a build, assuming you did everything correctly. I'm afraid the output above is not helpful. Have you verified that liblwjgl.so is included in the application package?

Zoe

It's properly compiled into the APK when debugging on my S6 edge. I can try building a release APK and install that to see if it still crashes (and check whether or not it's present). Could be a debug flavor issue as well

Zoe

The armeabi-v7a doesn't have the lib folder with the libraries generated from dependencies. The universal APK does though, going to launch it and see if it works.

I have no clue why armeabi-v7a doesn't generate the library folder though. the universal APK only has the arm64-v8a libraries declared.

Attempting to install the app-universal-debug.apk on my phone works fine. Tablet -> Failure [INSTALL_FAILED_NO_MATCHING_ABIS: Failed to extract native libraries, res=-113]

Attempting using the armeabi v7a apk -> installs but crashes

The error is again that it can't find the library, which isn't weird when the library files aren't included in the APK.

Generating a single APK produces the same: arm64-v8a is the only library version included.

Reproduced in the android-test repo as well. None of the other CPU architectures are included in the APK itself.
Opening the aar with 7zip shows that only arm64-v8a is the only library included.
Re-compiled the file and the same result: only arm64 is included. Re-cloned the repo, going to creating it again

Zoe

Still the same issue. The generator only generates arm64-v8a.

spasi

Try setting the LWJGL_BUILD_ARCH environment variable to armeabi-v7a before building LWJGL. By default, the build produces binaries that match the JVM used to run it (i.e. 64bit binaries if the JVM is 64bit, 32bit binaries if the JVM is 32bit).

Zoe

Is there a flag for generating all the Android core archs? Or do they all have to be built manually and separately? Testing now though

spasi

They have to be built separately. Normally we'd have CI for Android binaries and you wouldn't have to bother. Unfortunately, this is the current state of Android support.