gpu / JOCL

Java bindings for OpenCL
http://www.jocl.org
Other
187 stars 33 forks source link

Fix build for Android Studio and older jni.h versions #44

Closed starcatter closed 2 years ago

starcatter commented 2 years ago

Older releases of JNI, particularily the one that ships with the Android SDK, feature an incompatible signature for JNIInvokeInterface::AttachCurrentThread(), which expects the type JNIEnv rather than the void present in later revisions. This pull request handles this incompatibility by detecting whether JNI_VERSION_1_8 is defined (the oldest revision I found that had updated method signatures) and casts the parameter accordingly. Additionally I updated C-style casts of JNIEnv to void with reinterpret_cast, because the version of Clang Android Studio uses complains about that. The goal here is to get the native part of JOCL to build in Android studio, which greatly simplifies building for Android - just add JOCL's native sources and CMake files to an Android Studio "native" project and it will take care of building it and including the libraries within the apk file.

gpu commented 2 years ago

From a short look at the code chages, they look reasonable to me. I'll try to allocate some time for testing the build on Windows, and probably merge it soon.

starcatter commented 2 years ago

Thanks for looking into this.

starcatter commented 2 years ago

Hi, have you tested my changes?

I'll be doing a presentation on OpenCL on Android this Wednesday, it would be easier if I could just point to this repo.

No rush though, I can just point to my branch if it's not accepted by then.

gpu commented 2 years ago

Apologies for the delay here. This was a small (but important) and reasonable change. Testing and merging this should not have taken as long as it did.

(It had totally been pushed down my stack of 'todos' ... besides... you cannot imagine how many distracting notifications I receive because people are using the annotation "@gpu" in the code and commits of random projects 😆)

Thanks for the contribution!

starcatter commented 2 years ago

Great, thanks!

Here's what I prepared for the presentation: https://github.com/starcatter/OCL-JOCL/commits/master The commits are supposed to be a step-by-step guide to using JOCL on Android. And then a bunch of examples.

In a nutshell:

  1. Setup native project
  2. clone JOCL and JOCLCommon repos inside the native code dir
  3. add a add_subdirectory command to CMakeLists.txt to include JOCL
  4. add JOCL dependency to gradle

And that's it, now you can use OpenCL on Android without having to wrestle with C++ and JNI.

gpu commented 2 years ago

Thanks for the pointer. I had a short (!) look at the code, and can imagine that it will be helpful for people who want to use OpenCL on Android. (You might consider adding a README.md, basically containing the information/bullet points from your post above - this could make it even easier for people to actually try it out).

A few anecdotes:

I created a special version of JOCL more than 10 years ago, for an early prototype of an Android device that actually supported OpenCL back then. I think that OpenCL support from the hardware/driver side is more commonplace nowadays.

(But I also have to admit that I'm not really up to date with OpenCL. There are too many other tasks right now. I don't know whether I'll ever be able to update JOCL to OpenCL 3.0...).

And ideally, people should not have to compile the native libraries on their own. It would be great if the native library for Android could be part of the JOCL JAR file that is available in Maven Central. Then, people could just add the JOCL dependency to their Maven/Gradle build, and be done.

(But I don't know how many different versions of the library would be needed then - probably multiple ones, for the different architectures...).

An unrelated aside: There still is https://github.com/gpu/JOCL/pull/16 (5 years old...), and I don't know what to do with that. Considering that you now set up a project on Android, I assume that the other PR is obsolte and could be closed. But some questions in that PR also had been related to the different possible arch strings that may exist for Android devices...

starcatter commented 2 years ago

TBH I don't know much about bundling JARs, but if it's enough to just include the libs JOCL needs on different platforms, then you could use Android Studio to build them for all Android ABIs - set build to release mode, generate an apk file, and grab the libraries from there. By default it builds all ABIs and to me it's by far easier than cross-compiling manually.

gpu commented 2 years ago

Generally, yes: The native files (.dll/.so...) are put into the JAR file. When the JAR file is loaded, JOCL will unpack the native library into the "temp" directory, and load it from there. That sounds clumsy. It is clumsy. But it is 'the way to go'. Quite a bit of work went into the LibUtils class to make this work smoothly.

One technical question is: How does Java know which of the native libraries has to be upacked and loaded? This depends on the operating system (Windows/Mac/Linux/Android...) and on the architecture (x86, ARM...).

All this is figured out based on the ArchType in LibUtils right now. Iff the libraries for Android can currently be loaded automatically, then it seems to cover everything that is needed (at least for your environment).

(I assume that you are not manually loading the library - i.e. that you don't do a manual System.loadLibrary somewhere - is that correct?)

starcatter commented 2 years ago

Yes, JOCL finds the proper library to load.

If built as a part of the project, the libraries are placed in the .apk file in a place the application can find them, also AFAIK the directory for the current ABI is added to library loading path. image From what I can see here, the x86 and x86_64 libraries (for Android running on Atom tablets etc) are not built with proper names, but I think these would work regardless, due to proper library path being selected anyway.

That would probably need to be fixed for this stuff to work in a .jar file though.