1
votes

I want to use OpenCL in Android Studio,

I grabbed libOpenCL.so from my android device device and put it in jniLibs/[ABI]/

I put header files to jni/CL/

EDIT :

I switched to gradle-experimental:0.6.0-alpha7 and it bought some other problems, I replaced the first part with this:

repositories {
    libs(PrebuiltLibraries) {
        OpenCL {
            headers.srcDir "src/main/jni/CL"
            binaries.withType(SharedLibraryBinary) {
                sharedLibraryFile = file("src/main/jniLibs/${targetPlatform.getName()}/libOpenCL.so")
            }
        }
    }
}
android.sources {
    main {
        jni {
            dependencies {
                library "OpenCL" linkage "shared"
            }
        }
    }
}

Now it gives these errors:

C:\Users\Umut\Desktop\HelloJNI\app\src\main\jniLibs\arm64-v8a\libOpenCL.so: error adding symbols: File in wrong format

Error:error: ld returned 1 exit status

Error:Execution failed for task ':app:linkHello-jniArm64-v8aDebugAllSharedLibrary'. A build operation failed. Linker failed while linking libhello-jni.so.

What does "file in wrong format" can even mean? I took the library directly from my android phone.

Can, anybody please help me on what I have done wrong or what should I do to fix this problem?

As I am new to android development and gradle, please apologize me if I have misunderstood something.

.

PREVIOUS ATTEMPT WITH GRADLE EXPERIMENTAL 0.4.0

When using gradle-experimental:0.4.0 and I put this to my build.gradle file:

android.sources {
    main {
        jniLibs {
            dependencies {
                library file("src/main/jniLibs/armeabi-v7a/libOpenCL.so") abi "armeabi-v7a"
                library file("src/main/jniLibs/armeabi/libOpenCL.so") abi "armeabi"
                library file("src/main/jniLibs/x86/libOpenCL.so") abi "x86"
            }
        }
    }
}

Here is my ndk block in build.gradle:

android.ndk {
    moduleName = "openCLJni"
    cppFlags.addAll(["-I${file("src/main/jniLibs/")}".toString()])
    ldLibs.addAll(["android", "log"])
    stl = "stlport_static"
}

I try to make a very simple function call from my openCLJni.c :

jstring
Java_com_example_hellojni_HelloJni_stringFromJNI( JNIEnv* env,
                                              jobject thiz )
{
    cl_uint ret_num_platforms;
    cl_platform_id platform_id = NULL;
    cl_int ret = clGetPlatformIDs(1, &platform_id, &ret_num_platforms);
    return (*env)->NewStringUTF(env, "Hello from JNI");
}

Yet it gives me this error:

Error:(65) undefined reference to `clGetPlatformIDs'

and

Error:Execution failed for task ':app:linkArm64-v8aDebugAllHello-jniSharedLibrary'.

A build operation failed. Linker failed while linking libhello-jni.so. See the complete log at: file:///C:/Users/Umut/Desktop/OpenCLTest2/app/build/tmp/linkArm64-v8aDebugAllHello-jniSharedLibrary/output.txt

2
Seems like error points you in right direction. You must add a shared library to link clGetPlatformIDs() function. I use NDK_BUILD (not gradle) to do this, and it works as described here: developer.android.com/ndk/guides/prebuilts.html - Tomasz Jarosik
I guess you should add the library here: ldLibs.addAll(["android", "log"]) where android refers to libandroid.so and log refers to liblog.so for your #include <android/log.h> stuff. You have already setup the include paths for headers, but didn't tell the linker anything about clGetPlatformIDs - Gábor Buella
Thanks for answer, but when I try to add opencl to there like this: ldLibs.addAll(["android", "log", "OpenCL"]) it gives me this error: C:/Users/MYNAME/AppData/Local/Android/sdk/ndk-bundle/toolchains/aarch64-linux-android-4.9/prebuilt/windows-x86_64/bin/../lib/gcc/aarch64-linux-android/4.9/../../../../aarch64-linux-android/bin/ld.exe: cannot find -lOpenCL - Umut Ulutas

2 Answers

0
votes

Had the same problem and I managed to solve it:

The library is built for a certain architecture and if you do not add an abiFilter in your gradle build then it will try to compile and use the library for all available architectures for most of which the library is incompatible hence you get file in wrong format error.

The solution is to simply add an abiFilter for the architecture from which you got the library from. I got the library from a Galaxy Note 5. I added an abiFilter for "armeabi" in gradle build and it worked. The same file also worked with "armeabi-v7a" architecture.

I also noticed that there are several versions of the library which you can pull with ADB. I found and pulled the libGLES_mali.so which is also the OpenCL Mali library from the "/system/vendor/lib64/egl" and was able to run OpenCL with "arm64-v8a" architecture which runs faster.

You should just pull and add the correct library for the architecture you want to support in the correct architecture library folder and create flavors in gradle with abiFilters matching the library's architecture.

Here is my gradle build file using gradle experimental 0.7.0:

apply plugin: 'com.android.model.application'


model {

    repositories {
        libs(PrebuiltLibraries) {

            OpenCL {
                headers.srcDir "src/main/jniLibs/include/CL"
                binaries.withType(SharedLibraryBinary) {
                    sharedLibraryFile = file("src/main/jniLibs/${targetPlatform.getName()}/libGLES_mali.so")
                }
            }
        }
    }

    android {
        compileSdkVersion 23
        buildToolsVersion "23.0.3"

        defaultConfig {
            applicationId "com.apps.opencl_app"
            minSdkVersion.apiLevel 15
            targetSdkVersion.apiLevel 23
            versionCode 1
            versionName "1.0"
        }
        buildTypes {
            release {
                minifyEnabled false
                proguardFiles.add(file('proguard-android.txt'))
            }
        }

        ndk {


            moduleName = "sr_native"
            CFlags.add("-I${file("src/main/jniLibs/include/CL")}".toString())
            cppFlags.add("-I${file("src/main/jniLibs/include/CL")}".toString())
            ldLibs.addAll(["log"])
            abiFilters.add("arm64-v8a")


        }

        sources {

            main {
                jni {
                    dependencies {
                        library "OpenCL" linkage "shared"
                    }
                }

            }
        }

    }
}


dependencies {
    compile fileTree(dir: 'libs', include: ['*.jar'])
    compile 'com.android.support:appcompat-v7:23.4.0'
}
0
votes

For modern systems you should use

adb pull /system/vendor/lib64/libOpenCL.so

For the present time most of the tutorials will tell you to grab the library using

adb pull /system/vendor/lib/libOpenCL.so

and it will work but that library is for 32bit systems I guess.