its-happening
its-happening

Reputation: 1

Android Tensorflow Lite C++ .SO libraries not linked on runtime

I'm trying to build Tensorflow lite with C++ natively on Android device. I've built a .So file of tensorflow for every architecture and placed into the jniLibs folder. This is my Cmake file:

set(pathToProject /ih/user/project/NativeTfLite/app)

set(libs ${pathToProject}/src/main/jniLibs)
add_library(libtensorflowLite SHARED IMPORTED
        )
set_target_properties(libtensorflowLite PROPERTIES IMPORTED_LOCATION
        ${libs}/${ANDROID_ABI}/libtensorflowLite.so)

find_library( 
        log-lib
        log )

add_library(
        native-lib
        SHARED
        native-lib.cpp)

target_include_directories(native-lib PRIVATE
        ${lib}/include)

target_link_libraries( # Specifies the target library.
        native-lib.     #Problem is here when linking native-lib with libtensorflowlite
        libtensorflowLite
        ${log-lib} )

During compile time these files are found. However in target_link_libraries line, the linking of the 2 libraries libtensorflowlite and native-lib there is a runtime crash with the following error:

java.lang.UnsatisfiedLinkError: dlopen failed: library "/Users/ih/project/cameraFrames/NativeTfLite/app/src/main/jniLibs/arm64-v8a/libtensorflowLite.so" not found

Additionally the .SO files are not linked to the APK.

Here is my build.gradle file:



apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: 'kotlin-android-extensions'

android {
    compileSdkVersion 29
    buildToolsVersion "29.0.3"

    defaultConfig {
        applicationId "com.proj.nativetflite"
        minSdkVersion 24
        targetSdkVersion 29
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
        sourceSets {
            main {
                jniLibs.srcDir 'src/main/jniLibs'
                jniLibs.srcDirs = ["src/main/jniLibs"]
            }
        }
        externalNativeBuild {
            cmake {
                cppFlags "-std=c++11"
                arguments '-DCMAKE_VERBOSE_MAKEFILE=ON'
            }
        }
        ndk {
            abiFilters  "armeabi-v7a", "x86" , "arm64-v8a"
        }
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }

    externalNativeBuild {
        cmake {
            path "src/main/cpp/CMakeLists.txt"
            version "3.10.2"
        }
    }
}

dependencies {
    implementation fileTree(dir: 'jniLibs', include:  '**/*.so')

    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
    implementation 'androidx.appcompat:appcompat:1.1.0'
    implementation 'androidx.core:core-ktx:1.2.0'
    implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'androidx.test.ext:junit:1.1.1'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
}

What is causing this?

Upvotes: 0

Views: 1292

Answers (2)

klearning
klearning

Reputation: 1

Although I think Dan Albert's answer should be accepted, I'd like to add that I got the exact same error because I had not set the correct path to my tflite lib.

I kept my .so files in src/main/cpp/tflite/lib/${ANDROID_ABI}/, so in build.gradle I needed to add:

main {
    jniLibs.srcDirs = ['src/main/cpp/tflite/lib']
}

also, it could be worth checking out this answer (also from Dan) regarding making sure the SONAME of the .so is correct.

Upvotes: 0

Dan Albert
Dan Albert

Reputation: 10509

Prior to AGP 4.0 you need to explicitly package prebuilt libraries with jniLibs: https://developer.android.com/studio/projects/gradle-external-native-builds#jniLibs. Note that the docs say you don't need to do this for anything declared by CMake, but I'm fairly certain the docs are wrong here (I've reached out to the doc owner to see if we need to fix that or not, since it is correct for 4.0).

This should be unnecessary in 4.0, but that hasn't reached stable yet.

Upvotes: 0

Related Questions