0

I have built python3 with the android-ndk toolchain (llvm prebuilt) and I'm trying to link against my project in android studio. The build finishes without error but when I launch the app I get this error:

28926-28926/com.e.python3 E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.e.python3, PID: 28926
    java.lang.UnsatisfiedLinkError: dlopen failed: library "/home/user/AndroidStudioProjects/Python3/app/src/main/cpp/../jniLibs/x86/libpython3.8.so" not found
        at java.lang.Runtime.loadLibrary0(Runtime.java:1016)
        at java.lang.System.loadLibrary(System.java:1657)
        at com.e.python3.MainActivity.<clinit>(MainActivity.java:12)
...

The other threads I have found on the subject are related to exporting the lib to the apk but in my case the apk has the lib in the lib directory(I can see it through adb or with the apk analyser).

I followed the guide at : https://developer.android.com/studio/projects/configure-cmake

Here is my CMakeLists.txt:

cmake_minimum_required(VERSION 3.4.1)

add_library( # Sets the name of the library.
        native-lib
        SHARED
        native-lib.cpp)

find_library(
        log-lib
        log)

include_directories(
        /home/user/PythonBuild/python390.${CMAKE_ANDROID_ARCH_ABI}/include/python3.8
)

add_library(python3 SHARED IMPORTED)
set_target_properties(python3 PROPERTIES IMPORTED_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/../jniLibs/${CMAKE_ANDROID_ARCH_ABI}/libpython3.8.so)

target_link_libraries(
        native-lib
        python3
        ${log-lib})

And my gradle:

apply plugin: 'com.android.application'

android {
    compileSdkVersion 28
    defaultConfig {
        applicationId "com.e.python3"
        minSdkVersion 23
        targetSdkVersion 28
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
        externalNativeBuild {
            cmake {
                cppFlags ""
            }
        }
        ndk {
            moduleName "jnilib"
        }
    }
    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"
        }
    }
    splits {
        abi {
            enable true
            reset()
            include 'x86_64', 'armeabi-v7a', 'arm64-v8a', 'x86'
            universalApk false
        }
    }

    sourceSets {
        main {
            jniLibs.srcDirs = ['src/main/jniLibs']
        }
    }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'com.android.support:appcompat-v7:28.0.0'
    implementation 'com.android.support.constraint:constraint-layout:1.1.3'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.2'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
}

What's weird is that it tries to open the shared lib with the path from the computer it was built on, not the one of the apk.

2A-66-42
  • 554
  • 1
  • 5
  • 18

1 Answers1

0

I found the answer there: Using a prebuilt shared Library in Android Studio (cmake) thanks to @Michael

I changed the INSTSONAME while compiling python to discard the versioned part of the library (libpython3.8.so.1.0 -> libpython3.8.so). Doing so also discarded the SONAME. Using patchelf I was able to add SONAME and the library is found.

2A-66-42
  • 554
  • 1
  • 5
  • 18