Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ensure libpython's standard lib compatibility #8

Open
aaaaalbert opened this issue Jan 31, 2017 · 2 comments
Open

Ensure libpython's standard lib compatibility #8

aaaaalbert opened this issue Jan 31, 2017 · 2 comments

Comments

@aaaaalbert
Copy link
Owner

aaaaalbert commented Jan 31, 2017

We currently build libpython separately and out-of-app through Kivy (see relevant commit 9322af3), extract the shared object, and include that in ./distribution/python27/lib/armeabi-v7a (and the Python headers (also from the Kivy build dir) in ./distribution/python27/include) for the rest of our build process.

At some point in time, it would be nice to be able to build libpython directly from our main Gradle conf; more importantly, we need to ensure today that libpython links against a compatible version of the standard libraries.

The issue is that Android doesn't seem to version its system libraries, but their scope changes significantly between versions. A problem I ran into on Lollipop that involved forkpty seemingly has its roots in this mess --- updating to Nougat "fixed" the problem, in that Nougat's libc provides the call that the pre-built libpython2.7.so that I got from this repo requires.

Thus, when rebuilding libpython, we must test on several Android versions! I don't know if emulation works/makes sense/is efficient in this case, or we just grab another couple of phones that we flash to the various versions. (Dual-boot is not really an option. Third-party images can do it, but require root etc., so we'd be looking at non-stock and thus non-representative firmware afterwards.)


For easier reference, I'll reproduce the error message and a few sources that led me to my conclusions below too. It's well possible that other combinations of build and runtime versions give errors for different standard library calls.

W/linker  ( 7159): libpython2.7.so: unused DT entry: type 0x6ffffffe arg 0x1143c
W/linker  ( 7159): libpython2.7.so: unused DT entry: type 0x6fffffff arg 0x3
E/art     ( 7159): dlopen("/data/app/com.sensibility_testbed-1/lib/arm/libpython2.7.so", RTLD_LAZY) failed: dlopen failed: cannot locate symbol "forkpty" referenced by "libpython2.7.so"...
D/AndroidRuntime( 7159): Shutting down VM
E/AndroidRuntime( 7159): FATAL EXCEPTION: main
E/AndroidRuntime( 7159): Process: com.sensibility_testbed, PID: 7159
E/AndroidRuntime( 7159): java.lang.UnsatisfiedLinkError: dlopen failed: cannot locate symbol "forkpty" referenced by "libpython2.7.so"...
E/AndroidRuntime( 7159): 	at java.lang.Runtime.loadLibrary(Runtime.java:371)
E/AndroidRuntime( 7159): 	at java.lang.System.loadLibrary(System.java:988)
E/AndroidRuntime( 7159): 	at com.snakei.PythonInterpreterService.<clinit>(PythonInterpreterService.java:72)
E/AndroidRuntime( 7159): 	at com.sensibility_testbed.SensibilityActivity$2.onClick(SensibilityActivity.java:203)
E/AndroidRuntime( 7159): 	at android.view.View.performClick(View.java:4780)
E/AndroidRuntime( 7159): 	at android.view.View$PerformClick.run(View.java:19866)
E/AndroidRuntime( 7159): 	at android.os.Handler.handleCallback(Handler.java:739)
E/AndroidRuntime( 7159): 	at android.os.Handler.dispatchMessage(Handler.java:95)
E/AndroidRuntime( 7159): 	at android.os.Looper.loop(Looper.java:135)
E/AndroidRuntime( 7159): 	at android.app.ActivityThread.main(ActivityThread.java:5254)
E/AndroidRuntime( 7159): 	at java.lang.reflect.Method.invoke(Native Method)
E/AndroidRuntime( 7159): 	at java.lang.reflect.Method.invoke(Method.java:372)
E/AndroidRuntime( 7159): 	at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
E/AndroidRuntime( 7159): 	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)
W/ActivityManager(  813):   Force finishing activity 1 com.sensibility_testbed/.SensibilityActivity

Hints taken from:

@aaaaalbert
Copy link
Owner Author

For the forkpty call in libc in particular, API level 23 exposes it, whereas 22 doesn't. I haven't (yet?) found another library on 22 that implements forkpty.

@aaaaalbert
Copy link
Owner Author

I've rebuilt libpython2.7.so for API level 21, downgraded the Gradle config too, removed SensibilityActivity.java/onRequestPermissionsResult which isn't compatible with that API level, rebuilt the project, and behold, it works on my LG H420 running Android 5.0.1!

I guess that's a good sign!

Build command (see my Python build instructions):

p4a apk --arch=armeabi-v7a --private=/home/lukas/kivy-app --package=org.example.myapp --name "My app" --version 0.1 --requirements=python2,libffi --sdk_dir=$HOME/Android/Sdk --ndk_dir=$HOME/android-ndk-r13b --android_api=21 --ndk_ver=r13b

TODO: Document that we want backwards compatibility, and figure out how far backwards we can sanely go. Currently, the NDK supports API levels >=21, which covers around 60% of the world's Android population. Other API level pitfalls may lurk about.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant