I want to cross compile cpython for Android, I used the script provided in this github link.
Download the source code of cpython version 2.7.18 and place it in the same directory as the script
Run the script using this command:
python3 py4android.py --api 21 --version 2.7.18 armeabi-v7a arm64-v8a x86 x86_64
Everything goes as expected and generates a python2.7.a static library for each architecture. Then I add this library to the Android Studio project:
-jniLibs
-libs
-armeabi-v7a
-python2.7.a
-arm64-v8a
-python2.7.a
-x86
-python2.7.a
-x86_64
-python2.7.a
-include
-many .h files
CMakeLists.txt:
#...
include_directories(/home/xx/AndroidStudioProjects/ProTest/app/src/main/jniLibs/include)
# Link to final library
target_link_libraries( # Specifies the target library.
protest
# Links the target library to the log library
# included in the NDK.
${log-lib}
/home/xx/AndroidStudioProjects/ProTest/app/src/main/jniLibs/libs/${ANDROID_ABI}/libpython2.7.a
)
native-lib.cpp
#include<Python.h>
//...
extern "C"
JNIEXPORT void JNICALL
Java_com_xx_protest_MainActivity_python_test(JNIEnv *env, jobject thiz) {
Py_SetProgramName("fist_sc"); /* optional but recommended */
Py_Initialize();
PyRun_SimpleString("from time import time,ctime\n"
"print 'Today is',ctime(time())\n");
Py_Finalize();
}
When I compile the code it doesn't compile, seeing:
C/C++: ld: error: too many errors emitted, stopping now (use -error-limit=0 to see all errors)
error details:
for each platform it says (I just posted here the error for armeabi-v7a only) :
C/C++: ld: error: relocation R_ARM_REL32 cannot be used against symbol 'Py_InteractiveFlag'; recompile with -fPIC
C/C++: ld: error: relocation R_ARM_REL32 cannot be used against symbol 'Py_InteractiveFlag'; recompile with -fPIC
C/C++: ld: error: relocation R_ARM_REL32 cannot be used against symbol 'Py_InspectFlag'; recompile with -fPIC
C/C++: ld: error: relocation R_ARM_REL32 cannot be used against symbol 'PyNullImporter_Type'; recompile with -fPIC
C/C++: ld: error: relocation R_ARM_REL32 cannot be used against symbol 'PyNullImporter_Type'; recompile with -fPIC
C/C++: ld: error: relocation R_ARM_REL32 cannot be used against symbol 'PyNullImporter_Type'; recompile with -fPIC
C/C++: ld: error: relocation R_ARM_REL32 cannot be used against symbol 'PyNullImporter_Type'; recompile with -fPIC
C/C++: ld: error: relocation R_ARM_REL32 cannot be used against symbol 'PyString_Type'; recompile with -fPIC
C/C++: ld: error: relocation R_ARM_REL32 cannot be used against symbol 'PyString_Type'; recompile with -fPIC
C/C++: ld: error: relocation R_ARM_REL32 cannot be used against symbol 'PyString_Type'; recompile with -fPIC
C/C++: ld: error: relocation R_ARM_REL32 cannot be used against symbol 'PyString_Type'; recompile with -fPIC
C/C++: ld: error: relocation R_ARM_REL32 cannot be used against symbol 'PyString_Type'; recompile with -fPIC
C/C++: ld: error: relocation R_ARM_REL32 cannot be used against symbol 'PyString_Type'; recompile with -fPIC
C/C++: ld: error: relocation R_ARM_REL32 cannot be used against symbol 'PyString_Type'; recompile with -fPIC
C/C++: ld: error: relocation R_ARM_REL32 cannot be used against symbol 'PyString_Type'; recompile with -fPIC
C/C++: ld: error: relocation R_ARM_REL32 cannot be used against symbol 'PyString_Type'; recompile with -fPIC
C/C++: ld: error: relocation R_ARM_REL32 cannot be used against symbol 'PyString_Type'; recompile with -fPIC
C/C++: ld: error: relocation R_ARM_REL32 cannot be used against symbol 'PyString_Type'; recompile with -fPIC
C/C++: ld: error: relocation R_ARM_REL32 cannot be used against symbol 'PyString_Type'; recompile with -fPIC
C/C++: ld: error: relocation R_ARM_REL32 cannot be used against symbol 'PyBaseString_Type'; recompile with -fPIC
C/C++: ld: error: too many errors emitted, stopping now (use -error-limit=0 to see all errors)
C/C++: clang++: error: linker command failed with exit code 1 (use -v to see invocation)
I did as the error message suggests by compiling a shared library passing --enable-shared to the configure script. It generates in this case two shared libraries for each platform python2.7.so and python.2.7.so.1.0. I include both in the android studio project and recompile the project, it compiles successfully in this case, but it fails when I run it on my device with this error:
E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.abdo.mypy, PID: 24662
java.lang.UnsatisfiedLinkError: dlopen failed: library "libpython2.7.so.1.0" not found
at java.lang.Runtime.loadLibrary0(Runtime.java:1071)
at java.lang.Runtime.loadLibrary0(Runtime.java:1007)
at java.lang.System.loadLibrary(System.java:1667)
at com.xx.protest.MainActivity.<clinit>(MainActivity.java:14)
at java.lang.Class.newInstance(Native Method)
at android.app.AppComponentFactory.instantiateActivity(AppComponentFactory.java:95)
at androidx.core.app.CoreComponentFactory.instantiateActivity(CoreComponentFactory.java:45)
at android.app.Instrumentation.newActivity(Instrumentation.java:1251)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3437)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3703)
at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2216)
at android.os.Handler.dispatchMessage(Handler.java:107)
at android.os.Looper.loop(Looper.java:237)
at android.app.ActivityThread.main(ActivityThread.java:7948)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1075)
When I check the final apk, I found that python2.7.so.1.0 is not there, there are only protest.so and python2.7.so libraries, so how also include python2.7.so.1.0 in the final apk to fix the error?